Skip to content

Commit c767eca

Browse files
committed
Close #6.
2 parents 817bcca + 5978b37 commit c767eca

File tree

5 files changed

+225
-1
lines changed

5 files changed

+225
-1
lines changed

CHANGES

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,42 @@
11
History of changes to pytest-dependency
22
=======================================
33

4+
* Version 0.3 (not yet released)
5+
6+
** Incompatible changes
7+
8+
+ Prepend the class name to the default test name for test class
9+
methods. This fixes a potential name conflict, see Issue #6.
10+
11+
If your code uses test classes and you reference test methods by
12+
their default name, you must add the class name. E.g. if you have
13+
something like:
14+
15+
class TestClass(object):
16+
17+
@pytest.mark.dependency()
18+
def test_a():
19+
pass
20+
21+
@pytest.mark.dependency(depends=["test_a"])
22+
def test_b():
23+
pass
24+
25+
you need to change this to:
26+
27+
class TestClass(object):
28+
29+
@pytest.mark.dependency()
30+
def test_a():
31+
pass
32+
33+
@pytest.mark.dependency(depends=["TestClass::test_a"])
34+
def test_b():
35+
pass
36+
37+
If you override the test name in the pytest.mark.dependency()
38+
marker, nothing need to be changed.
39+
440
* Version 0.2 (2017-05-28)
541

642
** New features

doc/examples/testclass.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import pytest
2+
3+
4+
class TestClass(object):
5+
6+
@pytest.mark.dependency()
7+
@pytest.mark.xfail(reason="deliberate fail")
8+
def test_a(self):
9+
assert False
10+
11+
@pytest.mark.dependency()
12+
def test_b(self):
13+
pass
14+
15+
@pytest.mark.dependency(depends=["TestClass::test_a"])
16+
def test_c(self):
17+
pass
18+
19+
@pytest.mark.dependency(depends=["TestClass::test_b"])
20+
def test_d(self):
21+
pass
22+
23+
@pytest.mark.dependency(depends=["TestClass::test_b", "TestClass::test_c"])
24+
def test_e(self):
25+
pass
26+
27+
28+
class TestClassNamed(object):
29+
30+
@pytest.mark.dependency(name="a")
31+
@pytest.mark.xfail(reason="deliberate fail")
32+
def test_a(self):
33+
assert False
34+
35+
@pytest.mark.dependency(name="b", depends=["a"])
36+
def test_b(self):
37+
pass
38+
39+
@pytest.mark.dependency(name="c")
40+
def test_c(self):
41+
pass
42+
43+
@pytest.mark.dependency(name="d", depends=["c"])
44+
def test_d(self):
45+
pass
46+
47+
@pytest.mark.dependency(name="e", depends=["b", "c"])
48+
def test_e(self):
49+
pass

doc/src/usage.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ set:
4949

5050
.. _usage-parametrized:
5151

52+
Using test classes
53+
------------------
54+
55+
Tests may be grouped in classes in pytest. Marking the dependencies
56+
of methods in test classes works the same way as for simple test
57+
functions. In the following example we define two test classes. Each
58+
works in the same manner as the previous examples respectively:
59+
60+
.. literalinclude:: ../examples/testclass.py
61+
62+
In `TestClass` the default names for the tests are used, which is
63+
build from the name of the class and the respective method in this
64+
case, while in `TestClassNamed` these names are overridden by an
65+
explicit name argument to the :func:`pytest.mark.dependency` marker.
66+
5267
Parametrized tests
5368
------------------
5469

pytest_dependency.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ def __init__(self):
5252
def addResult(self, item, marker, rep):
5353
name = marker.kwargs.get('name')
5454
if not name:
55-
name = item.name
55+
if item.cls:
56+
name = "%s::%s" % (item.cls.__name__, item.name)
57+
else:
58+
name = item.name
5659
status = self.results.setdefault(name, DependencyItemStatus())
5760
status.addResult(rep)
5861

