Browse Source

[TESTS] Start the test suite.

This is still not complete enough, but should be a good starting point
for others to add more tests or request changes by adapting the tests.
develop
Evilham 2 years ago
parent
commit
6de9230bfb
  1. 25
      README.md
  2. 6
      releasebot.py
  3. 0
      tests/__init__.py
  4. 39
      tests/lib.py
  5. 154
      tests/test_gitea.py
  6. 57
      tests/test_helper_classes.py
  7. 35
      tests/test_helper_functions.py

25
README.md

@ -8,14 +8,29 @@ This depends exclusively on following python 3.5+ libraries:
For development you may want to use `pipenv install --dev`.
## WARNING: this is alpha code written for internal use in Devuan,
## Testing
This project uses [unittest][unittest] for testing and is still WIP, please
consider adding more test-cases to the tests module.
To run the tests, use:
python -m unittest
Of special interest are canonical examples of permissions handling and
decision making in ReleaseBot.
[unittest]: https://docs.python.org/3/library/unittest.html
## WARNING: this is beta code written for internal use in Devuan,
do not use it if you don't know what you are doing.
If it will kill your cat, burn your house, cut your fingers or any other damage i will
not responsable for anything.
If it will kill your cat, burn your house, cut your fingers or any other damage
the authors will not responsable for anything.
Devuan Releasebot is a little python script to be launched by cron ( please, do not use
systemd-crond for it, only "normal" crond! ) to autobuild devuan packages by
communicate to both gitea and jenkins.
communicating with both gitea and jenkins.
With the newer architecture it should be plausible to add different repository
sources and build systems like GitLab or buildbot respectively

6
releasebot.py

@ -63,7 +63,7 @@ class ReleaseBotRequester(object):
"""
name = attr.ib(type=str)
is_admin = attr.ib(type=bool)
is_admin = attr.ib(type=bool, default=False)
permissions = attr.ib(factory=list, type=typing.Iterable[str])
@ -77,7 +77,6 @@ class ReleaseBotTask(object):
repo_store = attr.ib(repr=False, type="GenericRepoStore")
command = attr.ib(type=ReleaseBotCommand)
requester = attr.ib(type=ReleaseBotRequester)
message = attr.ib(default="", type=str)
def notify(self, message: str, resolve: bool = False) -> type(None):
"""
@ -201,7 +200,8 @@ class GiteaRepoStore(GenericRepoStore):
# Setup the ReleaseBotRequester with their permissions
requester = ReleaseBotRequester(
name=issue["user"]["username"], is_admin=issue["user"]["is_admin"]
name=issue["user"]["username"],
is_admin=issue["user"].get("is_admin", False),
)
if self.is_packages_member(requester.name):
requester.permissions.append("member")

0
tests/__init__.py

39
tests/lib.py

@ -0,0 +1,39 @@
import attr
from releasebot import GiteaRepoStore
class ConfigMockup(object):
def __init__(self, data=dict()):
self.data = data
def get(self, section, item, fallback=None):
return self.data.get(section, dict()).get(item, fallback)
@attr.s
class ArgsMockup(object):
debug = attr.ib(default=False, type=bool)
dryrun = attr.ib(default=False, type=bool)
class ResponseMockup(object):
def __init__(self, response=dict(), ok=True):
self.response = response
self.ok = ok
def json(self):
return self.response
class GiteaRepoStoreMockup(GiteaRepoStore):
def __init__(self, config, args, responses=dict()):
super().__init__(config, args)
self.responses = responses
def _request(self, method: str, url: str, params: dict = dict()):
return (
self.responses.get(method, dict())
.get(url, dict())
.get(repr(params), ResponseMockup())
)

154
tests/test_gitea.py

