Source code for _pytest.stepwise

import pytest


[docs]def pytest_addoption(parser): group = parser.getgroup("general") group.addoption( "--sw", "--stepwise", action="store_true", dest="stepwise", help="exit on test failure and continue from last failing test next time", ) group.addoption( "--stepwise-skip", action="store_true", dest="stepwise_skip", help="ignore the first failing test but stop on the next failing test", )
[docs]@pytest.hookimpl def pytest_configure(config): if config.getvalue("stepwise"): config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin")
[docs]@pytest.hookimpl def pytest_sessionfinish(session): """Clear the list of failing tests if the plugin is not active. This might not be sensible, but has been like that, so keep it.""" config = session.config if not config.getvalue("stepwise"): config.cache.set("cache/stepwise", [])
[docs]class StepwisePlugin: def __init__(self, config): self.config = config self.session = None self.report_status = "" self.lastfailed = config.cache.get("cache/stepwise", None) self.skip = config.getvalue("stepwise_skip")
[docs] def pytest_sessionstart(self, session): self.session = session
[docs] def pytest_collection_modifyitems(self, session, config, items): if not self.lastfailed: self.report_status = "no previously failed tests, not skipping." return already_passed = [] found = False # Make a list of all tests that have been run before the last failing one. for item in items: if item.nodeid == self.lastfailed: found = True break else: already_passed.append(item) # If the previously failed test was not found among the test items, # do not skip any tests. if not found: self.report_status = "previously failed test not found, not skipping." already_passed = [] else: self.report_status = "skipping {} already passed items.".format( len(already_passed) ) for item in already_passed: items.remove(item) config.hook.pytest_deselected(items=already_passed)
[docs] def pytest_runtest_logreport(self, report): if report.failed: if self.skip: # Remove test from the failed ones (if it exists) and unset the skip option # to make sure the following tests will not be skipped. if report.nodeid == self.lastfailed: self.lastfailed = None self.skip = False else: # Mark test as the last failing and interrupt the test session. self.lastfailed = report.nodeid self.session.shouldstop = ( "Test failed, continuing from this test next run." ) else: # If the test was actually run and did pass. if report.when == "call": # Remove test from the failed ones, if exists. if report.nodeid == self.lastfailed: self.lastfailed = None
[docs] def pytest_report_collectionfinish(self): if self.config.getoption("verbose") >= 0 and self.report_status: return "stepwise: %s" % self.report_status
[docs] def pytest_sessionfinish(self, session): self.config.cache.set("cache/stepwise", self.lastfailed)