pytest-flakefighters 0.0.0__py3-none-any.whl → 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
_version.py ADDED
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.1.5'
32
+ __version_tuple__ = version_tuple = (0, 1, 5)
33
+
34
+ __commit_id__ = commit_id = None
@@ -18,13 +18,14 @@ class CoverageIndependence(FlakeFighter):
18
18
  """
19
19
  Classify tests as flaky if they fail independently of passing test cases that exercise overlapping code.
20
20
 
21
+ :ivar run_live: Run detection "live" after each test. Otherwise run as a postprocessing step after the test suite.
22
+ This is always False as live classification is not supported.
21
23
  :ivar threshold: The minimum distance to consider as "similar", expressed as a proportion 0 <= threshold < 1 where 0
22
- represents no difference and 1 represents complete difference.
23
- :ivar metric: From `scipy.spatial.distance`: ['braycurtis', 'canberra', 'chebyshev', 'correlation', 'dice',
24
- 'hamming', 'jaccard', 'kulsinski', 'mahalanobis', 'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean',
25
- 'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule'].
24
+ represents no difference and 1 represents complete difference.
25
+ :ivar metric: The distance metric to use. For a full list of valid values,see the `SciPy documentation for spatial
26
+ distances <https://docs.scipy.org/doc/scipy/reference/spatial.distance.html>`_.
26
27
  :ivar linkage_method: From `scipy.cluster.hierarchy.linkage`: ['single', 'complete', 'average', 'weighted',
27
- 'centroid', 'median', 'ward']
28
+ 'centroid', 'median', 'ward']
28
29
  """
29
30
 
30
31
  def __init__(self, threshold: float = 0, metric: str = "jaccard", linkage_method="single"):
@@ -17,10 +17,11 @@ from pytest_flakefighters.flakefighters.abstract_flakefighter import FlakeFighte
17
17
 
18
18
  class DeFlaker(FlakeFighter):
19
19
  """
20
- A python equivalent of the DeFlaker algorithm from Bell et al. 2019 [10.1145/3180155.3180164].
20
+ A python equivalent of the DeFlaker algorithm from `Bell et al. (2019) <https://doi.org/10.1145/3180155.3180164>`_.
21
21
  Given the subtle differences between JUnit and pytest, this is not intended to be an exact port, but it follows
22
22
  the same general methodology of checking whether covered code has been changed between commits.
23
23
 
24
+ :ivar run_live: Run detection "live" after each test. Otherwise run as a postprocessing step after the test suite.
24
25
  :ivar root: The root directory of the Git repository.
25
26
  :ivar source_commit: The source (older) commit hash. Defaults to HEAD^ (the previous commit to target).
26
27
  :ivar target_commit: The target (newer) commit hash. Defaults to HEAD (the most recent commit).
@@ -95,8 +96,8 @@ class DeFlaker(FlakeFighter):
95
96
  Classify an execution as flaky or not.
96
97
  :return: Boolean True of the test is classed as flaky and False otherwise.
97
98
  """
