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.
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-tests-drafts.yaml +1 -1
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-tests.yaml +1 -1
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.gitignore +3 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.pre-commit-config.yaml +4 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/PKG-INFO +29 -17
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/README.md +10 -5
- pytest_flakefighters-0.2.1/codecov.yml +20 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/pyproject.toml +82 -67
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/_version.py +3 -3
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/database_management.py +3 -1
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/deflaker.py +19 -5
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/plugin.py +11 -9
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/PKG-INFO +29 -17
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/SOURCES.txt +1 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/requires.txt +16 -11
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_deflaker.py +42 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-mega-linter.yml +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/publish-pypi.yaml +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.mega-linter.yaml +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.readthedocs.yaml +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/LICENSE +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/Makefile +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/make.bat +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/css/custom.css +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/favicon.png +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/logo.png +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/acknowlegements.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/conf.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/configuration.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/actions_and_webhooks.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/documentation.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/version_release.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/glossary.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/index.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/installation.rst +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/requirements.txt +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/setup.cfg +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/__init__.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/__init__.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/abstract_flakefighter.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/coverage_independence.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/flakefighters/traceback_matching.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/function_coverage.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/main.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/rerun_strategies.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/dependency_links.txt +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/entry_points.txt +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/top_level.txt +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/__init__.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/conftest.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_coverage_independence.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_traceback_matching.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_broken.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_example.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/flaky_reruns.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/pass_fail_flaky.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/test.txt +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/triangle.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_database_management.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_end_2_end.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_function_coverage.py +0 -0
- {pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/test_rerun_strategies.py +0 -0
|
@@ -1,46 +1,54 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-flakefighters
|
|
3
|
-
Version: 0.1
|
|
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:
|
|
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:
|
|
17
|
-
Requires-Dist:
|
|
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:
|
|
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:
|
|
24
|
-
Requires-Dist:
|
|
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
|
-
|
|
30
|
-
Requires-Dist:
|
|
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
|
+
[](https://www.repostatus.org/#active)
|
|
35
44
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
36
45
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
46
|
+

|
|
47
|
+
[](https://codecov.io/gh/test-flare/pytest-flakefighters)
|
|
48
|
+
[](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
|
|
49
|
+

|
|
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
|
+
[](https://www.repostatus.org/#active)
|
|
3
5
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
4
6
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
7
|
+

|
|
8
|
+
[](https://codecov.io/gh/test-flare/pytest-flakefighters)
|
|
9
|
+
[](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
|
|
10
|
+

|
|
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 = "
|
|
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
|
-
"
|
|
21
|
-
"coverage>=7.10.6",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
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
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"pre_commit",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
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
|
-
[
|
|
51
|
-
|
|
58
|
+
[tool.taplo]
|
|
59
|
+
reorder_keys = true
|
|
60
|
+
reorder_arrays = true
|
|
52
61
|
|
|
53
|
-
[
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
82
|
+
"use-symbolic-message-instead",
|
|
83
|
+
"useless-suppression",
|
|
75
84
|
]
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
100
|
-
|
|
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
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.2.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 1)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
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
|
|
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,
|
|
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
|
|
103
|
+
:param line_no: The line number to check.
|
|
91
104
|
"""
|
|
92
|
-
return
|
|
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,
|
|
113
|
+
self.line_modified_by_target_commit(file_path, line_no)
|
|
101
114
|
for file_path in execution.coverage
|
|
102
|
-
for
|
|
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):
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/plugin.py
RENAMED
|
@@ -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
|
-
|
|
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(
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters.egg-info/PKG-INFO
RENAMED
|
@@ -1,46 +1,54 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-flakefighters
|
|
3
|
-
Version: 0.1
|
|
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:
|
|
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:
|
|
17
|
-
Requires-Dist:
|
|
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:
|
|
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:
|
|
24
|
-
Requires-Dist:
|
|
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
|
-
|
|
30
|
-
Requires-Dist:
|
|
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
|
+
[](https://www.repostatus.org/#active)
|
|
35
44
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
36
45
|
[](https://pypi.org/project/pytest-flakefighters)
|
|
46
|
+

|
|
47
|
+
[](https://codecov.io/gh/test-flare/pytest-flakefighters)
|
|
48
|
+
[](https://causal-testing-framework.readthedocs.io/en/latest/?badge=latest)
|
|
49
|
+

|
|
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,22 +1,27 @@
|
|
|
1
|
-
pytest>=6.2.0
|
|
2
|
-
coverage>=7.10.6
|
|
3
1
|
GitPython>=3.1.45
|
|
4
|
-
|
|
5
|
-
sqlalchemy>=2.0.43
|
|
2
|
+
coverage>=7.10.6
|
|
6
3
|
dotenv>=0.9.9
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
nltk>=3.9
|
|
5
|
+
pandas>=2.3
|
|
6
|
+
pytest>=6.2.0
|
|
9
7
|
pyyaml>=6
|
|
10
8
|
scikit-learn>=1.7
|
|
11
|
-
|
|
9
|
+
scipy<=1.15
|
|
10
|
+
sqlalchemy>=2.0.43
|
|
11
|
+
unidiff>=0.7.5
|
|
12
12
|
|
|
13
13
|
[dev]
|
|
14
14
|
black
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
22
|
-
|
|
25
|
+
|
|
26
|
+
[pg]
|
|
27
|
+
psycopg2>2.9
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/flakefighters/test_deflaker.py
RENAMED
|
@@ -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]
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/ci-mega-linter.yml
RENAMED
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/.github/workflows/publish-pypi.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/css/custom.css
RENAMED
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/favicon.png
RENAMED
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/_static/images/logo.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/actions_and_webhooks.rst
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/docs/source/dev/version_release.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/src/pytest_flakefighters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_broken.py
RENAMED
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/deflaker_example.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_flakefighters-0.1.6 → pytest_flakefighters-0.2.1}/tests/resources/pass_fail_flaky.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|