diff --git a/neutron-requirements.txt b/neutron-requirements.txt index 3d6aa6aaa..0041d805f 100644 --- a/neutron-requirements.txt +++ b/neutron-requirements.txt @@ -1,3 +1 @@ # Neutron test cases requirements - -stestr>=2.0 # Apache-2.0 diff --git a/requirements.txt b/requirements.txt index 84087f293..c167b5c6f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ oslo.config>=5.2.0 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 python-heatclient>=1.5.0 # Apache-2.0 python-neutronclient>=6.7.0 # Apache-2.0 +stestr>=2.0 # Apache-2.0 testtools>=2.2.0 # MIT diff --git a/test-requirements.txt b/test-requirements.txt index 471b13dc9..0542a0f24 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,4 +2,3 @@ coverage!=4.4,>=4.0 # Apache-2.0 mock>=2.0 # BSD -stestr>=2.0 # Apache-2.0 diff --git a/tobiko/__init__.py b/tobiko/__init__.py index cb29eb32b..ee936bcdc 100644 --- a/tobiko/__init__.py +++ b/tobiko/__init__.py @@ -13,6 +13,7 @@ from __future__ import absolute_import from tobiko.common.managers import fixture as fixture_manager +from tobiko.common.managers import testcase as testcase_manager Fixture = fixture_manager.Fixture @@ -20,3 +21,5 @@ Fixture = fixture_manager.Fixture get_fixture = fixture_manager.FIXTURES.get create_fixture = fixture_manager.FIXTURES.create delete_fixture = fixture_manager.FIXTURES.delete + +list_testcase_ids = testcase_manager.TESTCASES.list_ids diff --git a/tobiko/common/managers/testcase.py b/tobiko/common/managers/testcase.py new file mode 100644 index 000000000..0c78bd2bb --- /dev/null +++ b/tobiko/common/managers/testcase.py @@ -0,0 +1,105 @@ +# Copyright 2018 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import absolute_import + +from stestr import config_file + + +class TestCaseManager(object): + + def __init__(self, config='.stestr.conf', repo_type='file', repo_url=None, + test_path=None, top_dir=None, group_regex=None, + blacklist_file=None, whitelist_file=None, black_regex=None, + filters=None): + """ + :param str config: The path to the stestr config file. Must be a + string. + :param str repo_type: This is the type of repository to use. Valid + choices are 'file' and 'sql'. + :param str repo_url: The url of the repository to use. + :param str test_path: Set the test path to use for unittest discovery. + If both this and the corresponding config file option are set, this + value will be used. + :param str top_dir: The top dir to use for unittest discovery. This + takes precedence over the value in the config file. (if one is + present in the config file) + :param str group_regex: Set a group regex to use for grouping tests + together in the stestr scheduler. If both this and the + corresponding config file option are set this value will be used. + :param str blacklist_file: Path to a blacklist file, this file contains + a separate regex exclude on each newline. + :param str whitelist_file: Path to a whitelist file, this file contains + a separate regex on each newline. + :param str black_regex: Test rejection regex. If a test cases name + matches on re.search() operation, it will be removed from the final + test list. + :param list filters: A list of string regex filters to initially apply + on the test list. Tests that match any of the regexes will be used. + (assuming any other filtering specified also uses it) + """ + + self.config = config + self.repo_type = repo_type + self.repo_url = repo_url + self.test_path = test_path + self.top_dir = top_dir + self.group_regex = group_regex + self.blacklist_file = blacklist_file + self.whitelist_file = whitelist_file + self.black_regex = black_regex + self.filters = filters + + def list_ids(self, **kwargs): + """Iterate over test_ids for a project + This method will print the test_ids for tests in a project. You can + filter the output just like with the run command to see exactly what + will be run. + """ + params = dict(config=self.config, repo_type=self.repo_type, + repo_url=self.repo_url, test_path=self.test_path, + top_dir=self.top_dir, group_regex=self.group_regex, + blacklist_file=self.blacklist_file, + whitelist_file=self.whitelist_file, + black_regex=self.black_regex, filters=self.filters) + if kwargs: + params.update(kwargs) + ids = None + config = params.pop('config') + conf = config_file.TestrConf(config) + filters = params.pop('filters') + blacklist_file = params.pop('blacklist_file') + whitelist_file = params.pop('whitelist_file') + black_regex = params.pop('black_regex') + cmd = conf.get_run_command( + regexes=filters, repo_type=params['repo_type'], + repo_url=params['repo_url'], group_regex=params['group_regex'], + blacklist_file=blacklist_file, whitelist_file=whitelist_file, + black_regex=black_regex, test_path=params['test_path'], + top_dir=params['top_dir']) + not_filtered = filters is None and blacklist_file is None\ + and whitelist_file is None and black_regex is None + try: + cmd.setUp() + # List tests if the fixture has not already needed to to filter. + if not_filtered: + ids = cmd.list_tests() + else: + ids = cmd.test_ids + finally: + cmd.cleanUp() + + return ids + + +TESTCASES = TestCaseManager() diff --git a/tobiko/tests/test_testcase.py b/tobiko/tests/test_testcase.py new file mode 100644 index 000000000..20f84d806 --- /dev/null +++ b/tobiko/tests/test_testcase.py @@ -0,0 +1,48 @@ +# Copyright 2018 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import absolute_import + +import os + +from tobiko.tests import base +import tobiko + + +class TestCasesManagerTest(base.TobikoTest): + + test_path = os.path.dirname(__file__) + + def setUp(self): + super(TestCasesManagerTest, self).setUp() + + top_dir = os.path.abspath(self.test_path) + while os.path.isdir(top_dir) and top_dir != os.path.sep: + if os.path.isdir(os.path.join(top_dir, '.stestr')): + break + top_dir = os.path.dirname(top_dir) + else: + raise self.fail("Unable to find '.stestr' directory") + self.top_dir = top_dir + self.repo_url = top_dir + + # Move to top directory + original_work_dir = os.getcwd() + os.chdir(self.top_dir) + self.addCleanup(os.chdir, original_work_dir) + + def test_list_testcase_ids(self): + testcases = tobiko.list_testcase_ids(test_path=self.test_path, + top_dir=self.top_dir, + repo_url=self.repo_url) + self.assertIn(self.id(), testcases)