Add simple_layout test decorator
And add it to test_no_job_project.
So that we can reduce the number of boilerplate git repos initialized
for every (or most) tests, make it simple to specify a single simple
layout file (like we used to do in zuul v2). The more complicated
scenarios can rely on the full copy-git-repos-from-test-fixtures
behavior, but simple tests can have that automatically generated from
a simple zuul.yaml file.
Change-Id: Ibeec4c526a1097823589f2c38a50e40dc346e0e5
diff --git a/doc/source/developer/testing.rst b/doc/source/developer/testing.rst
index 4a813d0..057ab7e 100644
--- a/doc/source/developer/testing.rst
+++ b/doc/source/developer/testing.rst
@@ -9,6 +9,8 @@
access to a number of attributes useful for manipulating or inspecting
the environment being simulated in the test:
+.. autofunction:: tests.base.simple_layout
+
.. autoclass:: tests.base.ZuulTestCase
:members:
diff --git a/tests/base.py b/tests/base.py
index 0c033b5..120920b 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -97,6 +97,30 @@
raise Exception("Timeout waiting for %s" % purpose)
+def simple_layout(path):
+ """Specify a layout file for use by a test method.
+
+ :arg str path: The path to the layout file.
+
+ Some tests require only a very simple configuration. For those,
+ establishing a complete config directory hierachy is too much
+ work. In those cases, you can add a simple zuul.yaml file to the
+ test fixtures directory (in fixtures/layouts/foo.yaml) and use
+ this decorator to indicate the test method should use that rather
+ than the tenant config file specified by the test class.
+
+ The decorator will cause that layout file to be added to a
+ config-project called "common-config" and each "project" instance
+ referenced in the layout file will have a git repo automatically
+ initialized.
+ """
+
+ def decorator(test):
+ test.__simple_layout__ = path
+ return test
+ return decorator
+
+
class ChangeReference(git.Reference):
_common_path_default = "refs/changes"
_points_to_commits_only = True
@@ -1231,7 +1255,8 @@
be loaded). It defaults to the value specified in
`config_file` but can be overidden by subclasses to obtain a
different tenant/project layout while using the standard main
- configuration.
+ configuration. See also the :py:func:`simple_layout`
+ decorator.
:cvar bool create_project_keys: Indicates whether Zuul should
auto-generate keys for each project, or whether the test
@@ -1324,7 +1349,6 @@
self.init_repo("org/conflict-project")
self.init_repo("org/noop-project")
self.init_repo("org/experimental-project")
- self.init_repo("org/no-jobs-project")
self.statsd = FakeStatsd()
# note, use 127.0.0.1 rather than localhost to avoid getting ipv6
@@ -1452,19 +1476,70 @@
# obeys the config_file and tenant_config_file attributes.
self.config = ConfigParser.ConfigParser()
self.config.read(os.path.join(FIXTURE_DIR, self.config_file))
- if hasattr(self, 'tenant_config_file'):
- self.config.set('zuul', 'tenant_config', self.tenant_config_file)
- git_path = os.path.join(
- os.path.dirname(
- os.path.join(FIXTURE_DIR, self.tenant_config_file)),
- 'git')
- if os.path.exists(git_path):
- for reponame in os.listdir(git_path):
- project = reponame.replace('_', '/')
- self.copyDirToRepo(project,
- os.path.join(git_path, reponame))
+
+ if not self.setupSimpleLayout():
+ if hasattr(self, 'tenant_config_file'):
+ self.config.set('zuul', 'tenant_config',
+ self.tenant_config_file)
+ git_path = os.path.join(
+ os.path.dirname(
+ os.path.join(FIXTURE_DIR, self.tenant_config_file)),
+ 'git')
+ if os.path.exists(git_path):
+ for reponame in os.listdir(git_path):
+ project = reponame.replace('_', '/')
+ self.copyDirToRepo(project,
+ os.path.join(git_path, reponame))
self.setupAllProjectKeys()
+ def setupSimpleLayout(self):
+ # If the test method has been decorated with a simple_layout,
+ # use that instead of the class tenant_config_file. Set up a
+ # single config-project with the specified layout, and
+ # initialize repos for all of the 'project' entries which
+ # appear in the layout.
+ test_name = self.id().split('.')[-1]
+ test = getattr(self, test_name)
+ if hasattr(test, '__simple_layout__'):
+ path = getattr(test, '__simple_layout__')
+ else:
+ return False
+
+ path = os.path.join(FIXTURE_DIR, path)
+ with open(path) as f:
+ layout = yaml.safe_load(f.read())
+ untrusted_projects = []
+ for item in layout:
+ if 'project' in item:
+ name = item['project']['name']
+ untrusted_projects.append(name)
+ self.init_repo(name)
+ self.addCommitToRepo(name, 'initial commit',
+ files={'README': ''},
+ branch='master', tag='init')
+
+ root = os.path.join(self.test_root, "config")
+ if not os.path.exists(root):
+ os.makedirs(root)
+ f = tempfile.NamedTemporaryFile(dir=root, delete=False)
+ config = [{'tenant':
+ {'name': 'tenant-one',
+ 'source': {'gerrit':
+ {'config-projects': ['common-config'],
+ 'untrusted-projects': untrusted_projects}}}}]
+ f.write(yaml.dump(config))
+ f.close()
+ self.config.set('zuul', 'tenant_config',
+ os.path.join(FIXTURE_DIR, f.name))
+
+ self.init_repo('common-config')
+ with open(path) as f:
+ files = {'zuul.yaml': f.read()}
+ self.addCommitToRepo('common-config', 'add content from fixture',
+ files, branch='master', tag='init')
+
+ return True
+
def setupAllProjectKeys(self):
if self.create_project_keys:
return
@@ -1956,8 +2031,7 @@
- org/node-project
- org/conflict-project
- org/noop-project
- - org/experimental-project
- - org/no-jobs-project\n""" % path)
+ - org/experimental-project\n""" % path)
for repo in untrusted_projects:
f.write(" - %s\n" % repo)
diff --git a/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml b/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
index b24f62e..141c78f 100644
--- a/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
@@ -225,9 +225,3 @@
dependencies: nonvoting-project-merge
- nonvoting-project-test2:
dependencies: nonvoting-project-merge
-
-- project:
- name: org/no-jobs-project
- check:
- jobs:
- - project-testfile
diff --git a/tests/fixtures/config/single-tenant/git/org_no-jobs-project/README b/tests/fixtures/config/single-tenant/git/org_no-jobs-project/README
deleted file mode 100644
index 44f3bac..0000000
--- a/tests/fixtures/config/single-tenant/git/org_no-jobs-project/README
+++ /dev/null
@@ -1 +0,0 @@
-staypuft
diff --git a/tests/fixtures/config/single-tenant/main.yaml b/tests/fixtures/config/single-tenant/main.yaml
index e8a7fcb..8c3e809 100644
--- a/tests/fixtures/config/single-tenant/main.yaml
+++ b/tests/fixtures/config/single-tenant/main.yaml
@@ -20,4 +20,3 @@
- org/conflict-project
- org/noop-project
- org/experimental-project
- - org/no-jobs-project
diff --git a/tests/fixtures/layouts/no-jobs-project.yaml b/tests/fixtures/layouts/no-jobs-project.yaml
new file mode 100644
index 0000000..803e5a0
--- /dev/null
+++ b/tests/fixtures/layouts/no-jobs-project.yaml
@@ -0,0 +1,23 @@
+- pipeline:
+ name: check
+ manager: independent
+ trigger:
+ gerrit:
+ - event: patchset-created
+ success:
+ gerrit:
+ verified: 1
+ failure:
+ gerrit:
+ verified: -1
+
+- job:
+ name: project-testfile
+ files:
+ - .*-requires
+
+- project:
+ name: org/no-jobs-project
+ check:
+ jobs:
+ - project-testfile
diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py
index 22ae46d..366354c 100755
--- a/tests/unit/test_scheduler.py
+++ b/tests/unit/test_scheduler.py
@@ -36,6 +36,7 @@
from tests.base import (
ZuulTestCase,
repack_repo,
+ simple_layout,
)
@@ -1910,6 +1911,7 @@
self.assertEqual(A.data['status'], 'MERGED')
self.assertEqual(A.reported, 2)
+ @simple_layout('layouts/no-jobs-project.yaml')
def test_no_job_project(self):
"Test that reports with no jobs don't get sent"
A = self.fake_gerrit.addFakeChange('org/no-jobs-project',