Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
- name: Run ruff
run: |
python -m ruff check .
- name: Run ruff format
run: |
python -m ruff format --check .
- name: Test with testtools
run: |
python -m testtools.run testscenarios.tests.test_suite
4 changes: 2 additions & 2 deletions doc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# dependency injection ('scenarios') by tests.
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand Down
11 changes: 5 additions & 6 deletions doc/example.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# testscenarios: extensions to python unittest to allow declarative
# dependency injection ('scenarios') by tests.
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -18,13 +18,12 @@
from testscenarios import TestWithScenarios


scenario1 = ('basic', {'attribute': 'value'})
scenario2 = ('advanced', {'attribute': 'value2'})
scenario1 = ("basic", {"attribute": "value"})
scenario2 = ("advanced", {"attribute": "value2"})


class SampleWithScenarios(TestWithScenarios):

scenarios = [scenario1, scenario2]

def test_demo(self):
self.assertIsInstance(self.attribute, str)
6 changes: 3 additions & 3 deletions doc/test_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# dependency injection ('scenarios') by tests.
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -16,7 +16,7 @@

import unittest

class TestSample(unittest.TestCase):

class TestSample(unittest.TestCase):
def test_so_easy(self):
pass
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#!/usr/bin/env python
import setuptools

setuptools.setup(
setup_requires=['pbr'],
pbr=True)
setuptools.setup(setup_requires=["pbr"], pbr=True)
28 changes: 15 additions & 13 deletions testscenarios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# dependency injection ('scenarios') by tests.
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand Down Expand Up @@ -39,20 +39,21 @@
# If the releaselevel is 'final', then the tarball will be major.minor.micro.
# Otherwise it is major.minor.micro~$(revno).
from pbr.version import VersionInfo
_version = VersionInfo('testscenarios')

_version = VersionInfo("testscenarios")
__version__ = _version.semantic_version().version_tuple()
version = _version.release_string()

__all__ = [
'TestWithScenarios',
'WithScenarios',
'apply_scenario',
'apply_scenarios',
'generate_scenarios',
'load_tests_apply_scenarios',
'multiply_scenarios',
'per_module_scenarios',
]
"TestWithScenarios",
"WithScenarios",
"apply_scenario",
"apply_scenarios",
"generate_scenarios",
"load_tests_apply_scenarios",
"multiply_scenarios",
"per_module_scenarios",
]


from testscenarios.scenarios import ( # noqa: E402
Expand All @@ -62,12 +63,13 @@
load_tests_apply_scenarios,
multiply_scenarios,
per_module_scenarios,
)
)
from testscenarios.testcase import TestWithScenarios, WithScenarios # noqa: E402


def test_suite():
import testscenarios.tests # noqa: F401

return testscenarios.tests.test_suite()


Expand Down
45 changes: 21 additions & 24 deletions testscenarios/scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
# Copyright (c) 2010, 2011 Martin Pool <mbp@sourcefrog.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# license you chose for the specific language governing permissions and
# limitations under that license.

__all__ = [
'apply_scenario',
'apply_scenarios',
'generate_scenarios',
'load_tests_apply_scenarios',
'multiply_scenarios',
]
"apply_scenario",
"apply_scenarios",
"generate_scenarios",
"load_tests_apply_scenarios",
"multiply_scenarios",
]

from itertools import (
product,
)
)
import sys

from testtools.testcase import clone_test_with_new_id
Expand All @@ -42,13 +42,12 @@ def apply_scenario(scenario, test):
:return: A new test cloned from test, with the scenario applied.
"""
name, parameters = scenario
scenario_suffix = '(' + name + ')'
newtest = clone_test_with_new_id(test,
test.id() + scenario_suffix)
scenario_suffix = "(" + name + ")"
newtest = clone_test_with_new_id(test, test.id() + scenario_suffix)
test_desc = test.shortDescription()
if test_desc is not None:
newtest_desc = "%(test_desc)s %(scenario_suffix)s" % vars()
newtest.shortDescription = (lambda: newtest_desc)
newtest.shortDescription = lambda: newtest_desc
for key, value in parameters.items():
setattr(newtest, key, value)
return newtest
Expand Down Expand Up @@ -76,7 +75,7 @@ def generate_scenarios(test_or_suite):
:return: A generator of tests - objects satisfying the TestCase protocol.
"""
for test in iterate_tests(test_or_suite):
scenarios = getattr(test, 'scenarios', None)
scenarios = getattr(test, "scenarios", None)
if scenarios:
for newtest in apply_scenarios(scenarios, test):
newtest.scenarios = None
Expand All @@ -98,10 +97,10 @@ def load_tests_apply_scenarios(*params):
pattern), and bzr used (standard_tests, module, loader).

