From 8cf4191d0356b91786c80a5767700de76c43012a Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Mon, 20 Nov 2023 15:19:03 +0100 Subject: [PATCH 1/7] Fix alternative name for AUTO cases in doc The correct file-name pattern is "cases_", not "case_" --- docs/api_reference.md | 4 ++-- src/pytest_cases/case_parametrizer_new.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/api_reference.md b/docs/api_reference.md index ded231dc..3a2f5db8 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -274,7 +274,7 @@ CaseType = Union[Callable, Type, ModuleRef] A decorator for test functions or fixtures, to parametrize them based on test cases. It works similarly to [`@pytest.mark.parametrize`](https://docs.pytest.org/en/stable/parametrize.html): argnames represent a coma-separated string of arguments to inject in the decorated test function or fixture. The argument values (`argvalues` in [`@pytest.mark.parametrize`](https://docs.pytest.org/en/stable/parametrize.html)) are collected from the various case functions found according to `cases`, and injected as lazy values so that the case functions are called just before the test or fixture is executed. -By default (`cases=AUTO`) the list of test cases is automatically drawn from the python module file named `test__cases.py` or if not found, `case_.py`, where `test_` is the current module name. +By default (`cases=AUTO`) the list of test cases is automatically drawn from the python module file named `test__cases.py` or if not found, `cases_.py`, where `test_` is the current module name. Finally, the `cases` argument also accepts an explicit case function, cases-containing class, module or module name; or a list containing any mix of these elements. Note that both absolute and relative module names are supported. @@ -293,7 +293,7 @@ argvalues = get_parametrize_args(host_class_or_module_of_f, cases_funs) - `argnames`: same than in `@pytest.mark.parametrize` - - `cases`: a case function, a class containing cases, a module object or a module name string (relative module names accepted). Or a list of such items. You may use `THIS_MODULE` or `'.'` to include current module. `AUTO` (default) means that the module named `test__cases.py` or if not found, `case_.py`, will be loaded, where `test_.py` is the module file of the decorated function. When a module is listed, all of its functions matching the `prefix`, `filter` and `has_tag` are selected, including those functions nested in classes following naming pattern `*Case*`. Nested subclasses are taken into account, as long as they follow the `*Case*` naming pattern. When classes are explicitly provided in the list, they can have any name and do not need to follow this `*Case*` pattern. + - `cases`: a case function, a class containing cases, a module object or a module name string (relative module names accepted). Or a list of such items. You may use `THIS_MODULE` or `'.'` to include current module. `AUTO` (default) means that the module named `test__cases.py` or if not found, `cases_.py`, will be loaded, where `test_.py` is the module file of the decorated function. When a module is listed, all of its functions matching the `prefix`, `filter` and `has_tag` are selected, including those functions nested in classes following naming pattern `*Case*`. Nested subclasses are taken into account, as long as they follow the `*Case*` naming pattern. When classes are explicitly provided in the list, they can have any name and do not need to follow this `*Case*` pattern. - `prefix`: the prefix for case functions. Default is 'case_' but you might wish to use different prefixes to denote different kind of cases, for example 'data_', 'algo_', 'user_', etc. diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index 63135a06..2bfab89d 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -106,7 +106,7 @@ def parametrize_with_cases(argnames, # type: Union[str, List[str] :param argnames: same than in @pytest.mark.parametrize :param cases: a case function, a class containing cases, a module object or a module name string (relative module names accepted). Or a list of such items. You may use `THIS_MODULE` or `'.'` to include current module. - `AUTO` (default) means that the module named `test__cases.py` or if not found, `case_.py`, will be + `AUTO` (default) means that the module named `test__cases.py` or if not found, `cases_.py`, will be loaded, where `test_.py` is the module file of the decorated function. When a module is listed, all of its functions matching the `prefix`, `filter` and `has_tag` are selected, including those functions nested in classes following naming pattern `*Case*`. Nested subclasses are taken into account, as long as they follow the @@ -224,7 +224,7 @@ def get_all_cases(parametrization_target=None, # type: Callable names accepted). Or a list of such items. You may use `THIS_MODULE` or `'.'` to include current module. `AUTO` (default) means that the module named `test__cases.py` will be loaded, where `test_.py` is the module file of the decorated function. `AUTO2` allows you to use the alternative naming scheme - `case_.py`. When a module is listed, all of its functions matching the `prefix`, `filter` and `has_tag` + `cases_.py`. When a module is listed, all of its functions matching the `prefix`, `filter` and `has_tag` are selected, including those functions nested in classes following naming pattern `*Case*`. When classes are explicitly provided in the list, they can have any name and do not need to follow this `*Case*` pattern. :param prefix: the prefix for case functions. Default is 'case_' but you might wish to use different prefixes to @@ -299,7 +299,7 @@ def get_all_cases(parametrization_target=None, # type: Callable else: # module if c is AUTO: - # First try `test__cases.py` Then `case_.py` + # First try `test__cases.py` Then `cases_.py` c = import_default_cases_module(caller_module_name) elif c is THIS_MODULE or c == '.': @@ -680,7 +680,7 @@ def import_default_cases_module(test_module_name): try: cases_module = import_module(cases_module_name1) except ModuleNotFoundError: - # Then try `case_.py` + # Then try `cases_.py` parts = test_module_name.split('.') assert parts[-1][0:5] == 'test_' cases_module_name2 = "%s.cases_%s" % ('.'.join(parts[:-1]), parts[-1][5:]) From 9c0711bcca8a9bda9a2e92e1932254057e9537a5 Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Mon, 20 Nov 2023 15:36:21 +0100 Subject: [PATCH 2/7] Disallow AUTO cases in non-"test_" modules Fixes #309. --- src/pytest_cases/case_parametrizer_new.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index 2bfab89d..1aa55d48 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -299,6 +299,17 @@ def get_all_cases(parametrization_target=None, # type: Callable else: # module if c is AUTO: + # Make sure we're in a test_.py-like module. + # We cannot accept AUTO cases in, e.g., conftest.py + # as we don't know what to look for. We complain here + # rather than raising AttributeError in the call to + # import_default_cases_module. See #309. + if not caller_module_name.split('.')[-1].startswith('test_'): + raise ValueError( + 'Cannot use AUTO cases in file "%s". AUTO cases are ' + 'only allowed in files whose name starts with "test_" ' + % caller_module_name + ) # First try `test__cases.py` Then `cases_.py` c = import_default_cases_module(caller_module_name) From 7e05b91162050690ebf997f6e90cf0d7b8902367 Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Mon, 20 Nov 2023 16:06:36 +0100 Subject: [PATCH 3/7] Add tests for get_all_cases --- tests/cases/issues/issue_309/conftest.py | 14 ++++++++++++++ tests/cases/issues/issue_309/test_issue_309.py | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/cases/issues/issue_309/conftest.py create mode 100644 tests/cases/issues/issue_309/test_issue_309.py diff --git a/tests/cases/issues/issue_309/conftest.py b/tests/cases/issues/issue_309/conftest.py new file mode 100644 index 00000000..9e3dc2e4 --- /dev/null +++ b/tests/cases/issues/issue_309/conftest.py @@ -0,0 +1,14 @@ +from pytest_cases import fixture, get_all_cases +from pytest_cases.common_others import AUTO + + +def mock_parameterization_target(): + """A callable to use as parametrization target.""" + + +@fixture +def get_all_cases_auto_fails(): + """Fail because we ask for AUTO cases in a non-'test_<...>' file.""" + def _fail(): + get_all_cases(mock_parameterization_target, cases=AUTO) + return _fail diff --git a/tests/cases/issues/issue_309/test_issue_309.py b/tests/cases/issues/issue_309/test_issue_309.py new file mode 100644 index 00000000..9eba22ce --- /dev/null +++ b/tests/cases/issues/issue_309/test_issue_309.py @@ -0,0 +1,7 @@ + +import pytest + + +def test_get_all_cases_auto_raises(get_all_cases_auto_fails): + with pytest.raises(ValueError): + get_all_cases_auto_fails() From 30b29a9c5d9e786ecfe6cb227cd31c2e44d30f04 Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Mon, 20 Nov 2023 16:08:52 +0100 Subject: [PATCH 4/7] Add info to changelog.md --- docs/changelog.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index b583a8f2..92c0e603 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,14 @@ # Changelog + - Corrected API documentation (and comments) for the second file-name + pattern for `AUTO`-cases lookup (`cases_.py` instead of + `case_.py`). PR [#320](https://github.com/smarie/python-pytest-cases/pull/320) + by [@michele-riva](https://github.com/michele-riva). + - Fixed `AssertionError` on `AUTO` cases outside a 'normal' test module. + Fixes [#309](https://github.com/smarie/python-pytest-cases/issues/309). PR + [#320](https://github.com/smarie/python-pytest-cases/pull/320) by + [@michele-riva](https://github.com/michele-riva). + ### 3.8.1 - bugfixes - Fixed `ScopeMismatch` with parametrized cases in non-trivial test From 69e6448e620b40e529be3273e82e252b90489007 Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Tue, 21 Nov 2023 06:50:00 +0100 Subject: [PATCH 5/7] Wrong exception in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sylvain MariƩ --- src/pytest_cases/case_parametrizer_new.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index 1aa55d48..20428cb8 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -302,7 +302,7 @@ def get_all_cases(parametrization_target=None, # type: Callable # Make sure we're in a test_.py-like module. # We cannot accept AUTO cases in, e.g., conftest.py # as we don't know what to look for. We complain here - # rather than raising AttributeError in the call to + # rather than raising AssertionError in the call to # import_default_cases_module. See #309. if not caller_module_name.split('.')[-1].startswith('test_'): raise ValueError( From 2bf247c12c8dde94a194b79a8a5bad7b5eee8d9a Mon Sep 17 00:00:00 2001 From: Michele Riva Date: Tue, 21 Nov 2023 06:51:06 +0100 Subject: [PATCH 6/7] Clearer exception text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sylvain MariƩ --- src/pytest_cases/case_parametrizer_new.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index 20428cb8..52d10116 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -306,7 +306,7 @@ def get_all_cases(parametrization_target=None, # type: Callable # import_default_cases_module. See #309. if not caller_module_name.split('.')[-1].startswith('test_'): raise ValueError( - 'Cannot use AUTO cases in file "%s". AUTO cases are ' + 'Cannot use `cases=AUTO` in file "%s". `cases=AUTO` is ' 'only allowed in files whose name starts with "test_" ' % caller_module_name ) From b02fc8241b8b64ee7116fd3169fe3435b87ce45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylvain=20Mari=C3=A9?= Date: Tue, 21 Nov 2023 12:52:30 +0100 Subject: [PATCH 7/7] Update docs/changelog.md --- docs/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 92c0e603..205aec23 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,7 @@ # Changelog +### 3.8.2 (in progress) - bugfixes + - Corrected API documentation (and comments) for the second file-name pattern for `AUTO`-cases lookup (`cases_.py` instead of `case_.py`). PR [#320](https://github.com/smarie/python-pytest-cases/pull/320)