Merge "Return dummuy test case in case not in one"

This commit is contained in:
Zuul 2020-07-10 22:40:36 +00:00 committed by Gerrit Code Review
commit d734c44be6
8 changed files with 213 additions and 159 deletions

View File

@ -20,7 +20,6 @@ from tobiko.common import _detail
from tobiko.common import _exception
from tobiko.common import _fixture
from tobiko.common import _logging
from tobiko.common.managers import testcase as testcase_manager
from tobiko.common.managers import loader as loader_manager
from tobiko.common import _operation
from tobiko.common import _os
@ -64,7 +63,6 @@ list_required_fixtures = _fixture.list_required_fixtures
SharedFixture = _fixture.SharedFixture
FixtureManager = _fixture.FixtureManager
CaptureLogTest = _logging.CaptureLogTest
CaptureLogFixture = _logging.CaptureLogFixture
load_object = loader_manager.load_object
@ -83,8 +81,6 @@ get_operation = _operation.get_operation
get_operation_name = _operation.get_operation_name
operation_config = _operation.operation_config
discover_testcases = testcase_manager.discover_testcases
Selection = _select.Selection
select = _select.select
ObjectNotFound = _select.ObjectNotFound
@ -95,10 +91,12 @@ skip = _skip.skip
skip_if = _skip.skip_if
skip_unless = _skip.skip_unless
BaseTestCase = _testcase.BaseTestCase
discover_test_cases = _testcase.discover_test_cases
get_test_case = _testcase.get_test_case
pop_test_case = _testcase.pop_test_case
push_test_case = _testcase.push_test_case
TobikoTestCase = _testcase.TobikoTestCase
TestCasesManager = _testcase.TestCasesManager
get_short_hostname = _utils.get_short_hostname

View File

