pytest-flakefighters 0.1.5__py3-none-any.whl → 0.2.0__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 CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.1.5'
32
- __version_tuple__ = version_tuple = (0, 1, 5)
31
+ __version__ = version = '0.2.0'
32
+ __version_tuple__ = version_tuple = (0, 2, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -77,6 +77,8 @@ class Test(Base):
77
77
  """
78
78
 
79
79
  run_id: Mapped[int] = Column(Integer, ForeignKey("run.id"), nullable=False)
80
+ fspath: Mapped[str] = Column(String)
81
+ line_no: Mapped[int] = Column(Integer)
80
82
  name: Mapped[str] = Column(String)
81
83
  skipped: Mapped[bool] = Column(Boolean, default=False)
82
84
  executions = relationship(
@@ -177,7 +179,7 @@ class FlakefighterResult(Base): # pylint: disable=R0902
177
179
  flaky: Mapped[bool] = Column(Boolean)
178
180
 
179
181
  __table_args__ = (
180
- CheckConstraint("(test_execution_id IS NOT NULL) + (test_id IS NOT NULL) = 1", name="check_test_id_not_null"),
182
+ CheckConstraint("NOT (test_execution_id IS NULL AND test_id IS NULL)", name="check_test_id_not_null"),
181
183
  )
182
184
 
183
185
 
@@ -2,6 +2,7 @@
2
2
  This module implements the DeFlaker FlakeFighter.
3
3
  """
4
4
 
5
+ import ast
5
6
  import os
6
7
 
7
8
  import git
@@ -63,6 +64,18 @@ class DeFlaker(FlakeFighter):
63
64
  range(hunk.target_start, hunk.target_start + hunk.target_length)
64
65
  )
65
66
 
67
+ # Need to know method declaration lines so we can ignore new/changed test methods
68
+ self.method_declarations = {}
69
+ for file, lines in self.lines_changed.items():
70
+ with open(file) as f:
71
+ tree = ast.parse(f.read())
72
+
73
+ self.method_declarations[file] = [
74
+ node.lineno
75
+ for node in ast.walk(tree)
76
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.lineno in lines
77
+ ]
78
+
66
79
  @classmethod
67
80
  def from_config(cls, config: dict):
68
81
  """
@@ -82,14 +95,14 @@ class DeFlaker(FlakeFighter):
82
95
  """
83
96
  return {"root": self.repo_root, "source_commit": self.source_commit, "target_commit": self.target_commit}
84
97
 
85
- def line_modified_by_target_commit(self, file_path: str, line_number: int) -> bool:
98
+ def line_modified_by_target_commit(self, file_path: str, line_no: int) -> bool:
86
99
  """
87
100
  Returns true if the given line in the file has been modified by the present commit.
88
101
 
89
102
  :param file_path: The file to check.
90
- :param line_number: The line number to check.
103
+ :param line_no: The line number to check.
91
104
  """
92
- return line_number in self.lines_changed.get(file_path, [])
105
+ return line_no in self.lines_changed.get(file_path, [])
93
106
 
94
107
  def _flaky_execution(self, execution):
95
108
  """
@@ -97,10 +110,11 @@ class DeFlaker(FlakeFighter):
97
110
  :return: Boolean True of the test is classed as flaky and False otherwise.
98
111
  """
99
112
  return execution.outcome != "passed" and not any(
100
- self.line_modified_by_target_commit(file_path, line_number)
113
+ self.line_modified_by_target_commit(file_path, line_no)
101
114
  for file_path in execution.coverage
102
- for line_number in execution.coverage[file_path]
115
+ for line_no in execution.coverage[file_path]
103
116
  if file_path in self.lines_changed
117
+ and (line_no == execution.test.line_no or line_no not in self.method_declarations.get(file_path, []))
104
118
  )
105
119
 
106
120
  def flaky_test_live(self, execution: TestExecution):
@@ -137,9 +137,18 @@ class FlakeFighterPlugin: # pylint: disable=R0902
137
137
  :return: The return value is not used, but only stops further processing.