@ -0,0 +1,154 @@
import unittest
import typing
import attr
from tests.lib import GiteaRepoStoreMockup, ArgsMockup, ConfigMockup, ResponseMockup
from releasebot import ReleaseBotTask, ReleaseBotCommand, ReleaseBotRequester
# This provides the testing model that we'll provide to our classes
# If you want to add test-cases, make sure you edit responses to match
# this description as well.
tested_open_issues = [
{
"id": 10,
"title": "Build",
"descr": "Not 'pending': not assigned to releasebot",
"repository": {"name": "goodowner", "owner": "devuan",},
"labels": [],
"assignee": {"username": "koala",},
},
{
"id": 11,
"title": "Build",
"descr": "Not 'pending': bad owner",
"repository": {"name": "badstuff", "owner": "badone",},
"labels": [],
"assignee": {"username": "releasebot",},
},
{
"id": 12,
"title": "Build",
"descr": "Is 'pending': but should have no permissions",
"repository": {"name": "stuff", "owner": "devuan",},
"labels": [],
"assignee": {"username": "releasebot",},
"user": {"username": "koala"},
},
{
"id": 13,
"title": "Build",
"descr": "Is 'pending': should be collaborator",
"repository": {"name": "stuff", "owner": "devuan",},
"labels": [],
"assignee": {"username": "releasebot",},
"user": {"username": "colab"},
},
{
"id": 14,
"title": "Build",
"descr": "Is 'pending': should be member",
"repository": {"name": "stuff", "owner": "devuan",},
"labels": [],
"assignee": {"username": "releasebot",},
"user": {"username": "dev1dev"},
},
{
"id": 15,
"title": "Build",
"descr": "Is 'pending': should be admin",
"repository": {"name": "stuff", "owner": "devuan",},
"labels": [],
"assignee": {"username": "releasebot"},
"user": {"username": "toor", "is_admin": True},
},
]
def expected_pending_tasks(repo_store):
return [
ReleaseBotTask(
id="devuan/stuff/issues/12",
command=ReleaseBotCommand(name="build", package="stuff", labels=set()),
requester=ReleaseBotRequester(name="koala", permissions=[]),
repo_store=repo_store,
),
ReleaseBotTask(
id="devuan/stuff/issues/13",
command=ReleaseBotCommand(name="build", package="stuff", labels=set()),
requester=ReleaseBotRequester(
name="colab", permissions=["collaborator/stuff"]
),
repo_store=repo_store,
),
ReleaseBotTask(
id="devuan/stuff/issues/14",
command=ReleaseBotCommand(name="build", package="stuff", labels=set()),
requester=ReleaseBotRequester(name="dev1dev", permissions=["member"]),
repo_store=repo_store,
),
ReleaseBotTask(
id="devuan/stuff/issues/15",
command=ReleaseBotCommand(name="build", package="stuff", labels=set()),
requester=ReleaseBotRequester(name="toor", is_admin=True, permissions=[]),
repo_store=repo_store,
),
]
# This emulates communication to gitea by hard-coding the responses.
# Of special interest is /repos/issues/search, which is defined above.
responses = {
"get": {
# Hard-coded team_id
"/orgs/devuan/teams/search": {
"{'q': 'packages', 'include_desc': False}": ResponseMockup(
response={"data": [{"id": 42}]}
)
},
# colab is collaborator in devuan/stuff, dev1dev and koala aren't
"/repos/devuan/stuff/collaborators/colab": {"{}": ResponseMockup(ok=True),},
"/repos/devuan/stuff/collaborators/dev1dev": {"{}": ResponseMockup(ok=False),},
"/repos/devuan/stuff/collaborators/koala": {"{}": ResponseMockup(ok=False),},
"/repos/devuan/stuff/collaborators/toor": {"{}": ResponseMockup(ok=False),},
"/repos/issues/search": {
"{'state': 'open', 'q': 'build'}": ResponseMockup(
ok=False, response=tested_open_issues
),
},
# dev1dev is member of packages, colab and koala aren't
"/teams/42/members/dev1dev": {"{}": ResponseMockup(ok=True),},
"/teams/42/members/colab": {"{}": ResponseMockup(ok=False),},
"/teams/42/members/koala": {"{}": ResponseMockup(ok=False),},
"/teams/42/members/toor": {"{}": ResponseMockup(ok=False),},
},
}
class TestRepoStores(unittest.TestCase):
def test_gitea_init(self):
self.maxDiff = None
rs = GiteaRepoStoreMockup(ConfigMockup(), ArgsMockup(), responses=responses)
# In our testing this team_id is 42
self.assertEqual(42, rs.packages_team_id)
# colab is a collaborator for package "stuff"
self.assertTrue(rs.is_package_collaborator("colab", "stuff"))
# koala is not
self.assertFalse(rs.is_package_collaborator("koala", "stuff"))
# dev1dev is a member of the packages team
self.assertTrue(rs.is_packages_member("dev1dev"))
# colab and koala are not
for dev in ["colab", "koala"]:
self.assertFalse(
rs.is_packages_member(dev),
"Wrong packages_member status for: {}".format(dev),
)
# Open issues: should be verbatim
open_issues = rs._get_build_issues()
self.assertEqual(tested_open_issues, open_issues)
# Pending tasks: should be filtered by namespace / assignee
pending_tasks = list(rs.get_pending_tasks())
self.assertEqual(expected_pending_tasks(rs), pending_tasks)
# ReleaseBot