98
- return not any(
99
- execution.outcome == "failed" and self.line_modified_by_target_commit(file_path, line_number)
99
+ return execution.outcome != "passed" and not any(
100
+ self.line_modified_by_target_commit(file_path, line_number)
100
101
  for file_path in execution.coverage
101
102
  for line_number in execution.coverage[file_path]
102
103
  if file_path in self.lines_changed
@@ -20,16 +20,18 @@ from pytest_flakefighters.flakefighters.abstract_flakefighter import FlakeFighte
20
20
 
21
21
  class TracebackMatching(FlakeFighter):
22
22
  """
23
- Simple text-based matching classifier from Section II.A of [Alshammari et. al.].
23
+ Simple text-based matching classifier from Section II.A of
24
+ `Alshammari et al. (2024) <https://doi.org/10.1109/ICST60714.2024.00031>`_.
24
25
  We implement text-based matching on the failure logs for each test. Each failure log is represented by its failure
25
26
  exception and stacktrace.
27
+
28
+ :ivar run_live: Run detection "live" after each test. Otherwise run as a postprocessing step after the test suite.
26
29
  """
27
30
 
28
31
  def __init__(self, run_live: bool, previous_runs: list[Run], root: str = "."):
29
32
  super().__init__(run_live)
30
33
  self.root = os.path.abspath(root)
31
34
  self.previous_runs = previous_runs
32
- print("TracebackMatching")
33
35
 
34
36
  @classmethod
35
37
  def from_config(cls, config: dict):
@@ -119,8 +121,11 @@ class TracebackMatching(FlakeFighter):
119
121
 
120
122
  class CosineSimilarity(TracebackMatching):
121
123
  """
122
- TF-IDF cosine similarity matching classifier from Section II.C of [Alshammari et. al.].
124
+ TF-IDF cosine similarity matching classifier from Section II.C of
125
+ `Alshammari et al. (2024) <https://doi.org/10.1109/ICST60714.2024.00031>`_.
123
126
  Test executions are classified as flaky if the stack trace is sufficiently similar to a previous flaky execution.
127
+
128
+ :ivar run_live: Run detection "live" after each test. Otherwise run as a postprocessing step after the test suite.
124
129
  """
125
130
 
126
131
  def __init__(self, run_live: bool, previous_runs: list[Run], root: str = ".", threshold: float = 1):
@@ -16,7 +16,7 @@ class Profiler:
16
16
 
17
17
  :ivar coverage_data: The (potentially) covered lines for each module.
18
18
  :ivar function_defs: The lines that define a given function in a given module, accessed as
19
- `function_defs[module][function]`.
19
+ `function_defs[module][function]`.
20
20
  """
21
21
 
22
22
  def __init__(self):
@@ -132,7 +132,12 @@ def pytest_configure(config: pytest.Config):
132
132
 
133
133
  flakefighters = []
134
134
  if flakefighter_configs is not None:
135
- flakefighter_configs = yaml.safe_load(flakefighter_configs.value)
135
+ if isinstance(flakefighter_configs, str):
136
+ flakefighter_configs = yaml.safe_load(flakefighter_configs)
137
+ elif hasattr(flakefighter_configs, "value"):
138
+ flakefighter_configs = yaml.safe_load(flakefighter_configs.value)
139
+ else:
140
+ raise TypeError(f"Unexpected type for config: {type(flakefighter_configs)}")
136
141
  for flakefighter in algorithms:
137
142
  if flakefighter.name in flakefighter_configs:
138
143
  flakefighters.append(
@@ -193,7 +193,7 @@ class FlakeFighterPlugin: # pylint: disable=R0902
193
193
  :param config: The pytest config object.
194
194
  :returns: The test status.
195
195
  """
196
- if getattr(report, "flaky", False):
196
+ if getattr(report, "flaky", False) and not report.passed:
197
197
  return report.outcome, "F", ("FLAKY", {"yellow": True})
198
198
  return None
199
199
 
@@ -81,7 +81,7 @@ class PreviouslyFlaky(FlakyFailure):
81
81
  def rerun(self, report: pytest.TestReport) -> bool:
82
82
  """
83
83
  :return: Boolean true if a test is a flaky failure or has previously been marked as flaky and has the same name
84
- as the current test.
84
+ as the current test.
85
85
  """
86
86
  return super().rerun(report) or any(test.name == report.nodeid for test in self.previously_flaky)
87
87
 
@@ -1,32 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-flakefighters
3
- Version: 0.0.0
3
+ Version: 0.1.5
4
4
  Summary: Pytest plugin implementing flaky test failure detection and classification.
5
5
  Author: TestFLARE Team
6
- License:
7
- The MIT License (MIT)
8
-
9
- Copyright (c) 2025 TestFLARE Team
10
-
11
- Permission is hereby granted, free of charge, to any person obtaining a copy
12
- of this software and associated documentation files (the "Software"), to deal
13
- in the Software without restriction, including without limitation the rights
14
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
- copies of the Software, and to permit persons to whom the Software is
16
- furnished to do so, subject to the following conditions:
17
-
18
- The above copyright notice and this permission notice shall be included in
19
- all copies or substantial portions of the Software.
20
-
21
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
- THE SOFTWARE.
28
-
29
- Project-URL: Repository, https://github.com/test-flare/pytest-flakefighter
6
+ Project-URL: Repository, https://github.com/test-flare/pytest-flakefighters
30
7
  Requires-Python: >=3.10
31
8
  Description-Content-Type: text/markdown
32
9
  License-File: LICENSE
@@ -49,6 +26,8 @@ Requires-Dist: pre_commit; extra == "dev"
49
26
  Requires-Dist: sphinx-autoapi; extra == "dev"
50
27
  Requires-Dist: sphinx_rtd_theme; extra == "dev"
51
28
  Requires-Dist: tox>=4.31.0; extra == "dev"
29
+ Requires-Dist: myst_parser; extra == "dev"
30
+ Requires-Dist: nbsphinx; extra == "dev"
52
31
  Dynamic: license-file
53
32
 
54
33
  # Pytest FlakeFighters
@@ -0,0 +1,18 @@
1
+ _version.py,sha256=rdxBMYpwzYxiWk08QbPLHSAxHoDfeKWwyaJIAM0lSic,704
2
+ pytest_flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ pytest_flakefighters/database_management.py,sha256=MDwwpF8FwmFX6is9pVPye7qEOrjZXOsfXG2UI5I7uk4,7029
4
+ pytest_flakefighters/function_coverage.py,sha256=IgzWHMFgkVrc68ZjQ1o27tGxKa8WvcMcGW8RWnpFLVw,2187
5
+ pytest_flakefighters/main.py,sha256=N0yGSGA-ZLtsKRCtSCIdnw7RPVEtLnXUhnftQGHjujA,5430
6
+ pytest_flakefighters/plugin.py,sha256=0XcbZooY_hCwCI1Kg1YntiWQPUn_buDsWBcal0cbEtQ,8802
7
+ pytest_flakefighters/rerun_strategies.py,sha256=YI-spvm0dhB-gGM9IEgDz19NHvzD_XesZ8lDcBDGSJM,2536
8
+ pytest_flakefighters/flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ pytest_flakefighters/flakefighters/abstract_flakefighter.py,sha256=bchRwoNzQaFhSknT9wKDpbf3EiReHPsHsDhm5qi8y_o,1953
10
+ pytest_flakefighters/flakefighters/coverage_independence.py,sha256=5swoY1jOaaGFlZNX6PdejBFVd7Gpi3zsaW5W6toIzk8,4480
11
+ pytest_flakefighters/flakefighters/deflaker.py,sha256=g0vPS2sEiD9XWFVu_FEZAw2pVkw9vGMWFa7Do1C3sck,5388
12
+ pytest_flakefighters/flakefighters/traceback_matching.py,sha256=LheOEqCvrBDrZJm4RK4ZFFcebWs4ggP7qRiUPg8HQpM,6926
13
+ pytest_flakefighters-0.1.5.dist-info/licenses/LICENSE,sha256=tTzR2CWQMPOp-mQIQqi0cTRkaogeBUmW06blQsBLdQg,1082
14
+ pytest_flakefighters-0.1.5.dist-info/METADATA,sha256=oJo4dnKiNGWO0-kPdvAz1zyCESfAWTh87k_-P8KRwf0,4390
15
+ pytest_flakefighters-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ pytest_flakefighters-0.1.5.dist-info/entry_points.txt,sha256=xockvN1AszN2XqaET77JDIRdOafgm3DdvOtHgVw-aDU,424
17
+ pytest_flakefighters-0.1.5.dist-info/top_level.txt,sha256=bWwe0xVZ_l2CP8KSnztW6FafZKQZ7zUTMa1U32geY28,30
18
+ pytest_flakefighters-0.1.5.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- pytest_flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- pytest_flakefighters/database_management.py,sha256=MDwwpF8FwmFX6is9pVPye7qEOrjZXOsfXG2UI5I7uk4,7029
3
- pytest_flakefighters/function_coverage.py,sha256=_WAENobGFbvlbT_CZO6_Ohf8lWaspi5DrWLZd4BdbxY,2183
4
- pytest_flakefighters/main.py,sha256=u2tgDVLcQ7bbCb55aLG7Nqu5KVx_9GyRAuMBdojCHeM,5148
5
- pytest_flakefighters/plugin.py,sha256=Y3eQRK58ydO-c77PpnQ8cjWFtOVHop4yf8iAPKEO6TU,8780
6
- pytest_flakefighters/rerun_strategies.py,sha256=nu6V6sqIMTVqkMBiYek30pe_zolGtdHQwTrgtj13ZG4,2532
7
- pytest_flakefighters/flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pytest_flakefighters/flakefighters/abstract_flakefighter.py,sha256=bchRwoNzQaFhSknT9wKDpbf3EiReHPsHsDhm5qi8y_o,1953
9
- pytest_flakefighters/flakefighters/coverage_independence.py,sha256=6Ic5SN1Np7vQbvNSRgWwiSF9ReQ293mvNwcn0ZS5js8,4349
10
- pytest_flakefighters/flakefighters/deflaker.py,sha256=L0pPCWTaKaK_lr7qGh4uhI1ofJXgDr9m-CCjOk-_2KM,5248
11
- pytest_flakefighters/flakefighters/traceback_matching.py,sha256=DVH8OeoDFmBQW277ap_-e2xe8UBJWkZl5HH-iMdb_Ag,6605
12
- pytest_flakefighters-0.0.0.dist-info/licenses/LICENSE,sha256=tTzR2CWQMPOp-mQIQqi0cTRkaogeBUmW06blQsBLdQg,1082
13
- pytest_flakefighters-0.0.0.dist-info/METADATA,sha256=rm_arh8KcYnTVM-qEaJNFyC_JSRvJ7hYhJugNak-9vg,5574
14
- pytest_flakefighters-0.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- pytest_flakefighters-0.0.0.dist-info/entry_points.txt,sha256=xockvN1AszN2XqaET77JDIRdOafgm3DdvOtHgVw-aDU,424
16
- pytest_flakefighters-0.0.0.dist-info/top_level.txt,sha256=mRzzeCn_6fy5c4knXqUVx2n0d86SvnOpeJcSRUevhWg,21
17
- pytest_flakefighters-0.0.0.dist-info/RECORD,,