Merge pull request #3295 from brianmaissy/feature/last-failed-no-failures-behavior
implemented --last-failed-no-failures
This commit is contained in:
		
						commit
						d03e38941b
					
				| 
						 | 
					@ -112,11 +112,12 @@ class LFPlugin(object):
 | 
				
			||||||
        self.active = any(config.getoption(key) for key in active_keys)
 | 
					        self.active = any(config.getoption(key) for key in active_keys)
 | 
				
			||||||
        self.lastfailed = config.cache.get("cache/lastfailed", {})
 | 
					        self.lastfailed = config.cache.get("cache/lastfailed", {})
 | 
				
			||||||
        self._previously_failed_count = None
 | 
					        self._previously_failed_count = None
 | 
				
			||||||
 | 
					        self._no_failures_behavior = self.config.getoption('last_failed_no_failures')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_report_collectionfinish(self):
 | 
					    def pytest_report_collectionfinish(self):
 | 
				
			||||||
        if self.active:
 | 
					        if self.active:
 | 
				
			||||||
            if not self._previously_failed_count:
 | 
					            if not self._previously_failed_count:
 | 
				
			||||||
                mode = "run all (no recorded failures)"
 | 
					                mode = "run {} (no recorded failures)".format(self._no_failures_behavior)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                noun = 'failure' if self._previously_failed_count == 1 else 'failures'
 | 
					                noun = 'failure' if self._previously_failed_count == 1 else 'failures'
 | 
				
			||||||
                suffix = " first" if self.config.getoption(
 | 
					                suffix = " first" if self.config.getoption(
 | 
				
			||||||
| 
						 | 
					@ -144,7 +145,8 @@ class LFPlugin(object):
 | 
				
			||||||
            self.lastfailed[report.nodeid] = True
 | 
					            self.lastfailed[report.nodeid] = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_collection_modifyitems(self, session, config, items):
 | 
					    def pytest_collection_modifyitems(self, session, config, items):
 | 
				
			||||||
        if self.active and self.lastfailed:
 | 
					        if self.active:
 | 
				
			||||||
 | 
					            if self.lastfailed:
 | 
				
			||||||
                previously_failed = []
 | 
					                previously_failed = []
 | 
				
			||||||
                previously_passed = []
 | 
					                previously_passed = []
 | 
				
			||||||
                for item in items:
 | 
					                for item in items:
 | 
				
			||||||
| 
						 | 
					@ -162,6 +164,9 @@ class LFPlugin(object):
 | 
				
			||||||
                    config.hook.pytest_deselected(items=previously_passed)
 | 
					                    config.hook.pytest_deselected(items=previously_passed)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    items[:] = previously_failed + previously_passed
 | 
					                    items[:] = previously_failed + previously_passed
 | 
				
			||||||
 | 
					            elif self._no_failures_behavior == 'none':
 | 
				
			||||||
 | 
					                config.hook.pytest_deselected(items=items)
 | 
				
			||||||
 | 
					                items[:] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_sessionfinish(self, session):
 | 
					    def pytest_sessionfinish(self, session):
 | 
				
			||||||
        config = self.config
 | 
					        config = self.config
 | 
				
			||||||
| 
						 | 
					@ -230,6 +235,12 @@ def pytest_addoption(parser):
 | 
				
			||||||
    parser.addini(
 | 
					    parser.addini(
 | 
				
			||||||
        "cache_dir", default='.pytest_cache',
 | 
					        "cache_dir", default='.pytest_cache',
 | 
				
			||||||
        help="cache directory path.")
 | 
					        help="cache directory path.")
 | 
				
			||||||
 | 
					    group.addoption(
 | 
				
			||||||
 | 
					        '--lfnf', '--last-failed-no-failures', action='store',
 | 
				
			||||||
 | 
					        dest='last_failed_no_failures', choices=('all', 'none'), default='all',
 | 
				
			||||||
 | 
					        help='change the behavior when no test failed in the last run or no '
 | 
				
			||||||
 | 
					             'information about the last failures was found in the cache'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_cmdline_main(config):
 | 
					def pytest_cmdline_main(config):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					New ``--last-failed-no-failures`` command-line option that allows to specify the behavior of the cache plugin's ```--last-failed`` feature when no tests failed in the last run (or no cache was found): ``none`` or ``all`` (the default).
 | 
				
			||||||
| 
						 | 
					@ -156,6 +156,16 @@ New ``--nf``, ``--new-first`` options: run new tests first followed by the rest
 | 
				
			||||||
of the tests, in both cases tests are also sorted by the file modified time,
 | 
					of the tests, in both cases tests are also sorted by the file modified time,
 | 
				
			||||||
with more recent files coming first.
 | 
					with more recent files coming first.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Behavior when no tests failed in the last run
 | 
				
			||||||
 | 
					---------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When no tests failed in the last run, or when no cached ``lastfailed`` data was
 | 
				
			||||||
 | 
					found, ``pytest`` can be configured either to run all of the tests or no tests,
 | 
				
			||||||
 | 
					using the ``--last-failed-no-failures`` option, which takes one of the following values::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pytest --last-failed-no-failures all    # run all tests (default behavior)
 | 
				
			||||||
 | 
					    pytest --last-failed-no-failures none   # run no tests and exit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The new config.cache object
 | 
					The new config.cache object
 | 
				
			||||||
--------------------------------
 | 
					--------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -604,6 +604,36 @@ class TestLastFailed(object):
 | 
				
			||||||
        result.stdout.fnmatch_lines('*4 passed*')
 | 
					        result.stdout.fnmatch_lines('*4 passed*')
 | 
				
			||||||
        assert self.get_cached_last_failed(testdir) == []
 | 
					        assert self.get_cached_last_failed(testdir) == []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_lastfailed_no_failures_behavior_all_passed(self, testdir):
 | 
				
			||||||
 | 
					        testdir.makepyfile("""
 | 
				
			||||||
 | 
					            def test_1():
 | 
				
			||||||
 | 
					                assert True
 | 
				
			||||||
 | 
					            def test_2():
 | 
				
			||||||
 | 
					                assert True
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        result = testdir.runpytest()
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*2 passed*"])
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*2 passed*"])
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf", "--lfnf", "all")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*2 passed*"])
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf", "--lfnf", "none")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*2 desel*"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_lastfailed_no_failures_behavior_empty_cache(self, testdir):
 | 
				
			||||||
 | 
					        testdir.makepyfile("""
 | 
				
			||||||
 | 
					            def test_1():
 | 
				
			||||||
 | 
					                assert True
 | 
				
			||||||
 | 
					            def test_2():
 | 
				
			||||||
 | 
					                assert False
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf", "--cache-clear")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*1 failed*1 passed*"])
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf", "--cache-clear", "--lfnf", "all")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*1 failed*1 passed*"])
 | 
				
			||||||
 | 
					        result = testdir.runpytest("--lf", "--cache-clear", "--lfnf", "none")
 | 
				
			||||||
 | 
					        result.stdout.fnmatch_lines(["*2 desel*"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestNewFirst(object):
 | 
					class TestNewFirst(object):
 | 
				
			||||||
    def test_newfirst_usecase(self, testdir):
 | 
					    def test_newfirst_usecase(self, testdir):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue