Skip to content

Commit 6660966

Browse files
Merge pull request #4076 from nicoddemus/unittest-param-fixture-msg
Improve error message when TestCase functions use a parametrized fixture
2 parents a1208f5 + 212937e commit 6660966

File tree

5 files changed

+52
-7
lines changed

5 files changed

+52
-7
lines changed

changelog/2535.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture.

src/_pytest/fixtures.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,20 @@ def _compute_fixture_value(self, fixturedef):
564564
except (AttributeError, ValueError):
565565
param = NOTSET
566566
param_index = 0
567-
if fixturedef.params is not None:
567+
has_params = fixturedef.params is not None
568+
fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
569+
if has_params and fixtures_not_supported:
570+
msg = (
571+
"{name} does not support fixtures, maybe unittest.TestCase subclass?\n"
572+
"Node id: {nodeid}\n"
573+
"Function type: {typename}"
574+
).format(
575+
name=funcitem.name,
576+
nodeid=funcitem.nodeid,
577+
typename=type(funcitem).__name__,
578+
)
579+
fail(msg)
580+
if has_params:
568581
frame = inspect.stack()[3]
569582
frameinfo = inspect.getframeinfo(frame[0])
570583
source_path = frameinfo.filename
@@ -573,9 +586,11 @@ def _compute_fixture_value(self, fixturedef):
573586
if source_path.relto(funcitem.config.rootdir):
574587
source_path = source_path.relto(funcitem.config.rootdir)
575588
msg = (
576-
"The requested fixture has no parameter defined for the "
577-
"current test.\n\nRequested fixture '{}' defined in:\n{}"
589+
"The requested fixture has no parameter defined for test:\n"
590+
" {}\n\n"
591+
"Requested fixture '{}' defined in:\n{}"
578592
"\n\nRequested here:\n{}:{}".format(
593+
funcitem.nodeid,
579594
fixturedef.argname,
580595
getlocation(fixturedef.func, funcitem.config.rootdir),
581596
source_path,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import pytest
2+
import unittest
3+
4+
5+
@pytest.fixture(params=[1, 2])
6+
def two(request):
7+
return request.param
8+
9+
10+
@pytest.mark.usefixtures("two")
11+
class TestSomethingElse(unittest.TestCase):
12+
def test_two(self):
13+
pass

testing/python/fixture.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,7 +3606,8 @@ def test_foo(request, get_named_fixture):
36063606
result = testdir.runpytest()
36073607
result.stdout.fnmatch_lines(
36083608
"""
3609-
E*Failed: The requested fixture has no parameter defined for the current test.
3609+
E*Failed: The requested fixture has no parameter defined for test:
3610+
E* test_call_from_fixture.py::test_foo
36103611
E*
36113612
E*Requested fixture 'fix_with_param' defined in:
36123613
E*test_call_from_fixture.py:4
@@ -3632,7 +3633,8 @@ def test_foo(request):
36323633
result = testdir.runpytest()
36333634
result.stdout.fnmatch_lines(
36343635
"""
3635-
E*Failed: The requested fixture has no parameter defined for the current test.
3636+
E*Failed: The requested fixture has no parameter defined for test:
3637+
E* test_call_from_test.py::test_foo
36363638
E*
36373639
E*Requested fixture 'fix_with_param' defined in:
36383640
E*test_call_from_test.py:4
@@ -3662,7 +3664,8 @@ def test_foo(request):
36623664
result = testdir.runpytest()
36633665
result.stdout.fnmatch_lines(
36643666
"""
3665-
E*Failed: The requested fixture has no parameter defined for the current test.
3667+
E*Failed: The requested fixture has no parameter defined for test:
3668+
E* test_external_fixture.py::test_foo
36663669
E*
36673670
E*Requested fixture 'fix_with_param' defined in:
36683671
E*conftest.py:4
@@ -3705,7 +3708,8 @@ def test_foo(request):
37053708
result = testdir.runpytest()
37063709
result.stdout.fnmatch_lines(
37073710
"""
3708-
E*Failed: The requested fixture has no parameter defined for the current test.
3711+
E*Failed: The requested fixture has no parameter defined for test:
3712+
E* test_foos.py::test_foo
37093713
E*
37103714
E*Requested fixture 'fix_with_param' defined in:
37113715
E*fix.py:4

testing/test_unittest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,3 +1010,15 @@ def test_hello(self):
10101010
result = testdir.runpytest()
10111011
assert "should raise this exception" in result.stdout.str()
10121012
assert "ERROR at teardown of MyTestCase.test_hello" not in result.stdout.str()
1013+
1014+
1015+
def test_error_message_with_parametrized_fixtures(testdir):
1016+
testdir.copy_example("unittest/test_parametrized_fixture_error_message.py")
1017+
result = testdir.runpytest()
1018+
result.stdout.fnmatch_lines(
1019+
[
1020+
"*test_two does not support fixtures*",
1021+
"*TestSomethingElse::test_two",
1022+
"*Function type: TestCaseFunction",
1023+
]
1024+
)

0 commit comments

Comments
 (0)