tests/test_03_class.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""Usage with test classes.
2+
"""
3+
4+
import pytest
5+
6+
7+
def test_class_simple(ctestdir):
8+
"""Simple dependencies of test methods in a class.
9+
test_a() deliberately fails, some other methods depend on it, some don't.
10+
"""
11+
ctestdir.makepyfile("""
12+
import pytest
13+
14+
class TestClass(object):
15+
16+
@pytest.mark.dependency()
17+
def test_a(self):
18+
assert False
19+
20+
@pytest.mark.dependency()
21+
def test_b(self):
22+
pass
23+
24+
@pytest.mark.dependency(depends=["TestClass::test_a"])
25+
def test_c(self):
26+
pass
27+
28+
@pytest.mark.dependency(depends=["TestClass::test_b"])
29+
def test_d(self):
30+
pass
31+
32+
@pytest.mark.dependency(depends=["TestClass::test_b",
33+
"TestClass::test_c"])
34+
def test_e(self):
35+
pass
36+
""")
37+
result = ctestdir.runpytest("--verbose")
38+
result.assert_outcomes(passed=2, skipped=2, failed=1)
39+
result.stdout.fnmatch_lines("""
40+
*::TestClass::test_a FAILED
41+
*::TestClass::test_b PASSED
42+
*::TestClass::test_c SKIPPED
43+
*::TestClass::test_d PASSED
44+
*::TestClass::test_e SKIPPED
45+
""")
46+
47+
48+
def test_class_simple_named(ctestdir):
49+
"""Mostly the same as test_class_simple(), but name the test methods
50+
now explicitely.
51+
"""
52+
ctestdir.makepyfile("""
53+
import pytest
54+
55+
class TestClassNamed(object):
56+
57+
@pytest.mark.dependency(name="a")
58+
def test_a(self):
59+
assert False
60+
61+
@pytest.mark.dependency(name="b")
62+
def test_b(self):
63+
pass
64+
65+
@pytest.mark.dependency(name="c", depends=["a"])
66+
def test_c(self):
67+
pass
68+
69+
@pytest.mark.dependency(name="d", depends=["b"])
70+
def test_d(self):
71+
pass
72+
73+
@pytest.mark.dependency(name="e", depends=["b", "c"])
74+
def test_e(self):
75+
pass
76+
""")
77+
result = ctestdir.runpytest("--verbose")
78+
result.assert_outcomes(passed=2, skipped=2, failed=1)
79+
result.stdout.fnmatch_lines("""
80+
*::TestClassNamed::test_a FAILED
81+
*::TestClassNamed::test_b PASSED
82+
*::TestClassNamed::test_c SKIPPED
83+
*::TestClassNamed::test_d PASSED
84+
*::TestClassNamed::test_e SKIPPED
85+
""")
86+
87+
88+
def test_class_default_name(ctestdir):
89+
"""Issue #6: for methods of test classes, the default name used to be
90+
the method name. This could have caused conflicts if there is a
91+
function having the same name outside the class. In the following
92+
example, before fixing this issue, the method test_a() of class
93+
TestClass would have shadowed the failure of function test_a().
94+
95+
Now the class name is prepended to the default test name, removing
96+
this conflict.
97+
"""
98+
ctestdir.makepyfile("""
99+
import pytest
100+
101+
@pytest.mark.dependency()
102+
def test_a():
103+
assert False
104+
105+
class TestClass(object):
106+
107+
@pytest.mark.dependency()
108+
def test_a(self):
109+
pass
110+
111+
@pytest.mark.dependency(depends=["test_a"])
112+
def test_b():
113+
pass
114+
""")
115+
result = ctestdir.runpytest("--verbose")
116+
result.assert_outcomes(passed=1, skipped=1, failed=1)
117+
result.stdout.fnmatch_lines("""
118+
*::test_a FAILED
119+
*::TestClass::test_a PASSED
120+
*::test_b SKIPPED
121+
""")

0 commit comments

Comments
 (0)