Skip to content

Commit 4be2316

Browse files
author
Israel Fruchter (ifruchte)
committed
Adding pydot --fixture-graph
1 parent f106e48 commit 4be2316

File tree

3 files changed

+97
-1
lines changed

3 files changed

+97
-1
lines changed

README.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,49 @@ Output can look like this:
4747
tests/fixtures/order.py:30
4848
tests/unit/api/conftest.py:261
4949

50+
You can also generate the usage fixture graph like that:
51+
52+
.. sourcecode::
53+
pytest --fixture-graph -s
54+
55+
The Output would be like that:
56+
57+
.. sourcecode::
58+
============================= test session starts =============================
59+
platform win32 -- Python 2.7.10, pytest-3.3.1, py-1.5.2, pluggy-0.6.0
60+
rootdir: C:\Users\ifruchte\Projects\pytest-fixture-tools, inifile: tox.ini
61+
plugins: pep8-1.0.6, cov-2.5.1, fixture-tools-1.0.0
62+
collected 7 items
63+
64+
pytest_fixture_tools\__init__.py . [ 14%]
65+
pytest_fixture_tools\plugin.py . [ 28%]
66+
tests\__init__.py . [ 42%]
67+
tests\conftest.py . [ 57%]
68+
tests\test_fixture_duplicates.py .
69+
-------------------------------- fixture-graph --------------------------------
70+
created at artifacts/fixture-graph-tests-test_fixture_duplicates.py__test_there_are_not_fixture_duplicates.dot.
71+
You can convert it to a PNG using 'dot -Tpng artifacts/fixture-graph-tests-test_fixture_duplicates.py__test_there_are_not_fixture_duplicates.dot -o artifacts/fixture-graph-tests-test_fixture_duplicates.py__test_there_are_not_fixture_duplicates.png'
72+
============================= test session starts =============================
73+
platform win32 -- Python 2.7.10, pytest-3.3.1, py-1.5.2, pluggy-0.6.0
74+
rootdir: c:\users\ifruchte\appdata\local\temp\pytest-of-ifruchte\pytest-445\test_there_are_not_fixture_duplicates0, inifile:
75+
plugins: pep8-1.0.6, cov-2.5.1, fixture-tools-1.0.0
76+
collected 2 items
77+
78+
======================== no tests ran in 0.06 seconds =========================
79+
.s [100%]
80+
81+
===================== 6 passed, 1 skipped in 0.29 seconds =====================
82+
83+
And running the hinted command:
84+
85+
.. sourcecode::
86+
dot -Tpng artifacts/fixture-graph-tests-test_fixture_duplicates.py__test_there_are_not_fixture_duplicates.dot -o artifacts/fixture-graph-tests-test_fixture_duplicates.py__test_there_are_not_fixture_duplicates.png
87+
88+
would provide this output, that can help under a test that depend on large amount of fixtures:
89+
90+
.. image:: imgs/graph_example.png
91+
:alt: alternate text
92+
:align: right
5093

5194
Contact
5295
-------

pytest_fixture_tools/plugin.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
11
"""Pytest fixture tools plugin."""
22

33
import py
4+
import os
5+
import errno
46

57
from _pytest.python import getlocation
68
from collections import defaultdict
79

10+
import pydot
11+
812
tw = py.io.TerminalWriter()
913
verbose = 1
1014

1115

16+
def mkdir_recursive(path):
17+
try:
18+
os.makedirs(path)
19+
except OSError as exc:
20+
if exc.errno == errno.EEXIST and os.path.isdir(path):
21+
pass
22+
else:
23+
raise
24+
25+
1226
def pytest_addoption(parser):
1327
"""Add commandline options show-fixture-duplicates and fixture."""
1428
group = parser.getgroup("general")
@@ -18,6 +32,9 @@ def pytest_addoption(parser):
1832
group.addoption('--fixture',
1933
action="store", type=str, dest="fixture_name", default='',
2034
help="Name of specific fixture for which you want to get duplicates")
35+
group.addoption('--fixture-graph',
36+
action="store_true", dest="fixture_graph", default=False,
37+
help="create .dot fixture graph for each test")
2138

2239

2340
def pytest_cmdline_main(config):
@@ -93,3 +110,39 @@ def _show_fixture_duplicates_main(config, session):
93110
for argname, fixtures in available:
94111
print_duplicates(argname, fixtures, previous_argname)
95112
previous_argname = argname
113+
114+
115+
def pytest_runtest_setup(item):
116+
if item.config.option.fixture_graph and hasattr(item, "_fixtureinfo"):
117+
curdir = py.path.local()
118+
# fixtures came from function parameters names
119+
data = dict()
120+
data['func_args'] = item._fixtureinfo.argnames, 'red'
121+
for fixture_name, fixture_data in list(item._fixtureinfo.name2fixturedefs.items()):
122+
123+
loc = getlocation(fixture_data[0].func, curdir)
124+
if 'pytest_vgw' in loc:
125+
color = 'yellow'
126+
else:
127+
color = 'green'
128+
data[fixture_name] = fixture_data[0].argnames, color
129+
130+
graph = pydot.Dot(graph_type='digraph')
131+
132+
for name, depended_list in list(data.items()):
133+
depended_list, color = depended_list
134+
135+
node = pydot.Node(name, style="filled", fillcolor=color)
136+
graph.add_node(node)
137+
for i in depended_list:
138+
edge = pydot.Edge(node, i)
139+
graph.add_edge(edge)
140+
141+
log_dir = os.environ.get('LOG_DEST_DIR', 'artifacts')
142+
mkdir_recursive(log_dir)
143+
filename = "{0}/fixture-graph-{1}".format(log_dir, item._nodeid.replace(":", "_").replace("/", "-"))
144+
graph.write(filename + ".dot")
145+
tw.line()
146+
tw.sep("-", "fixture-graph")
147+
tw.line("created at {}.dot.".format(filename))
148+
tw.line("You can convert it to a PNG using 'dot -Tpng {0}.dot -o {0}.png'".format(filename))

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def run_tests(self):
5252
] + [('Programming Language :: Python :: %s' % x) for x in '2.6 2.7 3.0 3.1 3.2 3.3'.split()],
5353
cmdclass={'test': ToxTestCommand},
5454
install_requires=[
55-
'pytest',
55+
'pytest', 'pydot'
5656
],
5757
# the following makes a plugin available to py.test
5858
entry_points={

0 commit comments

Comments
 (0)