mirror of
https://github.com/odoo/runbot.git
synced 2025-03-16 07:55:45 +07:00
[IMP] runbot: add basic tests
Deploying non tested code is prone to errors and leads to frustration. With this commit, basic tests are done to avoid such a situation.
This commit is contained in:
parent
84e6be84ad
commit
4ac6a0db98
@ -86,4 +86,3 @@ def get_py_version(build):
|
||||
if f.readline().strip().endswith('python3'):
|
||||
return 'python3'
|
||||
return 'python'
|
||||
|
||||
|
5
runbot/tests/__init__.py
Normal file
5
runbot/tests/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from . import test_repo
|
||||
from . import test_branch
|
||||
from . import test_build
|
||||
from . import test_jobs
|
||||
from . import test_frontend
|
52
runbot/tests/test_branch.py
Normal file
52
runbot/tests/test_branch.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from unittest.mock import patch
|
||||
from odoo.tests import common
|
||||
|
||||
class Test_Branch(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_Branch, self).setUp()
|
||||
Repo = self.env['runbot.repo']
|
||||
self.repo = Repo.create({'name': 'bla@example.com:foo/bar', 'token': '123'})
|
||||
self.Branch = self.env['runbot.branch']
|
||||
|
||||
#mock_patch = patch('odoo.addons.runbot.models.repo.runbot_repo._github', self._github)
|
||||
#mock_patch.start()
|
||||
#self.addCleanup(mock_patch.stop)
|
||||
|
||||
def test_base_fields(self):
|
||||
branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/head/master'
|
||||
})
|
||||
|
||||
self.assertEqual(branch.branch_name, 'master')
|
||||
self.assertEqual(branch.branch_url, 'https://example.com/foo/bar/tree/master')
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
|
||||
def test_pull_request(self, mock_github):
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:bar_branch'},
|
||||
'base' : {'ref': 'master'},
|
||||
}
|
||||
pr = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/pull/12345'
|
||||
})
|
||||
self.assertEqual(pr.branch_name, '12345')
|
||||
self.assertEqual(pr.branch_url, 'https://example.com/foo/bar/pull/12345')
|
||||
self.assertEqual(pr.target_branch_name, 'master')
|
||||
self.assertEqual(pr.pull_head_name, 'foo-dev:bar_branch')
|
||||
|
||||
def test_coverage_in_name(self):
|
||||
"""Test that coverage in branch name enables coverage"""
|
||||
branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/head/foo-branch-bar'
|
||||
})
|
||||
self.assertFalse(branch.coverage)
|
||||
cov_branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/head/foo-coverage-branch-bar'
|
||||
})
|
||||
self.assertTrue(cov_branch.coverage)
|
215
runbot/tests/test_build.py
Normal file
215
runbot/tests/test_build.py
Normal file
@ -0,0 +1,215 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from unittest.mock import patch
|
||||
from odoo.tests import common
|
||||
|
||||
class Test_Build(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_Build, self).setUp()
|
||||
self.Repo = self.env['runbot.repo']
|
||||
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
|
||||
self.Branch = self.env['runbot.branch']
|
||||
self.branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/master'
|
||||
})
|
||||
self.branch_10 = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/10.0'
|
||||
})
|
||||
self.branch_11 = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/11.0'
|
||||
})
|
||||
self.Build = self.env['runbot.build']
|
||||
|
||||
@patch('odoo.addons.runbot.models.build.fqdn')
|
||||
def test_base_fields(self, mock_fqdn):
|
||||
build = self.Build.create({
|
||||
'branch_id': self.branch.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
'port' : '1234',
|
||||
})
|
||||
self.assertEqual(build.id, build.sequence)
|
||||
self.assertEqual(build.dest, '%05d-master-d0d0ca' % build.id)
|
||||
# test dest change on new commit
|
||||
build.name = 'deadbeef0000ffffffffffffffffffffffffffff'
|
||||
self.assertEqual(build.dest, '%05d-master-deadbe' % build.id)
|
||||
|
||||
# Test domain compute with fqdn and ir.config_parameter
|
||||
mock_fqdn.return_value = 'runbot98.nowhere.org'
|
||||
self.assertEqual(build.domain, 'runbot98.nowhere.org:1234')
|
||||
self.env['ir.config_parameter'].set_param('runbot.runbot_domain', 'runbot99.example.org')
|
||||
build._get_domain()
|
||||
self.assertEqual(build.domain, 'runbot99.example.org:1234')
|
||||
|
||||
def test_pr_is_duplicate(self):
|
||||
""" test PR is a duplicate of a dev branch build """
|
||||
dup_repo = self.Repo.create({
|
||||
'name': 'bla@example.com:foo-dev/bar',
|
||||
'duplicate_id': self.repo.id
|
||||
})
|
||||
self.repo.duplicate_id = dup_repo.id
|
||||
dev_branch = self.Branch.create({
|
||||
'repo_id': dup_repo.id,
|
||||
'name': 'refs/heads/10.0-fix-thing-moc'
|
||||
})
|
||||
dev_build = self.Build.create({
|
||||
'branch_id': dev_branch.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
pr = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/pull/12345'
|
||||
})
|
||||
|
||||
pr_build = self.Build.create({
|
||||
'branch_id': pr.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual(pr_build.state, 'duplicate')
|
||||
self.assertEqual(pr_build.duplicate_id.id, dev_build.id)
|
||||
|
||||
def test_dev_is_duplicate(self):
|
||||
""" test dev branch build is a duplicate of a PR """
|
||||
dup_repo = self.Repo.create({
|
||||
'name': 'bla@example.com:foo-dev/bar',
|
||||
'duplicate_id': self.repo.id
|
||||
})
|
||||
self.repo.duplicate_id = dup_repo.id
|
||||
dev_branch = self.Branch.create({
|
||||
'repo_id': dup_repo.id,
|
||||
'name': 'refs/heads/10.0-fix-thing-moc'
|
||||
})
|
||||
pr = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/pull/12345'
|
||||
})
|
||||
|
||||
pr_build = self.Build.create({
|
||||
'branch_id': pr.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
dev_build = self.Build.create({
|
||||
'branch_id': dev_branch.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual(dev_build.state, 'duplicate')
|
||||
self.assertEqual(dev_build.duplicate_id.id, pr_build.id)
|
||||
|
||||
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
|
||||
def test_closest_branch_01(self, mock_is_on_remote):
|
||||
""" test find a matching branch in a target repo based on branch name """
|
||||
mock_is_on_remote.return_value = True
|
||||
server_repo = self.Repo.create({'name': 'bla@example.com:foo-dev/bar'})
|
||||
addons_repo = self.Repo.create({'name': 'bla@example.com:ent-dev/bar'})
|
||||
self.Branch.create({
|
||||
'repo_id': server_repo.id,
|
||||
'name': 'refs/heads/10.0-fix-thing-moc'
|
||||
})
|
||||
addons_branch = self.Branch.create({
|
||||
'repo_id': addons_repo.id,
|
||||
'name': 'refs/heads/10.0-fix-thing-moc'
|
||||
})
|
||||
addons_build = self.Build.create({
|
||||
'branch_id': addons_branch.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual((server_repo.id, addons_branch.name, 'exact'), addons_build._get_closest_branch_name(server_repo.id))
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
|
||||
def test_closest_branch_02(self, mock_github):
|
||||
""" test find two matching PR having the same head name """
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:bar_branch'},
|
||||
'base' : {'ref': 'master'},
|
||||
'state': 'open'
|
||||
}
|
||||
server_repo = self.Repo.create({'name': 'bla@example.com:foo-dev/bar', 'token': '1'})
|
||||
addons_repo = self.Repo.create({'name': 'bla@example.com:ent-dev/bar', 'token': '1'})
|
||||
server_pr = self.Branch.create({
|
||||
'repo_id': server_repo.id,
|
||||
'name': 'refs/pull/123456'
|
||||
})
|
||||
addons_pr = self.Branch.create({
|
||||
'repo_id': addons_repo.id,
|
||||
'name': 'refs/pull/789101'
|
||||
})
|
||||
addons_build = self.Build.create({
|
||||
'branch_id': addons_pr.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual((server_repo.id, server_pr.name, 'exact'), addons_build._get_closest_branch_name(server_repo.id))
|
||||
|
||||
@patch('odoo.addons.runbot.models.build.runbot_build._branch_exists')
|
||||
def test_closest_branch_03(self, mock_branch_exists):
|
||||
""" test find a branch based on dashed prefix"""
|
||||
mock_branch_exists.return_value = True
|
||||
addons_repo = self.Repo.create({'name': 'bla@example.com:ent-dev/bar', 'token': '1'})
|
||||
addons_branch = self.Branch.create({
|
||||
'repo_id': addons_repo.id,
|
||||
'name': 'refs/heads/10.0-fix-blah-blah-moc'
|
||||
})
|
||||
addons_build = self.Build.create({
|
||||
'branch_id': addons_branch.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual((self.repo.id, 'refs/heads/10.0', 'prefix'), addons_build._get_closest_branch_name(self.repo.id))
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
|
||||
def test_closest_branch_05(self, mock_github):
|
||||
""" test last resort value """
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:bar_branch'},
|
||||
'base' : {'ref': '10.0'},
|
||||
'state': 'open'
|
||||
}
|
||||
server_repo = self.Repo.create({'name': 'bla@example.com:foo-dev/bar', 'token': '1'})
|
||||
addons_repo = self.Repo.create({'name': 'bla@example.com:ent-dev/bar', 'token': '1'})
|
||||
server_pr = self.Branch.create({
|
||||
'repo_id': server_repo.id,
|
||||
'name': 'refs/pull/123456'
|
||||
})
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:foobar_branch'},
|
||||
'base' : {'ref': '10.0'},
|
||||
'state': 'open'
|
||||
}
|
||||
addons_pr = self.Branch.create({
|
||||
'repo_id': addons_repo.id,
|
||||
'name': 'refs/pull/789101'
|
||||
})
|
||||
addons_build = self.Build.create({
|
||||
'branch_id': addons_pr.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual((server_repo.id, server_pr.target_branch_name, 'default'), addons_build._get_closest_branch_name(server_repo.id))
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
|
||||
def test_closest_branch_05_master(self, mock_github):
|
||||
""" test last resort value when nothing common can be found"""
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:bar_branch'},
|
||||
'base' : {'ref': 'saas-14'},
|
||||
'state': 'open'
|
||||
}
|
||||
server_repo = self.Repo.create({'name': 'bla@example.com:foo-dev/bar', 'token': '1'})
|
||||
addons_repo = self.Repo.create({'name': 'bla@example.com:ent-dev/bar', 'token': '1'})
|
||||
server_pr = self.Branch.create({
|
||||
'repo_id': server_repo.id,
|
||||
'name': 'refs/pull/123456'
|
||||
})
|
||||
mock_github.return_value = {
|
||||
'head' : {'label': 'foo-dev:foobar_branch'},
|
||||
'base' : {'ref': '10.0'},
|
||||
'state': 'open'
|
||||
}
|
||||
addons_pr = self.Branch.create({
|
||||
'repo_id': addons_repo.id,
|
||||
'name': 'refs/pull/789101'
|
||||
})
|
||||
addons_build = self.Build.create({
|
||||
'branch_id': addons_pr.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
})
|
||||
self.assertEqual((server_repo.id, 'master', 'default'), addons_build._get_closest_branch_name(server_repo.id))
|
71
runbot/tests/test_frontend.py
Normal file
71
runbot/tests/test_frontend.py
Normal file
@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from itertools import cycle
|
||||
from unittest.mock import patch
|
||||
from werkzeug.wrappers import Response
|
||||
from odoo.tests import common
|
||||
from odoo.addons.runbot.controllers import frontend
|
||||
|
||||
|
||||
class Test_Frontend(common.HttpCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_Frontend, self).setUp()
|
||||
Repo = self.env['runbot.repo']
|
||||
self.repo = Repo.create({'name': 'bla@example.com:foo/bar', 'token': '123'})
|
||||
self.Branch = self.env['runbot.branch']
|
||||
self.sticky_branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/master',
|
||||
'sticky': True,
|
||||
})
|
||||
self.branch = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/master-test-moc',
|
||||
'sticky': False,
|
||||
})
|
||||
self.Build = self.env['runbot.build']
|
||||
|
||||
@patch('odoo.http.Response.set_default')
|
||||
@patch('odoo.addons.runbot.controllers.frontend.request')
|
||||
def test_frontend_basic(self, mock_request, mock_set_default):
|
||||
mock_request.env = self.env
|
||||
mock_request._cr = self.cr
|
||||
controller = frontend.Runbot()
|
||||
|
||||
states = ['done', 'pending', 'testing', 'running', 'deathrow']
|
||||
branches = [self.branch, self.sticky_branch]
|
||||
names = ['deadbeef', 'd0d0caca', 'deadface', 'cacafeed']
|
||||
# create 5 builds in each branch
|
||||
for i, state, branch, name in zip(range(10), cycle(states), cycle(branches), cycle(names)):
|
||||
self.Build.create({
|
||||
'branch_id': branch.id,
|
||||
'name': '%s0000ffffffffffffffffffffffffffff' % name,
|
||||
'port': '1234',
|
||||
'state': state,
|
||||
'result': 'ok'
|
||||
})
|
||||
|
||||
def mocked_simple_repo_render(template, context):
|
||||
self.assertEqual(template, 'runbot.repo', 'The frontend controller should use "runbot.repo" template')
|
||||
self.assertEqual(self.sticky_branch, context['branches'][0]['branch'], "The sticky branch should be in first place")
|
||||
self.assertEqual(self.branch, context['branches'][1]['branch'], "The non sticky branch should be in second place")
|
||||
self.assertEqual(len(context['branches'][0]['builds']), 4, "Only the 4 last builds should appear in the context")
|
||||
self.assertEqual(context['pending'], 2, "There should be 2 pending builds")
|
||||
self.assertEqual(context['running'], 2, "There should be 2 running builds")
|
||||
self.assertEqual(context['testing'], 2, "There should be 2 testing builds")
|
||||
self.assertEqual(context['pending_total'], 2, "There should be 2 pending builds")
|
||||
self.assertEqual(context['pending_level'], 'info', "The pending level should be info")
|
||||
return Response()
|
||||
|
||||
mock_request.render = mocked_simple_repo_render
|
||||
controller.repo()
|
||||
|
||||
def mocked_repo_search_render(template, context):
|
||||
dead_count = len([bu['name'] for b in context['branches'] for bu in b['builds'] if bu['name'].startswith('dead')])
|
||||
undead_count = len([bu['name'] for b in context['branches'] for bu in b['builds'] if not bu['name'].startswith('dead')])
|
||||
self.assertEqual(dead_count, 4, 'The search for "dead" should return 4 builds')
|
||||
self.assertEqual(undead_count, 0, 'The search for "dead" should not return any build without "dead" in its name')
|
||||
return Response()
|
||||
|
||||
mock_request.render = mocked_repo_search_render
|
||||
controller.repo(search='dead')
|
56
runbot/tests/test_jobs.py
Normal file
56
runbot/tests/test_jobs.py
Normal file
@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from time import localtime
|
||||
from unittest.mock import patch
|
||||
from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class Test_Jobs(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_Jobs, self).setUp()
|
||||
self.Repo = self.env['runbot.repo']
|
||||
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar', 'token': 'xxx'})
|
||||
self.Branch = self.env['runbot.branch']
|
||||
self.branch_master = self.Branch.create({
|
||||
'repo_id': self.repo.id,
|
||||
'name': 'refs/heads/master',
|
||||
})
|
||||
self.Build = self.env['runbot.build']
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._domain')
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
|
||||
@patch('odoo.addons.runbot.models.build.runbot_build._cmd')
|
||||
@patch('odoo.addons.runbot.models.build.os.path.getmtime')
|
||||
@patch('odoo.addons.runbot.models.build.time.localtime')
|
||||
@patch('odoo.addons.runbot.models.build.docker_run')
|
||||
@patch('odoo.addons.runbot.models.build.grep')
|
||||
def test_job_30_failed(self, mock_grep, mock_docker_run, mock_localtime, mock_getmtime, mock_cmd, mock_github, mock_domain):
|
||||
""" Test that a failed build sets the failure state on github """
|
||||
a_time = datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
mock_grep.return_value = False
|
||||
mock_docker_run.return_value = 2
|
||||
now = localtime()
|
||||
mock_localtime.return_value = now
|
||||
mock_getmtime.return_value = None
|
||||
mock_cmd.return_value = ([], [])
|
||||
mock_domain.return_value = 'runbotxx.somewhere.com'
|
||||
build = self.Build.create({
|
||||
'branch_id': self.branch_master.id,
|
||||
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
|
||||
'port' : '1234',
|
||||
'state': 'done',
|
||||
'job_start': a_time,
|
||||
'job_end': a_time
|
||||
})
|
||||
self.assertFalse(build.result)
|
||||
self.Build._job_30_run(build, '/tmp/x.log')
|
||||
self.assertEqual(build.result, 'ko')
|
||||
expected_status = {
|
||||
'state': 'failure',
|
||||
'target_url': 'http://runbotxx.somewhere.com/runbot/build/%s' % build.id,
|
||||
'description': 'runbot build %s (runtime 0s)' % build.dest,
|
||||
'context': 'ci/runbot'
|
||||
}
|
||||
mock_github.assert_called_with('/repos/:owner/:repo/statuses/d0d0caca0000ffffffffffffffffffffffffffff', expected_status, ignore_errors=True)
|
17
runbot/tests/test_repo.py
Normal file
17
runbot/tests/test_repo.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from unittest.mock import patch
|
||||
from odoo.tests import common
|
||||
|
||||
class Test_Repo(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_Repo, self).setUp()
|
||||
self.Repo = self.env['runbot.repo']
|
||||
|
||||
@patch('odoo.addons.runbot.models.repo.runbot_repo._root')
|
||||
def test_base_fields(self, mock_root):
|
||||
mock_root.return_value = '/tmp/static'
|
||||
repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
|
||||
self.assertEqual(repo.path, '/tmp/static/repo/bla_example.com_foo_bar')
|
||||
|
||||
self.assertEqual(repo.base, 'example.com/foo/bar')
|
Loading…
Reference in New Issue
Block a user