57
tests/test_helper_classes.py

@ -0,0 +1,57 @@
import unittest
from tests.lib import ArgsMockup
class TestReleaseBoHelperClasses(unittest.TestCase):
def test_ReleaseBotCommand(self):
from releasebot import ReleaseBotCommand
cmd = ReleaseBotCommand(
name="Name", package="Package", labels=["cool", "stuff"]
)
self.assertEqual("Name", cmd.name)
self.assertEqual("Package", cmd.package)
self.assertEqual(["cool", "stuff"], cmd.labels)
def test_ReleaseBotRequester(self):
from releasebot import ReleaseBotRequester
req = ReleaseBotRequester(name="Name", is_admin=True)
self.assertEqual("Name", req.name)
self.assertEqual(True, req.is_admin)
self.assertEqual([], req.permissions)
req = ReleaseBotRequester(
name="Name2", is_admin=False, permissions=["contributor/Package"]
)
self.assertEqual("Name2", req.name)
self.assertEqual(False, req.is_admin)
self.assertEqual(["contributor/Package"], req.permissions)
def test_ReleaseBotTask(self):
from releasebot import GenericRepoStore, ReleaseBotTask
class RS(GenericRepoStore):
def __init__(self):
self.args = ArgsMockup()
def get_pending_tasks(self):
return []
def do_notify_task(self, task: ReleaseBotTask, message: str, resolve: bool):
self._message = message
self._resolve = resolve
rs = RS()
task = ReleaseBotTask(id="test", command=None, requester=None, repo_store=rs)
message = "Test Message"
task.notify(message)
self.assertEqual(message, rs._message)
self.assertEqual(False, rs._resolve)
rs = RS()
task = ReleaseBotTask(id="test2", command=None, requester=None, repo_store=rs)
message = "Test Message2"
task.notify(message, resolve=True)
self.assertEqual(message, rs._message)
self.assertEqual(True, rs._resolve)

35
tests/test_helper_functions.py

@ -0,0 +1,35 @@
import unittest
import typing
from tests.lib import ConfigMockup
class TestHelperFunctions(unittest.TestCase):
def _list_helper_test_case(
self, value: str, result: typing.Iterable[str], separator: str = ","
):
"""
Helper function to test _list_helper
"""
from releasebot import _list_helper
self.assertEqual(
result,
_list_helper(
ConfigMockup({"section": {"item": value}}), "section", "item", separator
),
)
def test_comma_separated(self):
self._list_helper_test_case("a,b,c", ["a", "b", "c"])
def test_dot_separated(self):
self._list_helper_test_case("a.b.c.d", ["a", "b", "c", "d"], ".")
def test_comma_separated_spaces(self):
self._list_helper_test_case("a , b , c", ["a", "b", "c"])
def test_dot_separated_spaces(self):
self._list_helper_test_case(
"a . b . c . d", ["a", "b", "c", "d"], "."
)
Loading…
Cancel
Save