138
138
  """
139
139
  item.execution_count = 0
140
- executions = []
141
140
  skipped = False
142
141
 
142
+ fspath, line_inx, _ = item.location
143
+
144
+ test = Test( # pylint: disable=E1123
145
+ name=item.nodeid,
146
+ fspath=fspath,
147
+ line_no=line_inx + 1, # need to add one to the line index because this indexes from zero
148
+ skipped=skipped,
149
+ )
150
+ self.run.tests.append(test)
151
+
143
152
  for _ in range(self.rerun_strategy.max_reruns + 1):
144
153
  item.execution_count += 1
145
154
  item.ihook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location)
@@ -164,8 +173,7 @@ class FlakeFighterPlugin: # pylint: disable=R0902
164
173
  },
165
174
  exception=report.exception,
166
175
  )
167
- item.test_execution = test_execution
168
- executions.append(test_execution)
176
+ test.executions.append(test_execution)
169
177
  for ff in filter(lambda ff: ff.run_live, self.flakefighters):
170
178
  ff.flaky_test_live(test_execution)
171
179
  report.flaky = any(result.flaky for result in test_execution.flakefighter_results)
@@ -176,12 +184,6 @@ class FlakeFighterPlugin: # pylint: disable=R0902
176
184
  break # Skip further reruns
177
185
 
178
186
  item.ihook.pytest_runtest_logfinish(nodeid=item.nodeid, location=item.location)
179
- test = Test( # pylint: disable=E1123
180
- name=item.nodeid,
181
- skipped=skipped,
182
- executions=executions,
183
- )
184
- self.run.tests.append(test)
185
187
  return True
186
188
 
187
189
  def pytest_report_teststatus(
@@ -1,10 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-flakefighters
3
- Version: 0.1.5
3
+ Version: 0.2.0
4
4
  Summary: Pytest plugin implementing flaky test failure detection and classification.
5
5
  Author: TestFLARE Team
6
+ Project-URL: Homepage, https://test-flare.github.io/
7
+ Project-URL: Documentation, https://pytest-flakefighters.readthedocs.io
6
8
  Project-URL: Repository, https://github.com/test-flare/pytest-flakefighters
7
- Requires-Python: >=3.10
9
+ Project-URL: Issues, https://github.com/test-flare/pytest-flakefighters/issues
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Requires-Python: <3.14,>=3.10
8
16
  Description-Content-Type: text/markdown
9
17
  License-File: LICENSE
10
18
  Requires-Dist: pytest>=6.2.0
@@ -13,7 +21,7 @@ Requires-Dist: GitPython>=3.1.45
13
21
  Requires-Dist: unidiff>=0.7.5
14
22
  Requires-Dist: sqlalchemy>=2.0.43
15
23
  Requires-Dist: dotenv>=0.9.9
16
- Requires-Dist: pandas
24
+ Requires-Dist: pandas>=2.3
17
25
  Requires-Dist: scipy<=1.15
18
26
  Requires-Dist: pyyaml>=6
19
27
  Requires-Dist: scikit-learn>=1.7
@@ -28,19 +36,24 @@ Requires-Dist: sphinx_rtd_theme; extra == "dev"
28
36
  Requires-Dist: tox>=4.31.0; extra == "dev"
29
37
  Requires-Dist: myst_parser; extra == "dev"
30
38
  Requires-Dist: nbsphinx; extra == "dev"
39
+ Requires-Dist: pytest-html; extra == "dev"
40
+ Requires-Dist: pytest-json-report>=1.5; extra == "dev"
41
+ Provides-Extra: pg
42
+ Requires-Dist: psycopg2>2.9; extra == "pg"
31
43
  Dynamic: license-file
32
44
 
33
45
  # Pytest FlakeFighters
46
+ ### Pytest plugin implementing flaky test failure detection and classification.
34
47
 
48
+ [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
35
49
  [![PyPI version](https://img.shields.io/pypi/v/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
36
50
  [![Python versions](https://img.shields.io/pypi/pyversions/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
51
+ ![Test status](https://github.com/test-flare/pytest-flakefighters/actions/workflows/ci-tests.yaml/badge.svg)
52
+ [![codecov](https://codecov.io/gh/test-flare/pytest-flakefighters/branch/main/graph/badge.svg?token=04ijFVrb4a)](https://codecov.io/gh/test-flare/pytest-flakefighters)
53
+ [![Documentation Status](https://readthedocs.org/projects/causal-testing-framework/badge/?version=latest)](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
54
+ ![GitHub License](https://img.shields.io/github/license/test-flare/pytest-flakefighters)
37
55
 
38
- Pytest plugin implementing flaky test failure detection and
39
- classification.
40
56
 
41
- ------------------------------------------------------------------------
42
-
43
- This [pytest](https://github.com/pytest-dev/pytest) plugin was generated with [Cookiecutter](https://github.com/audreyr/cookiecutter) along with [\@hackebrot](https://github.com/hackebrot)\'s [cookiecutter-pytest-plugin](https://github.com/pytest-dev/cookiecutter-pytest-plugin) template.
44
57
 
45
58
  ## Features
46
59
 
@@ -93,3 +106,7 @@ Both extend the base class `FlakeFighter` and implement the `flaky_failure` meth
93
106
  ## Issues
94
107
 
95
108
  If you encounter any problems, please [file an issue](https://github.com/test-flare/pytest-flakefighters/issues) along with a detailed description.
109
+
110
+ ------------------------------------------------------------------------
111
+
112
+ This [pytest](https://github.com/pytest-dev/pytest) plugin was generated with [Cookiecutter](https://github.com/audreyr/cookiecutter) along with [\@hackebrot](https://github.com/hackebrot)\'s [cookiecutter-pytest-plugin](https://github.com/pytest-dev/cookiecutter-pytest-plugin) template.
@@ -1,18 +1,18 @@
1
- _version.py,sha256=rdxBMYpwzYxiWk08QbPLHSAxHoDfeKWwyaJIAM0lSic,704
1
+ _version.py,sha256=Dg8AmJomLVpjKL6prJylOONZAPRtB86LOce7dorQS_A,704
2
2
  pytest_flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- pytest_flakefighters/database_management.py,sha256=MDwwpF8FwmFX6is9pVPye7qEOrjZXOsfXG2UI5I7uk4,7029
3
+ pytest_flakefighters/database_management.py,sha256=mSdrP4enD6_oT941y5KAP-Jae84FihVJEvqCUFPhrss,7105
4
4
  pytest_flakefighters/function_coverage.py,sha256=IgzWHMFgkVrc68ZjQ1o27tGxKa8WvcMcGW8RWnpFLVw,2187
5
5
  pytest_flakefighters/main.py,sha256=N0yGSGA-ZLtsKRCtSCIdnw7RPVEtLnXUhnftQGHjujA,5430
6
- pytest_flakefighters/plugin.py,sha256=0XcbZooY_hCwCI1Kg1YntiWQPUn_buDsWBcal0cbEtQ,8802
6
+ pytest_flakefighters/plugin.py,sha256=kdagObAK93ab6-5lckwkBR846RPspxXen4qlEcsAjB8,8866
7
7
  pytest_flakefighters/rerun_strategies.py,sha256=YI-spvm0dhB-gGM9IEgDz19NHvzD_XesZ8lDcBDGSJM,2536
8
8
  pytest_flakefighters/flakefighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  pytest_flakefighters/flakefighters/abstract_flakefighter.py,sha256=bchRwoNzQaFhSknT9wKDpbf3EiReHPsHsDhm5qi8y_o,1953
10
10
  pytest_flakefighters/flakefighters/coverage_independence.py,sha256=5swoY1jOaaGFlZNX6PdejBFVd7Gpi3zsaW5W6toIzk8,4480
11
- pytest_flakefighters/flakefighters/deflaker.py,sha256=g0vPS2sEiD9XWFVu_FEZAw2pVkw9vGMWFa7Do1C3sck,5388
11
+ pytest_flakefighters/flakefighters/deflaker.py,sha256=GjmAA5i7YFJKbNaheWihqUqyu9_z2NZwqy6U--ztj9c,5989
12
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,,
13
+ pytest_flakefighters-0.2.0.dist-info/licenses/LICENSE,sha256=tTzR2CWQMPOp-mQIQqi0cTRkaogeBUmW06blQsBLdQg,1082
14
+ pytest_flakefighters-0.2.0.dist-info/METADATA,sha256=lXyrJ4fAUh8pJ2mMn3vCPoKSIkFwtZlt2rBccWbOdtM,5772
15
+ pytest_flakefighters-0.2.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
16
+ pytest_flakefighters-0.2.0.dist-info/entry_points.txt,sha256=xockvN1AszN2XqaET77JDIRdOafgm3DdvOtHgVw-aDU,424
17
+ pytest_flakefighters-0.2.0.dist-info/top_level.txt,sha256=bWwe0xVZ_l2CP8KSnztW6FafZKQZ7zUTMa1U32geY28,30
18
+ pytest_flakefighters-0.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5