:param loader: A TestLoader.
:param standard_test: The test objects found in this module before
:param standard_test: The test objects found in this module before
multiplication.
"""
if getattr(params[0], 'suiteClass', None) is not None:
if getattr(params[0], "suiteClass", None) is not None:
loader, standard_tests, pattern = params
else:
standard_tests, module, loader = params
Expand All @@ -115,15 +114,15 @@ def multiply_scenarios(*scenarios):

It is safe to pass scenario generators or iterators.

:returns: A list of compound scenarios: the cross-product of all
:returns: A list of compound scenarios: the cross-product of all
scenarios, with the names concatenated and the parameters
merged together.
"""
result = []
scenario_lists = map(list, scenarios)
for combination in product(*scenario_lists):
names, parameters = zip(*combination)
scenario_name = ','.join(names)
scenario_name = ",".join(names)
scenario_parameters = {}
for parameter in parameters:
scenario_parameters.update(parameter)
Expand All @@ -145,21 +144,19 @@ def per_module_scenarios(attribute_name, modules):
yet.

:param attribute_name: A name to be set in the scenario parameter
dictionary (and thence onto the test instance) pointing to the
dictionary (and thence onto the test instance) pointing to the
implementation module (or import exception) for this scenario.

:param modules: An iterable of (short_name, module_name), where
:param modules: An iterable of (short_name, module_name), where
the short name is something like 'python' to put in the
scenario name, and the long name is a fully-qualified Python module
name.
"""
scenarios = []
for short_name, module_name in modules:
try:
mod = __import__(module_name, {}, {}, [''])
mod = __import__(module_name, {}, {}, [""])
except BaseException:
mod = sys.exc_info()
scenarios.append((
short_name,
{attribute_name: mod}))
scenarios.append((short_name, {attribute_name: mod}))
return scenarios
27 changes: 17 additions & 10 deletions testscenarios/testcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
# dependency injection ('scenarios') by tests.
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# license you chose for the specific language governing permissions and
# limitations under that license.

__all__ = [
'TestWithScenarios',
'WithScenarios',
]
"TestWithScenarios",
"WithScenarios",
]

import unittest

Expand All @@ -32,12 +32,16 @@
compatibly with WithScenarios).
"""


class WithScenarios(object):
__doc__ = """A mixin for TestCase with support for declarative scenarios.
""" + _doc
__doc__ = (
"""A mixin for TestCase with support for declarative scenarios.
"""
+ _doc
)

def _get_scenarios(self):
return getattr(self, 'scenarios', None)
return getattr(self, "scenarios", None)

def countTestCases(self):
scenarios = self._get_scenarios()
Expand Down Expand Up @@ -65,5 +69,8 @@ def run(self, result=None):


class TestWithScenarios(WithScenarios, unittest.TestCase):
__doc__ = """Unittest TestCase with support for declarative scenarios.
""" + _doc
__doc__ = (
"""Unittest TestCase with support for declarative scenarios.
"""
+ _doc
)
15 changes: 8 additions & 7 deletions testscenarios/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# dependency injection ('scenarios') by tests.
#
# Copyright (c) 2009, Robert Collins <robertc@robertcollins.net>
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -23,20 +23,21 @@

def test_suite():
standard_tests = unittest.TestSuite()
module = sys.modules['testscenarios.tests']
module = sys.modules["testscenarios.tests"]
loader = unittest.TestLoader()
return load_tests(standard_tests, module, loader)


def load_tests(standard_tests, module, loader):
test_modules = [
'testcase',
'scenarios',
]
"testcase",
"scenarios",
]
prefix = "testscenarios.tests.test_"
test_mod_names = [prefix + test_module for test_module in test_modules]
standard_tests.addTests(loader.loadTestsFromNames(test_mod_names))
doctest.set_unittest_reportflags(doctest.REPORT_ONLY_FIRST_FAILURE)
standard_tests.addTest(
doctest.DocFileSuite("../../README.rst", optionflags=doctest.ELLIPSIS))
doctest.DocFileSuite("../../README.rst", optionflags=doctest.ELLIPSIS)
)
return loader.suiteClass(testscenarios.generate_scenarios(standard_tests))
Loading