@ -114,7 +114,7 @@ class FixtureUtil(base.TobikoCMD):
def discover_testcases(self):
args = self.args
return tobiko.discover_testcases(
return tobiko.discover_test_cases(
config=args.config,
repo_type=args.repo_type,
repo_url=args.repo_url,

View File

@ -20,7 +20,6 @@ from testtools import content
from tobiko.common import _detail
from tobiko.common import _fixture
from tobiko.common import _testcase
LOG = log.getLogger(__name__)
@ -78,15 +77,3 @@ class CaptureLogHandler(logging.Handler):
def format_all(self):
for record in self.records:
yield self.format(record) + '\n'
class CaptureLogTest(_testcase.TobikoTestCase):
capture_log_level = logging.DEBUG
capture_log_logger = logging.root
def setUp(self):
self.useFixture(CaptureLogFixture(test_case_id=self.id(),
level=self.capture_log_level,
logger=self.capture_log_logger))
super(CaptureLogTest, self).setUp()

View File

@ -13,10 +13,119 @@
# under the License.
from __future__ import absolute_import
import logging
import os
import sys
from oslo_log import log
from stestr import config_file
import testtools
from tobiko.common import _exception
from tobiko.common import _logging
LOG = log.getLogger(__name__)
os.environ.setdefault('PYTHON', sys.executable)
class TestCasesFinder(object):
def __init__(self, config=None, repo_type=None, 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 or '.stestr.conf'
self.repo_type = repo_type or 'file'
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 discover_test_cases(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
except SystemExit:
msg = ("Error discovering test cases IDs with parameters: "
"{!r}").format(params)
raise RuntimeError(msg)
finally:
cmd.cleanUp()
return sorted(ids)
FINDER = TestCasesFinder()
def discover_test_cases(finder=FINDER, **kwargs):
return finder.discover_test_cases(**kwargs)
class TestCasesManager(object):
@ -25,7 +134,10 @@ class TestCasesManager(object):
self._test_cases = []
def get_test_case(self) -> testtools.TestCase:
return self._test_cases[-1]
try:
return self._test_cases[-1]
except IndexError:
return DUMMY_TEST_CASE
def pop_test_case(self) -> testtools.TestCase:
return self._test_cases.pop()
@ -50,11 +162,29 @@ def get_test_case(manager=TEST_CASES):
return manager.get_test_case()
class TobikoTestCase(testtools.TestCase):
class BaseTestCase(testtools.TestCase):
_capture_log = False
_capture_log_level = logging.DEBUG
_capture_log_logger = logging.root
@classmethod
def setUpClass(cls):
super(BaseTestCase, cls).setUpClass()
from tobiko import config
cls._capture_log = config.CONF.tobiko.logging.capture_log
def setUp(self):
super(BaseTestCase, self).setUp()
self._push_test_case()
super(TobikoTestCase, self).setUp()
self._setup_capture_log()
def _setup_capture_log(self):
if self._capture_log:
self.useFixture(_logging.CaptureLogFixture(
test_case_id=self.id(),
level=self._capture_log_level,
logger=self._capture_log_logger))
def _push_test_case(self):
push_test_case(self)
@ -62,3 +192,12 @@ class TobikoTestCase(testtools.TestCase):
def _pop_test_case(self):
self.assertIs(self, pop_test_case())
class DummyTestCase(BaseTestCase):
def runTest(self):
pass
DUMMY_TEST_CASE = DummyTestCase()

View File

@ -1,123 +0,0 @@
# 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
import sys
from oslo_log import log
from stestr import config_file
LOG = log.getLogger(__name__)
os.environ.setdefault('PYTHON', sys.executable)
def discover_testcases(manager=None, **kwargs):
manager = manager or TESTCASES
return manager.discover(**kwargs)
class TestCaseManager(object):
def __init__(self, config=None, repo_type=None, 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 or '.stestr.conf'
self.repo_type = repo_type or 'file'
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 discover(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
except SystemExit:
msg = ("Error discovering test cases IDs with parameters: "
"{!r}").format(params)
raise RuntimeError(msg)
finally:
cmd.cleanUp()
return sorted(ids)
TESTCASES = TestCaseManager()

View File

@ -226,10 +226,7 @@ def setup_tobiko_config(conf):
warnings_logger.logger.setLevel(log.ERROR)
tobiko.setup_fixture(HttpProxyFixture)
if conf.logging.capture_log:
monkey.patch(testtools, 'TestCase', tobiko.CaptureLogTest)
else:
monkey.patch(testtools, 'TestCase', tobiko.TobikoTestCase)
monkey.patch(testtools, 'TestCase', tobiko.BaseTestCase)
for module_name in CONFIG_MODULES:
module = importlib.import_module(module_name)

View File

@ -15,16 +15,18 @@ from __future__ import absolute_import
import os
import testtools
import tobiko
from tobiko.tests import unit
class TestCasesManagerTest(unit.TobikoUnitTest):
class DiscoverTestCasesTest(unit.TobikoUnitTest):
test_path = os.path.dirname(__file__)
def setUp(self):
super(TestCasesManagerTest, self).setUp()
super(DiscoverTestCasesTest, self).setUp()
top_dir = os.path.abspath(self.test_path)
while os.path.isdir(top_dir) and top_dir != os.path.sep:
@ -42,8 +44,59 @@ class TestCasesManagerTest(unit.TobikoUnitTest):
self.addCleanup(os.chdir, original_work_dir)
def test_discover_testcases(self):
testcases = tobiko.discover_testcases(test_path=self.test_path,
top_dir=self.top_dir,
repo_url=self.repo_url,
filters=[self.id()])
testcases = tobiko.discover_test_cases(test_path=self.test_path,
top_dir=self.top_dir,
repo_url=self.repo_url,
filters=[self.id()])
self.assertIn(self.id(), testcases)
class TestCaseTest(unit.TobikoUnitTest):
def setUp(self):
super(TestCaseTest, self).setUp()
self.addCleanup(self._pop_inner_test_cases)
def _pop_inner_test_cases(self):
case = tobiko.get_test_case()
while case is not self:
tobiko.pop_test_case()
case = tobiko.get_test_case()
def test_get_test_case(self):
result = tobiko.get_test_case()
self.assertIs(self, result)
def test_get_test_case_out_of_context(self):
manager = tobiko.TestCasesManager()
result = tobiko.get_test_case(manager=manager)
self.assertIsInstance(result, tobiko.BaseTestCase)
self.assertEqual('tobiko.common._testcase.DummyTestCase.runTest',
result.id())
def test_push_test_case(self):
class InnerTest(testtools.TestCase):
def runTest(self):
pass
inner_case = InnerTest()
tobiko.push_test_case(inner_case)
self.assertIs(inner_case, tobiko.get_test_case())
def test_pop_test_case(self):
class InnerTest(testtools.TestCase):
def runTest(self):
pass
inner_case = InnerTest()
tobiko.push_test_case(inner_case)
result = tobiko.pop_test_case()
self.assertIs(inner_case, result)
self.assertIs(self, tobiko.get_test_case())

View File

@ -46,8 +46,12 @@ skip_if_missing_overcloud = tobiko.skip_unless(
class OvercloudKeystoneCredentialsFixture(
keystone.EnvironKeystoneCredentialsFixture):
def get_environ(self):
return load_overcloud_rcfile()
if has_overcloud():
return load_overcloud_rcfile()
else:
return {}
def list_overcloud_nodes(**params):
@ -161,9 +165,8 @@ class OvercloudHostConfig(tobiko.SharedFixture):
def setup_overcloud_keystone_crederntials():
if has_overcloud():
keystone.DEFAULT_KEYSTONE_CREDENTIALS_FIXTURES.append(
OvercloudKeystoneCredentialsFixture)
keystone.DEFAULT_KEYSTONE_CREDENTIALS_FIXTURES.append(
OvercloudKeystoneCredentialsFixture)
def get_overcloud_nodes_dataframe(oc_node_df_function):