Skip to content

Commit

Permalink
Add --used-fixtures command
Browse files Browse the repository at this point in the history
  • Loading branch information
malthejorgensen committed Sep 26, 2018
1 parent 9219d96 commit 5505c49
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 7 deletions.
80 changes: 73 additions & 7 deletions pytest_deadfixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
DUPLICATE_FIXTURES_HEADLINE = '\n\nYou may have some duplicate fixtures:'
UNUSED_FIXTURES_FOUND_HEADLINE = 'Hey there, I believe the following fixture(s) are not being used:'
UNUSED_FIXTURES_NOT_FOUND_HEADLINE = 'Cool, every declared fixture is being used.'
USED_FIXTURES_FOUND_HEADLINE = (
'Hey there, I believe the following fixture(s) are being used:'
)
USED_FIXTURES_NOT_FOUND_HEADLINE = 'We could not any fixtures being used'

EXIT_CODE_ERROR = 11
EXIT_CODE_SUCCESS = 0
Expand All @@ -27,6 +31,11 @@
'fixturedef, relpath, result'
)

UsedFixture = namedtuple(
'UsedFixture',
'relpath, argname, fixturedef'
)


def pytest_addoption(parser):
group = parser.getgroup('deadfixtures')
Expand All @@ -44,20 +53,37 @@ def pytest_addoption(parser):
default=False,
help='Show duplicated fixtures'
)
group.addoption(
'--used-fixtures',
action='store_true',
dest='usedfixtures',
default=False,
help='Show fixtures being used',
)


def pytest_cmdline_main(config):
if config.option.deadfixtures:
if _show_dead_fixtures(config):
return EXIT_CODE_ERROR
return EXIT_CODE_SUCCESS
elif config.option.usedfixtures:
if _show_used_fixtures(config):
return EXIT_CODE_ERROR
return EXIT_CODE_SUCCESS


def _show_dead_fixtures(config):
from _pytest.main import wrap_session
return wrap_session(config, show_dead_fixtures)


def _show_used_fixtures(config):
from _pytest.main import wrap_session

return wrap_session(config, show_used_fixtures)


def get_best_relpath(func, curdir):
loc = getlocation(func, curdir)
return curdir.bestrelpath(loc)
Expand Down Expand Up @@ -97,8 +123,10 @@ def get_fixtures(session):
return available


def get_used_fixturesdefs(session):
fixturesdefs = []
def get_used_fixtures(session):
used = []
seen = set()
curdir = py.path.local()
for test_function in session.items:
try:
info = test_function._fixtureinfo
Expand All @@ -112,8 +140,27 @@ def get_used_fixturesdefs(session):
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
if fixturedefs is None:
continue
fixturesdefs.append(fixturedefs[-1])
return fixturesdefs

for fixturedef in fixturedefs:
loc = getlocation(fixturedef.func, curdir)
if (fixturedef.argname, loc) in seen:
continue

seen.add((fixturedef.argname, loc))

module = fixturedef.func.__module__

if (
not module.startswith("_pytest.") and
not module.startswith("pytest_") and
not ('site-packages' in loc)
):
used.append(
UsedFixture(
curdir.bestrelpath(loc), fixturedef.argname, fixturedef
)
)
return used


def write_docstring(tw, doc):
Expand Down Expand Up @@ -201,11 +248,14 @@ def show_dead_fixtures(config, session):
tw = _pytest.config.create_terminal_writer(config)
verbose = config.getvalue('verbose')

used_fixtures = get_used_fixturesdefs(session)
used_fixturedefs = [f.fixturedef for f in get_used_fixtures(session)]
available_fixtures = get_fixtures(session)

unused_fixtures = [fixture for fixture in available_fixtures
if fixture.fixturedef not in used_fixtures]
unused_fixtures = [
fixture
for fixture in available_fixtures
if fixture.fixturedef not in used_fixturedefs
]

tw.line()
if unused_fixtures:
Expand All @@ -214,3 +264,19 @@ def show_dead_fixtures(config, session):
else:
tw.line(UNUSED_FIXTURES_NOT_FOUND_HEADLINE, green=True)
return unused_fixtures


def show_used_fixtures(config, session):
session.perform_collect()
tw = _pytest.config.create_terminal_writer(config)
verbose = config.getvalue('verbose')

used_fixtures = get_used_fixtures(session)

tw.line()
if used_fixtures:
tw.line(USED_FIXTURES_FOUND_HEADLINE, green=True)
write_fixtures(tw, used_fixtures, verbose)
else:
tw.line(USED_FIXTURES_NOT_FOUND_HEADLINE, red=True)
return used_fixtures
48 changes: 48 additions & 0 deletions tests/test_deadfixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ def test_simple():

assert message not in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'autouse_fixture',
'test_dont_list_autouse_fixture'
)

assert message in result.stdout.str()


def test_dont_list_same_file_fixture(testdir, message_template):
testdir.makepyfile("""
Expand All @@ -84,6 +92,14 @@ def test_simple(same_file_fixture):

assert message not in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'same_file_fixture',
'test_dont_list_same_file_fixture'
)

assert message in result.stdout.str()


def test_list_same_file_unused_fixture(testdir, message_template):
testdir.makepyfile("""
Expand All @@ -107,6 +123,14 @@ def test_simple():

assert message in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'same_file_fixture',
'test_list_same_file_unused_fixture'
)

assert message not in result.stdout.str()


def test_dont_list_conftest_fixture(testdir, message_template):
testdir.makepyfile(conftest="""
Expand Down Expand Up @@ -134,6 +158,14 @@ def test_conftest_fixture(conftest_fixture):

assert message not in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'conftest_fixture',
'conftest'
)

assert message in result.stdout.str()


def test_list_conftest_unused_fixture(testdir, message_template):
testdir.makepyfile(conftest="""
Expand Down Expand Up @@ -161,6 +193,14 @@ def test_conftest_fixture():

assert message in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'conftest_fixture',
'conftest'
)

assert message not in result.stdout.str()


def test_dont_list_decorator_usefixtures(testdir, message_template):
testdir.makepyfile("""
Expand All @@ -185,6 +225,14 @@ def test_decorator_usefixtures():

assert message not in result.stdout.str()

result = testdir.runpytest('--used-fixtures')
message = message_template.format(
'decorator_usefixtures',
'test_dont_list_decorator_usefixtures'
)

assert message in result.stdout.str()


def test_write_docs_when_verbose(testdir):
testdir.makepyfile("""
Expand Down

0 comments on commit 5505c49

Please sign in to comment.