TestRun defines the set of tests that should be run together in a single pytest invocation. It'll either be a whole test file or a subset of a test file. This class assumes that we won't always know the full set of TestClasses in a test file. So it's designed to include or exclude
| 4 | |
| 5 | |
| 6 | class TestRun: |
| 7 | """ |
| 8 | TestRun defines the set of tests that should be run together in a single pytest invocation. |
| 9 | It'll either be a whole test file or a subset of a test file. |
| 10 | |
| 11 | This class assumes that we won't always know the full set of TestClasses in a test file. |
| 12 | So it's designed to include or exclude explicitly requested TestClasses, while having accepting |
| 13 | that there will be an ambiguous set of "unknown" test classes that are not expliclty called out. |
| 14 | Those manifest as tests that haven't been explicitly excluded. |
| 15 | """ |
| 16 | |
| 17 | test_file: str |
| 18 | _exclued: Set[str] # Tests that should be excluded from this test run |
| 19 | _included: Set[str] # If non-empy, only these tests should be run in this test run |
| 20 | |
| 21 | def __init__( |
| 22 | self, |
| 23 | name: str, |
| 24 | excluded: Optional[Iterable[str]] = None, |
| 25 | included: Optional[Iterable[str]] = None, |
| 26 | ) -> None: |
| 27 | self._excluded = set() |
| 28 | self._included = set() |
| 29 | |
| 30 | if excluded and included: |
| 31 | raise ValueError("Can't specify both included and excluded") |
| 32 | |
| 33 | if "::" in name: |
| 34 | assert ( |
| 35 | not included and not excluded |
| 36 | ), "Can't specify included or excluded tests when specifying a test class in the file name" |
| 37 | self.test_file, test_class = name.split("::") |
| 38 | self._included.add(test_class) |
| 39 | else: |
| 40 | self.test_file = name |
| 41 | |
| 42 | # For testing purposes |
| 43 | if excluded: |
| 44 | self._excluded = set(excluded) |
| 45 | if included: |
| 46 | self._included = set(included) |
| 47 | |
| 48 | @staticmethod |
| 49 | def empty() -> "TestRun": |
| 50 | return TestRun("") |
| 51 | |
| 52 | def is_empty(self) -> bool: |
| 53 | # Lack of a test_file means that this is an empty run, |
| 54 | # which means there is nothing to run. It's the zero. |
| 55 | return not self.test_file |
| 56 | |
| 57 | def is_full_file(self) -> bool: |
| 58 | return not self._included and not self._excluded |
| 59 | |
| 60 | def included(self) -> Set[str]: |
| 61 | return self._included.copy() |
| 62 | |
| 63 | def excluded(self) -> Set[str]: |
no outgoing calls
searching dependent graphs…