(
self, config: Config, items: List[nodes.Item]
)
| 326 | |
| 327 | @hookimpl(hookwrapper=True, tryfirst=True) |
| 328 | def pytest_collection_modifyitems( |
| 329 | self, config: Config, items: List[nodes.Item] |
| 330 | ) -> Generator[None, None, None]: |
| 331 | yield |
| 332 | |
| 333 | if not self.active: |
| 334 | return |
| 335 | |
| 336 | if self.lastfailed: |
| 337 | previously_failed = [] |
| 338 | previously_passed = [] |
| 339 | for item in items: |
| 340 | if item.nodeid in self.lastfailed: |
| 341 | previously_failed.append(item) |
| 342 | else: |
| 343 | previously_passed.append(item) |
| 344 | self._previously_failed_count = len(previously_failed) |
| 345 | |
| 346 | if not previously_failed: |
| 347 | # Running a subset of all tests with recorded failures |
| 348 | # only outside of it. |
| 349 | self._report_status = "%d known failures not in selected tests" % ( |
| 350 | len(self.lastfailed), |
| 351 | ) |
| 352 | else: |
| 353 | if self.config.getoption("lf"): |
| 354 | items[:] = previously_failed |
| 355 | config.hook.pytest_deselected(items=previously_passed) |
| 356 | else: # --failedfirst |
| 357 | items[:] = previously_failed + previously_passed |
| 358 | |
| 359 | noun = "failure" if self._previously_failed_count == 1 else "failures" |
| 360 | suffix = " first" if self.config.getoption("failedfirst") else "" |
| 361 | self._report_status = "rerun previous {count} {noun}{suffix}".format( |
| 362 | count=self._previously_failed_count, suffix=suffix, noun=noun |
| 363 | ) |
| 364 | |
| 365 | if self._skipped_files > 0: |
| 366 | files_noun = "file" if self._skipped_files == 1 else "files" |
| 367 | self._report_status += " (skipped {files} {files_noun})".format( |
| 368 | files=self._skipped_files, files_noun=files_noun |
| 369 | ) |
| 370 | else: |
| 371 | self._report_status = "no previously failed tests, " |
| 372 | if self.config.getoption("last_failed_no_failures") == "none": |
| 373 | self._report_status += "deselecting all items." |
| 374 | config.hook.pytest_deselected(items=items[:]) |
| 375 | items[:] = [] |
| 376 | else: |
| 377 | self._report_status += "not deselecting items." |
| 378 | |
| 379 | def pytest_sessionfinish(self, session: Session) -> None: |
| 380 | config = self.config |
no test coverage detected