pytest-flakefighters 0.1.6__tar.gz → 0.2.1__tar.gz

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.
Files changed (62) hide show
  1. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-tests-drafts.yaml +1 -1
  2. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-tests.yaml +1 -1
  3. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.gitignore +3 -0
  4. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.pre-commit-config.yaml +4 -0
  5. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/PKG-INFO +29 -17
  6. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/README.md +10 -5
  7. pytest_flakefighters-0.2.1/codecov.yml +20 -0
  8. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/pyproject.toml +82 -67
  9. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/_version.py +3 -3
  10. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/database_management.py +3 -1
  11. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/deflaker.py +19 -5
  12. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/plugin.py +11 -9
  13. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/PKG-INFO +29 -17
  14. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/SOURCES.txt +1 -0
  15. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/requires.txt +16 -11
  16. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_deflaker.py +42 -0
  17. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-mega-linter.yml +0 -0
  18. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/publish-pypi.yaml +0 -0
  19. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.mega-linter.yaml +0 -0
  20. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.readthedocs.yaml +0 -0
  21. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/LICENSE +0 -0
  22. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/Makefile +0 -0
  23. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/make.bat +0 -0
  24. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/css/custom.css +0 -0
  25. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/favicon.png +0 -0
  26. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/logo.png +0 -0
  27. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/acknowlegements.rst +0 -0
  28. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/conf.py +0 -0
  29. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/configuration.rst +0 -0
  30. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/actions_and_webhooks.rst +0 -0
  31. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/documentation.rst +0 -0
  32. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/version_release.rst +0 -0
  33. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/glossary.rst +0 -0
  34. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/index.rst +0 -0
  35. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/installation.rst +0 -0
  36. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/requirements.txt +0 -0
  37. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/setup.cfg +0 -0
  38. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/__init__.py +0 -0
  39. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/__init__.py +0 -0
  40. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/abstract_flakefighter.py +0 -0
  41. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/coverage_independence.py +0 -0
  42. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/traceback_matching.py +0 -0
  43. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/function_coverage.py +0 -0
  44. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/main.py +0 -0
  45. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/rerun_strategies.py +0 -0
  46. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/dependency_links.txt +0 -0
  47. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/entry_points.txt +0 -0
  48. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/top_level.txt +0 -0
  49. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/__init__.py +0 -0
  50. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/conftest.py +0 -0
  51. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_coverage_independence.py +0 -0
  52. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_traceback_matching.py +0 -0
  53. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_broken.py +0 -0
  54. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_example.py +0 -0
  55. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/flaky_reruns.py +0 -0
  56. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/pass_fail_flaky.py +0 -0
  57. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/test.txt +0 -0
  58. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/triangle.py +0 -0
  59. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_database_management.py +0 -0
  60. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_end_2_end.py +0 -0
  61. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_function_coverage.py +0 -0
  62. {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_rerun_strategies.py +0 -0
@@ -1,4 +1,4 @@
1
- name: Continuous Integration Tests Draft PR (pytest)
1
+ name: CI Tests Draft
2
2
  # This duplicate ci workflow is required so the badge in the README.md is not effected by draft PRs
3
3
  on:
4
4
  pull_request:
@@ -1,4 +1,4 @@
1
- name: Continuous Integration Tests (pytest)
1
+ name: CI Tests
2
2
 
3
3
  on:
4
4
  pull_request:
@@ -215,3 +215,6 @@ megalinter-reports/
215
215
 
216
216
  # Hide autogenerated sourcecode docs
217
217
  docs/source/autoapi
218
+
219
+ # Hide autogenerated version file
220
+ _version.py
@@ -19,3 +19,7 @@ repos:
19
19
  types: [python]
20
20
  args: ['--max-line-length=120', '--max-positional-arguments=12']
21
21
  files: ^src/|^tests/
22
+ - repo: https://github.com/ComPWA/taplo-pre-commit
23
+ rev: v0.9.3
24
+ hooks:
25
+ - id: taplo-format
@@ -1,46 +1,54 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-flakefighters
3
- Version: 0.1.6
3
+ Version: 0.2.1
4
4
  Summary: Pytest plugin implementing flaky test failure detection and classification.
5
5
  Author: TestFLARE Team
6
+ Project-URL: Documentation, https://pytest-flakefighters.readthedocs.io
7
+ Project-URL: Homepage, https://test-flare.github.io/
8
+ Project-URL: Issues, https://github.com/test-flare/pytest-flakefighters/issues
6
9
  Project-URL: Repository, https://github.com/test-flare/pytest-flakefighters
7
10
  Requires-Python: <3.14,>=3.10
8
11
  Description-Content-Type: text/markdown
9
12
  License-File: LICENSE
10
- Requires-Dist: pytest>=6.2.0
11
- Requires-Dist: coverage>=7.10.6
12
13
  Requires-Dist: GitPython>=3.1.45
13
- Requires-Dist: unidiff>=0.7.5
14
- Requires-Dist: sqlalchemy>=2.0.43
14
+ Requires-Dist: coverage>=7.10.6
15
15
  Requires-Dist: dotenv>=0.9.9
16
- Requires-Dist: pandas
17
- Requires-Dist: scipy<=1.15
16
+ Requires-Dist: nltk>=3.9
17
+ Requires-Dist: pandas>=2.3
18
+ Requires-Dist: pytest>=6.2.0
18
19
  Requires-Dist: pyyaml>=6
19
20
  Requires-Dist: scikit-learn>=1.7
20
- Requires-Dist: nltk>=3.9
21
+ Requires-Dist: scipy<=1.15
22
+ Requires-Dist: sqlalchemy>=2.0.43
23
+ Requires-Dist: unidiff>=0.7.5
21
24
  Provides-Extra: dev
22
25
  Requires-Dist: black; extra == "dev"
23
- Requires-Dist: pytest-cov; extra == "dev"
24
- Requires-Dist: pylint; extra == "dev"
26
+ Requires-Dist: myst_parser; extra == "dev"
27
+ Requires-Dist: nbsphinx; extra == "dev"
25
28
  Requires-Dist: pre_commit; extra == "dev"
29
+ Requires-Dist: pylint; extra == "dev"
30
+ Requires-Dist: pytest-cov; extra == "dev"
31
+ Requires-Dist: pytest-html; extra == "dev"
32
+ Requires-Dist: pytest-json-report>=1.5; extra == "dev"
26
33
  Requires-Dist: sphinx-autoapi; extra == "dev"
27
34
  Requires-Dist: sphinx_rtd_theme; extra == "dev"
28
35
  Requires-Dist: tox>=4.31.0; extra == "dev"
29
- Requires-Dist: myst_parser; extra == "dev"
30
- Requires-Dist: nbsphinx; extra == "dev"
36
+ Provides-Extra: pg
37
+ Requires-Dist: psycopg2>2.9; extra == "pg"
31
38
  Dynamic: license-file
32
39
 
33
40
  # Pytest FlakeFighters
41
+ ### Pytest plugin implementing flaky test failure detection and classification.
34
42
 
43
+ [![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
44
  [![PyPI version](https://img.shields.io/pypi/v/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
36
45
  [![Python versions](https://img.shields.io/pypi/pyversions/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
46
+ ![Test status](https://github.com/test-flare/pytest-flakefighters/actions/workflows/ci-tests.yaml/badge.svg)
47
+ [![codecov](https://codecov.io/gh/test-flare/pytest-flakefighters/branch/main/graph/badge.svg?token=04ijFVrb4a)](https://codecov.io/gh/test-flare/pytest-flakefighters)
48
+ [![Documentation Status](https://readthedocs.org/projects/causal-testing-framework/badge/?version=latest)](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
49
+ ![GitHub License](https://img.shields.io/github/license/test-flare/pytest-flakefighters)
37
50
 
38
- Pytest plugin implementing flaky test failure detection and
39
- classification.
40
51
 
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
52
 
45
53
  ## Features
46
54
 
@@ -93,3 +101,7 @@ Both extend the base class `FlakeFighter` and implement the `flaky_failure` meth
93
101
  ## Issues
94
102
 
95
103
  If you encounter any problems, please [file an issue](https://github.com/test-flare/pytest-flakefighters/issues) along with a detailed description.
104
+
105
+ ------------------------------------------------------------------------
106
+
107
+ 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,14 +1,15 @@
1
1
  # Pytest FlakeFighters
2
+ ### Pytest plugin implementing flaky test failure detection and classification.
2
3
 
4
+ [![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)
3
5
  [![PyPI version](https://img.shields.io/pypi/v/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
4
6
  [![Python versions](https://img.shields.io/pypi/pyversions/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
7
+ ![Test status](https://github.com/test-flare/pytest-flakefighters/actions/workflows/ci-tests.yaml/badge.svg)
8
+ [![codecov](https://codecov.io/gh/test-flare/pytest-flakefighters/branch/main/graph/badge.svg?token=04ijFVrb4a)](https://codecov.io/gh/test-flare/pytest-flakefighters)
9
+ [![Documentation Status](https://readthedocs.org/projects/causal-testing-framework/badge/?version=latest)](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
10
+ ![GitHub License](https://img.shields.io/github/license/test-flare/pytest-flakefighters)
5
11
 
6
- Pytest plugin implementing flaky test failure detection and
7
- classification.
8
12
 
9
- ------------------------------------------------------------------------
10
-
11
- 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.
12
13
 
13
14
  ## Features
14
15
 
@@ -61,3 +62,7 @@ Both extend the base class `FlakeFighter` and implement the `flaky_failure` meth
61
62
  ## Issues
62
63
 
63
64
  If you encounter any problems, please [file an issue](https://github.com/test-flare/pytest-flakefighters/issues) along with a detailed description.
65
+
66
+ ------------------------------------------------------------------------
67
+
68
+ 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.
@@ -0,0 +1,20 @@
1
+ codecov:
2
+ require_ci_to_pass: yes
3
+
4
+ coverage:
5
+ precision: 2
6
+ round: down
7
+ range: "70...100"
8
+
9
+ parsers:
10
+ gcov:
11
+ branch_detection:
12
+ conditional: yes
13
+ loop: yes
14
+ method: no
15
+ macro: no
16
+
17
+ comment:
18
+ layout: "reach,diff,flags,files,footer"
19
+ behavior: default
20
+ require_changes: no
@@ -1,102 +1,117 @@
1
1
  [build-system]
2
- requires = [
3
- "setuptools>=64",
4
- "setuptools_scm[toml]>=8",
5
- "wheel"
6
- ]
7
2
  build-backend = "setuptools.build_meta"
8
-
9
- [tool.setuptools_scm]
10
- write_to = "src/_version.py"
3
+ requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2", "wheel"]
11
4
 
12
5
  [project]
13
- name = "pytest-flakefighters"
14
- authors = [{ name = "TestFLARE Team" },]
15
- description = "Pytest plugin implementing flaky test failure detection and classification."
16
- readme = "README.md"
17
- requires-python = ">=3.10,<3.14"
18
- license-files = ["LICENSE"]
6
+ authors = [{ name = "TestFLARE Team" }]
19
7
  dependencies = [
20
- "pytest>=6.2.0",
21
- "coverage>=7.10.6",
22
- "GitPython>=3.1.45",
23
- "unidiff>=0.7.5",
24
- "sqlalchemy>=2.0.43",
25
- "dotenv>=0.9.9",
26
- "pandas",
27
- "scipy<=1.15",
28
- "pyyaml>=6",
29
- "scikit-learn>=1.7",
30
- "nltk>=3.9",
8
+ "GitPython>=3.1.45",
9
+ "coverage>=7.10.6",
10
+ "dotenv>=0.9.9",
11
+ "nltk>=3.9",
12
+ "pandas>=2.3",
13
+ "pytest>=6.2.0",
14
+ "pyyaml>=6",
15
+ "scikit-learn>=1.7",
16
+ "scipy<=1.15",
17
+ "sqlalchemy>=2.0.43",
18
+ "unidiff>=0.7.5",
31
19
  ]
20
+ description = "Pytest plugin implementing flaky test failure detection and classification."
32
21
  dynamic = ["version"]
22
+ license-files = ["LICENSE"]
23
+ name = "pytest-flakefighters"
24
+ readme = "README.md"
25
+ requires-python = ">=3.10,<3.14"
26
+
27
+ [project.entry-points.pytest11]
28
+ flakefighters = "pytest_flakefighters.main"
29
+
30
+ [project.entry-points."pytest_flakefighters"]
31
+ CosineSimilarity = "pytest_flakefighters.flakefighters.traceback_matching:CosineSimilarity"
32
+ CoverageIndependence = 'pytest_flakefighters.flakefighters.coverage_independence:CoverageIndependence'
33
+ DeFlaker = "pytest_flakefighters.flakefighters.deflaker:DeFlaker"
34
+ TracebackMatching = "pytest_flakefighters.flakefighters.traceback_matching:TracebackMatching"
33
35
 
34
36
  [project.optional-dependencies]
35
37
  dev = [
36
- "black",
37
- "pytest-cov",
38
- "pylint",
39
- "pre_commit",
40
- "sphinx-autoapi",
41
- "sphinx_rtd_theme",
42
- "tox>=4.31.0",
43
- "myst_parser",
44
- "nbsphinx",
38
+ "black",
39
+ "myst_parser",
40
+ "nbsphinx",
41
+ "pre_commit",
42
+ "pylint",
43
+ "pytest-cov",
44
+ "pytest-html",
45
+ "pytest-json-report>=1.5",
46
+ "sphinx-autoapi",
47
+ "sphinx_rtd_theme",
48
+ "tox>=4.31.0",
45
49
  ]
50
+ pg = ["psycopg2>2.9"]
46
51
 
47
52
  [project.urls]
53
+ Documentation = "https://pytest-flakefighters.readthedocs.io"
54
+ Homepage = "https://test-flare.github.io/"
55
+ Issues = "https://github.com/test-flare/pytest-flakefighters/issues"
48
56
  Repository = "https://github.com/test-flare/pytest-flakefighters"
49
57
 
50
- [project.entry-points.pytest11]
51
- flakefighters = "pytest_flakefighters.main"
58
+ [tool.taplo]
59
+ reorder_keys = true
60
+ reorder_arrays = true
52
61
 
53
- [project.entry-points."pytest_flakefighters"]
54
- CoverageIndependence = 'pytest_flakefighters.flakefighters.coverage_independence:CoverageIndependence'
55
- DeFlaker = "pytest_flakefighters.flakefighters.deflaker:DeFlaker"
56
- TracebackMatching = "pytest_flakefighters.flakefighters.traceback_matching:TracebackMatching"
57
- CosineSimilarity = "pytest_flakefighters.flakefighters.traceback_matching:CosineSimilarity"
62
+ [tool.black]
63
+ # https://github.com/psf/black
64
+ line-length = 120
65
+ target-version = ["py310"]
58
66
 
67
+ [tool.isort]
68
+ profile = "black"
59
69
 
60
70
  [tool.pylint]
61
- ignore-paths="tests/resources"
62
- disable=[
63
- "raw-checker-failed",
71
+ disable = [
64
72
  "bad-inline-option",
65
- "locally-disabled",
66
- "file-ignored",
67
- "suppressed-message",
68
- "useless-suppression",
69
73
  "deprecated-pragma",
70
- "use-symbolic-message-instead",
71
- "logging-fstring-interpolation",
74
+ "file-ignored",
72
75
  "import-error",
76
+ "locally-disabled",
77
+ "logging-fstring-interpolation",
78
+ "raw-checker-failed",
79
+ "suppressed-message",
80
+ "unexpected-keyword-arg",
73
81
  "unspecified-encoding",
74
- "unexpected-keyword-arg"
82
+ "use-symbolic-message-instead",
83
+ "useless-suppression",
75
84
  ]
76
- max-line-length=120
77
- variable-rgx="^[a-z][a-z0-9]*((_[a-z0-9]+)*)?$"
78
-
79
- [tool.black]
80
- # https://github.com/psf/black
81
- line-length = 120
82
- target-version = ["py310"]
85
+ ignore-paths = "tests/resources"
86
+ max-line-length = 120
87
+ variable-rgx = "^[a-z][a-z0-9]*((_[a-z0-9]+)*)?$"
83
88
 
84
89
  [tool.pytest.ini_options]
85
90
  minversion = "6.0"
86
91
  testpaths = ["tests"]
87
- [tool.isort]
88
- profile = "black"
92
+
93
+ [tool.setuptools_scm]
94
+ write_to = "src/_version.py"
89
95
 
90
96
  [tool.tox]
97
+ env_list = ["3.10", "3.11", "3.12", "3.13"]
91
98
  requires = ["tox>=4.19"]
92
- env_list = ["3.10","3.11","3.12","3.13"]
93
- skip_missing_interpreters = false # fail if devs don’t have all required Python versions
99
+ skip_missing_interpreters = false # fail if devs don’t have all required Python versions
94
100
 
95
101
  # Base configuration for all test environments
96
102
  [tool.tox.env_run_base]
97
- usedevelop = true
103
+ allowlist_externals = ["pytest"]
104
+ commands = [
105
+ [
106
+ "--cov-report=html",
107
+ "--cov=src/pytest_flakefighters",
108
+ "-p",
109
+ "no:flakefighters",
110
+ "pytest",
111
+ "{posargs:tests}",
112
+ ],
113
+ ]
114
+ deps = ["pytest", "pytest-cov", "pytest-html", "pytest-json-report"]
98
115
  description = "Run pytest under {base_python}"
99
- allowlist_externals=["pytest"]
100
- extras = ["dev","test"]
101
- deps = ["pytest","pytest-cov"]
102
- commands = [["pytest","-p","no:flakefighters","--cov=src/pytest_flakefighters","--cov-report=html","{posargs:tests}"]]
116
+ extras = ["dev", "test"]
117
+ usedevelop = true
@@ -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.6'
32
- __version_tuple__ = version_tuple = (0, 1, 6)
31
+ __version__ = version = '0.2.1'
32
+ __version_tuple__ = version_tuple = (0, 2, 1)
33
33
 
34
- __commit_id__ = commit_id = 'gfd77e6b1e'
34
+ __commit_id__ = commit_id = 'gfcca48c00'
@@ -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,46 +1,54 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-flakefighters
3
- Version: 0.1.6
3
+ Version: 0.2.1
4
4
  Summary: Pytest plugin implementing flaky test failure detection and classification.
5
5
  Author: TestFLARE Team
6
+ Project-URL: Documentation, https://pytest-flakefighters.readthedocs.io
7
+ Project-URL: Homepage, https://test-flare.github.io/
8
+ Project-URL: Issues, https://github.com/test-flare/pytest-flakefighters/issues
6
9
  Project-URL: Repository, https://github.com/test-flare/pytest-flakefighters
7
10
  Requires-Python: <3.14,>=3.10
8
11
  Description-Content-Type: text/markdown
9
12
  License-File: LICENSE
10
- Requires-Dist: pytest>=6.2.0
11
- Requires-Dist: coverage>=7.10.6
12
13
  Requires-Dist: GitPython>=3.1.45
13
- Requires-Dist: unidiff>=0.7.5
14
- Requires-Dist: sqlalchemy>=2.0.43
14
+ Requires-Dist: coverage>=7.10.6
15
15
  Requires-Dist: dotenv>=0.9.9
16
- Requires-Dist: pandas
17
- Requires-Dist: scipy<=1.15
16
+ Requires-Dist: nltk>=3.9
17
+ Requires-Dist: pandas>=2.3
18
+ Requires-Dist: pytest>=6.2.0
18
19
  Requires-Dist: pyyaml>=6
19
20
  Requires-Dist: scikit-learn>=1.7
20
- Requires-Dist: nltk>=3.9
21
+ Requires-Dist: scipy<=1.15
22
+ Requires-Dist: sqlalchemy>=2.0.43
23
+ Requires-Dist: unidiff>=0.7.5
21
24
  Provides-Extra: dev
22
25
  Requires-Dist: black; extra == "dev"
23
- Requires-Dist: pytest-cov; extra == "dev"
24
- Requires-Dist: pylint; extra == "dev"
26
+ Requires-Dist: myst_parser; extra == "dev"
27
+ Requires-Dist: nbsphinx; extra == "dev"
25
28
  Requires-Dist: pre_commit; extra == "dev"
29
+ Requires-Dist: pylint; extra == "dev"
30
+ Requires-Dist: pytest-cov; extra == "dev"
31
+ Requires-Dist: pytest-html; extra == "dev"
32
+ Requires-Dist: pytest-json-report>=1.5; extra == "dev"
26
33
  Requires-Dist: sphinx-autoapi; extra == "dev"
27
34
  Requires-Dist: sphinx_rtd_theme; extra == "dev"
28
35
  Requires-Dist: tox>=4.31.0; extra == "dev"
29
- Requires-Dist: myst_parser; extra == "dev"
30
- Requires-Dist: nbsphinx; extra == "dev"
36
+ Provides-Extra: pg
37
+ Requires-Dist: psycopg2>2.9; extra == "pg"
31
38
  Dynamic: license-file
32
39
 
33
40
  # Pytest FlakeFighters
41
+ ### Pytest plugin implementing flaky test failure detection and classification.
34
42
 
43
+ [![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
44
  [![PyPI version](https://img.shields.io/pypi/v/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
36
45
  [![Python versions](https://img.shields.io/pypi/pyversions/pytest-flakefighters.svg)](https://pypi.org/project/pytest-flakefighters)
46
+ ![Test status](https://github.com/test-flare/pytest-flakefighters/actions/workflows/ci-tests.yaml/badge.svg)
47
+ [![codecov](https://codecov.io/gh/test-flare/pytest-flakefighters/branch/main/graph/badge.svg?token=04ijFVrb4a)](https://codecov.io/gh/test-flare/pytest-flakefighters)
48
+ [![Documentation Status](https://readthedocs.org/projects/causal-testing-framework/badge/?version=latest)](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
49
+ ![GitHub License](https://img.shields.io/github/license/test-flare/pytest-flakefighters)
37
50
 
38
- Pytest plugin implementing flaky test failure detection and
39
- classification.
40
51
 
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
52
 
45
53
  ## Features
46
54
 
@@ -93,3 +101,7 @@ Both extend the base class `FlakeFighter` and implement the `flaky_failure` meth
93
101
  ## Issues
94
102
 
95
103
  If you encounter any problems, please [file an issue](https://github.com/test-flare/pytest-flakefighters/issues) along with a detailed description.
104
+
105
+ ------------------------------------------------------------------------
106
+
107
+ 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.
@@ -4,6 +4,7 @@
4
4
  .readthedocs.yaml
5
5
  LICENSE
6
6
  README.md
7
+ codecov.yml
7
8
  pyproject.toml
8
9
  .github/workflows/ci-mega-linter.yml
9
10
  .github/workflows/ci-tests-drafts.yaml
@@ -1,22 +1,27 @@
1
- pytest>=6.2.0
2
- coverage>=7.10.6
3
1
  GitPython>=3.1.45
4
- unidiff>=0.7.5
5
- sqlalchemy>=2.0.43
2
+ coverage>=7.10.6
6
3
  dotenv>=0.9.9
7
- pandas
8
- scipy<=1.15
4
+ nltk>=3.9
5
+ pandas>=2.3
6
+ pytest>=6.2.0
9
7
  pyyaml>=6
10
8
  scikit-learn>=1.7
11
- nltk>=3.9
9
+ scipy<=1.15
10
+ sqlalchemy>=2.0.43
11
+ unidiff>=0.7.5
12
12
 
13
13
  [dev]
14
14
  black
15
- pytest-cov
16
- pylint
15
+ myst_parser
16
+ nbsphinx
17
17
  pre_commit
18
+ pylint
19
+ pytest-cov
20
+ pytest-html
21
+ pytest-json-report>=1.5
18
22
  sphinx-autoapi
19
23
  sphinx_rtd_theme
20
24
  tox>=4.31.0
21
- myst_parser
22
- nbsphinx
25
+
26
+ [pg]
27
+ psycopg2>2.9
@@ -67,6 +67,42 @@ def test_dirty_repo(flaky_reruns_repo):
67
67
  assert deflaker.target_commit is None, f"Expected source commit None but was {deflaker.target_commit}"
68
68
 
69
69
 
70
+ def test_new_test_preserves_original_results(flaky_reruns_repo):
71
+ """
72
+ Test the setup of source and target commits for a dirty repo (uncommitted changes).
73
+ """
74
+
75
+ deflaker = DeFlaker(True, root=flaky_reruns_repo.working_dir)
76
+ test_execution = TestExecution(
77
+ outcome="failed",
78
+ coverage={
79
+ os.path.join(flaky_reruns_repo.working_dir, "flaky_reruns.py"): [1, 4, 6, 9, 10, 11, 12],
80
+ },
81
+ )
82
+ Test( # pylint: disable=E1123
83
+ name="test_create_or_delete",
84
+ fspath=os.path.join(flaky_reruns_repo.working_dir, "flaky_reruns.py"),
85
+ line_no=9,
86
+ executions=[test_execution],
87
+ )
88
+ deflaker.flaky_test_live(test_execution)
89
+ expected = FlakefighterResult(name="DeFlaker", flaky=True)
90
+ assert test_execution.flakefighter_results == [
91
+ expected
92
+ ], "Expected original run of test_create_or_delete to be flaky"
93
+
94
+ # Add a new test and check that test_create_or_delete is still flaky
95
+ with open(os.path.join(flaky_reruns_repo.working_dir, "flaky_reruns.py"), "w") as f:
96
+ print("def test_fail(self):\n assert False", file=f)
97
+
98
+ test_execution.flakefighter_results = []
99
+ test_execution.coverage = {
100
+ os.path.join(flaky_reruns_repo.working_dir, "flaky_reruns.py"): [1, 4, 6, 9, 10, 11, 12, 14],
101
+ }
102
+ deflaker.flaky_test_live(test_execution)
103
+ assert test_execution.flakefighter_results == [expected], "Expected second run of test_create_or_delete to be flaky"
104
+
105
+
70
106
  def test_named_source_target(flaky_reruns_repo):
71
107
  """
72
108
  Test the setup of source and target commits when both are named.
@@ -126,6 +162,12 @@ def test_flaky_test_live_false(deflaker_repo):
126
162
  os.path.join(deflaker_repo.working_dir, "app.py"): [1, 2, 6, 7, 8, 11, 12, 15, 16],
127
163
  },
128
164
  )
165
+ Test( # pylint: disable=E1123
166
+ name="test_app",
167
+ fspath=os.path.join(deflaker_repo.working_dir, "deflaker_example.py"),
168
+ line_no=15,
169
+ executions=[test_execution],
170
+ )
129
171
  deflaker.flaky_test_live(test_execution)
130
172
  expected = FlakefighterResult(name="DeFlaker", flaky=False)
131
173
  assert test_execution.flakefighter_results == [expected]