{"id":6912,"library":"testscenarios","title":"Testscenarios","description":"Testscenarios is a Python library that extends `unittest` to provide clean dependency injection, enabling a single test method to be run with multiple scenarios. This is particularly useful for interface testing (testing many implementations via a single test suite) or for classic dependency injection, where test dependencies are provided externally. The library is currently at version 0.5.0, offering a stable approach to scenario-based testing.","status":"active","version":"0.5.0","language":"en","source_language":"en","source_url":"https://github.com/testing-cabal/testscenarios","tags":["testing","unittest","dependency injection","scenarios","test automation"],"install":[{"cmd":"pip install testscenarios","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Used for additional testing utilities, though testscenarios can be used with standard unittest.TestCase.","package":"testtools","optional":false}],"imports":[{"note":"The primary class for integrating scenarios into unittest.TestCase classes.","wrong":"from testscenarios.testscenarios import TestWithScenarios","symbol":"TestWithScenarios","correct":"from testscenarios import TestWithScenarios"},{"note":"A utility function to integrate scenarios via the unittest `load_tests` protocol.","symbol":"load_tests_apply_scenarios","correct":"from testscenarios import load_tests_apply_scenarios"}],"quickstart":{"code":"import unittest\nfrom testscenarios import TestWithScenarios\n\nclass MyScenarioTest(TestWithScenarios, unittest.TestCase):\n    # Define scenarios as a list of (name, dictionary_of_parameters) tuples\n    scenarios = [\n        ('addition_scenario', dict(num1=5, num2=3, expected_sum=8)),\n        ('subtraction_scenario', dict(num1=10, num2=4, expected_difference=6)),\n        ('multiplication_scenario', dict(num1=2, num2=6, expected_product=12))\n    ]\n\n    def test_addition(self):\n        \"\"\"Test addition operation using scenario parameters.\"\"\"\n        # Parameters from the current scenario are automatically available as instance attributes\n        actual_sum = self.num1 + self.num2\n        self.assertEqual(actual_sum, self.expected_sum)\n\n    def test_subtraction(self):\n        \"\"\"Test subtraction operation using scenario parameters.\"\"\"\n        actual_difference = self.num1 - self.num2\n        self.assertEqual(actual_difference, self.expected_difference)\n\n    def test_multiplication(self):\n        \"\"\"Test multiplication operation using scenario parameters.\"\"\"\n        actual_product = self.num1 * self.num2\n        self.assertEqual(actual_product, self.expected_product)\n\nif __name__ == '__main__':\n    unittest.main()","lang":"python","description":"This quickstart demonstrates defining multiple scenarios directly within a `unittest.TestCase` by inheriting from `TestWithScenarios`. Each scenario is a tuple containing a descriptive name and a dictionary of parameters. These parameters are injected as instance attributes into the test method when executed, allowing the same test logic to run with different data sets. To run, save as a Python file and execute with `python -m unittest your_test_file.py`."},"warnings":[{"fix":"Ensure `TestWithScenarios` is the leftmost base class (e.g., `class MyTest(TestWithScenarios, unittest.TestCase):`). Avoid overriding `run()` or `__call__()` in your test classes.","message":"When using `TestWithScenarios` as a mixin, it must be the first class in the MRO (Method Resolution Order) of your `unittest.TestCase` subclass. Additionally, you must not override the `run()` or `__call__()` methods in your test class, as `TestWithScenarios` relies on these to generate and execute tests for each scenario.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always access the scenario-provided module/dependency via `self.attribute_name` within your test methods, where `attribute_name` is defined in your scenario dictionary.","message":"If using `per_module_scenarios` for dependency injection, ensure all access to the module under test goes through the attribute set by the scenario on the test object (e.g., `self.my_module`). Directly importing the module within the test file will bypass the scenario's injected dependency, potentially leading to incorrect test results or unexpected behavior.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If dynamic scenario generation is needed, ensure that scenarios are uniquely generated or cloned per test object if there's a risk of shared state, or use the `load_tests` hook (e.g., `load_tests_apply_scenarios`) which explicitly handles scenario generation before tests are added to the suite.","message":"Modifying the `scenarios` attribute dynamically after a test has been loaded but before it runs can lead to unexpected behavior if not handled carefully. Multiple tests might share a single `scenarios` attribute, so altering it for one test could unintentionally affect others.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your project runs on Python 3.10 or a newer compatible version.","message":"The GitHub repository indicates support for Python 3.10 and newer, while the PyPI `requires_python` metadata is `None`. Using `testscenarios` with Python versions older than 3.10 may lead to compatibility issues or unexpected behavior.","severity":"gotcha","affected_versions":"< 3.10"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}