pytest-tap 3.3__tar.gz → 3.5__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_tap-3.5/.gitignore +71 -0
- {pytest-tap-3.3 → pytest_tap-3.5}/AUTHORS +2 -0
- {pytest-tap-3.3 → pytest_tap-3.5}/PKG-INFO +39 -18
- pytest-tap-3.3/src/pytest_tap.egg-info/PKG-INFO → pytest_tap-3.5/docs/releases.rst +26 -30
- pytest_tap-3.5/pyproject.toml +83 -0
- pytest_tap-3.5/pytest_tap/__init__.py +1 -0
- pytest_tap-3.5/pytest_tap/plugin.py +203 -0
- pytest_tap-3.5/tests/__init__.py +0 -0
- pytest_tap-3.5/tests/test_help.py +24 -0
- pytest_tap-3.5/tests/test_plugin.py +247 -0
- pytest_tap-3.5/tests/test_xdist.py +30 -0
- pytest-tap-3.3/MANIFEST.in +0 -4
- pytest-tap-3.3/README.rst +0 -57
- pytest-tap-3.3/docs/releases.rst +0 -81
- pytest-tap-3.3/setup.cfg +0 -21
- pytest-tap-3.3/setup.py +0 -51
- pytest-tap-3.3/src/pytest_tap/__init__.py +0 -1
- pytest-tap-3.3/src/pytest_tap/plugin.py +0 -150
- pytest-tap-3.3/src/pytest_tap.egg-info/SOURCES.txt +0 -16
- pytest-tap-3.3/src/pytest_tap.egg-info/dependency_links.txt +0 -1
- pytest-tap-3.3/src/pytest_tap.egg-info/entry_points.txt +0 -3
- pytest-tap-3.3/src/pytest_tap.egg-info/not-zip-safe +0 -1
- pytest-tap-3.3/src/pytest_tap.egg-info/requires.txt +0 -2
- pytest-tap-3.3/src/pytest_tap.egg-info/top_level.txt +0 -1
- {pytest-tap-3.3 → pytest_tap-3.5}/LICENSE +0 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
env/
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
# Usually these files are written by a python script from a template
|
|
29
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
30
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.coverage
|
|
41
|
+
.coverage.*
|
|
42
|
+
.cache
|
|
43
|
+
nosetests.xml
|
|
44
|
+
coverage.xml
|
|
45
|
+
*,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache
|
|
48
|
+
|
|
49
|
+
# Translations
|
|
50
|
+
*.mo
|
|
51
|
+
|
|
52
|
+
# Django stuff:
|
|
53
|
+
*.log
|
|
54
|
+
|
|
55
|
+
# Sphinx documentation
|
|
56
|
+
docs/_build/
|
|
57
|
+
|
|
58
|
+
# PyBuilder
|
|
59
|
+
target/
|
|
60
|
+
|
|
61
|
+
#Ipython Notebook
|
|
62
|
+
.ipynb_checkpoints
|
|
63
|
+
|
|
64
|
+
# Vim
|
|
65
|
+
*.sw*
|
|
66
|
+
|
|
67
|
+
# TAP
|
|
68
|
+
*.tap
|
|
69
|
+
|
|
70
|
+
# Virtual environments
|
|
71
|
+
venv/
|
|
@@ -1,40 +1,63 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-tap
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5
|
|
4
4
|
Summary: Test Anything Protocol (TAP) reporting plugin for pytest
|
|
5
|
-
|
|
6
|
-
Author: Matt Layman
|
|
7
|
-
Author-email: matthewlayman@gmail.com
|
|
5
|
+
Author-email: Matt Layman <matthewlayman@gmail.com>
|
|
8
6
|
License: BSD
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
License-File: AUTHORS
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: TAP,pytest,unittest
|
|
11
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
11
|
Classifier: Framework :: Pytest
|
|
13
12
|
Classifier: Intended Audience :: Developers
|
|
14
13
|
Classifier: License :: OSI Approved :: BSD License
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python ::
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
20
|
Classifier: Topic :: Software Development :: Testing
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Requires-Dist: pytest>=3.0
|
|
23
|
+
Requires-Dist: tap-py<4.0,>=3.2
|
|
24
|
+
Description-Content-Type: text/x-rst
|
|
25
25
|
|
|
26
26
|
pytest-tap is a reporting plugin for pytest that outputs
|
|
27
27
|
`Test Anything Protocol (TAP) <http://testanything.org/>`_ data.
|
|
28
28
|
TAP is a line based test protocol for recording test data in a standard way.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
Developer documentation is on
|
|
32
|
-
`Read the Docs <https://tappy.readthedocs.io/>`_.
|
|
30
|
+
Use ``pytest --tap`` after installing to get started.
|
|
33
31
|
|
|
32
|
+
Follow `GitHub <https://github.com/python-tap/pytest-tap>`_
|
|
33
|
+
for more information or to follow this plugin's development.
|
|
34
|
+
Additional developer documentation about Python and TAP is on
|
|
35
|
+
`Read the Docs <https://tappy.readthedocs.io/>`_.
|
|
34
36
|
|
|
35
37
|
Releases
|
|
36
38
|
========
|
|
37
39
|
|
|
40
|
+
Version 3.5, January 30, 2025
|
|
41
|
+
-----------------------------
|
|
42
|
+
|
|
43
|
+
* Diagnostics now output logs, stdout, stderr for failed tests.
|
|
44
|
+
Use the standard ``--show-capture`` flag to control the output.
|
|
45
|
+
* Diagnostics can display for passing tests using the
|
|
46
|
+
``--tap-log-passing-tests`` flag.
|
|
47
|
+
* Add support for Python 3.12.
|
|
48
|
+
* Add support for Python 3.13.
|
|
49
|
+
* Drop support for Python 3.8 (it is end-of-life).
|
|
50
|
+
|
|
51
|
+
Version 3.4, July 15, 2023
|
|
52
|
+
--------------------------
|
|
53
|
+
|
|
54
|
+
* Deprecate ``--tap-stream`` in favor of ``--tap`` for streaming mode.
|
|
55
|
+
* When using xdist, report the plan at the beginning of execution.
|
|
56
|
+
* Add support for Python 3.11.
|
|
57
|
+
* Drop support for Python 3.7 (it is end-of-life).
|
|
58
|
+
* Drop support for Python 3.6 (it is end-of-life).
|
|
59
|
+
* Drop support for PyPy.
|
|
60
|
+
|
|
38
61
|
Version 3.3, October 27, 2021
|
|
39
62
|
-----------------------------
|
|
40
63
|
|
|
@@ -113,5 +136,3 @@ Version 1.9, Released June 11, 2016
|
|
|
113
136
|
|
|
114
137
|
* Initial release as stand-alone plugin.
|
|
115
138
|
The version number aligns with tappy.
|
|
116
|
-
|
|
117
|
-
|
|
@@ -1,40 +1,38 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pytest-tap
|
|
3
|
-
Version: 3.3
|
|
4
|
-
Summary: Test Anything Protocol (TAP) reporting plugin for pytest
|
|
5
|
-
Home-page: https://github.com/python-tap/pytest-tap
|
|
6
|
-
Author: Matt Layman
|
|
7
|
-
Author-email: matthewlayman@gmail.com
|
|
8
|
-
License: BSD
|
|
9
|
-
Keywords: TAP,unittest,pytest
|
|
10
|
-
Platform: any
|
|
11
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
-
Classifier: Framework :: Pytest
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
22
|
-
Classifier: Topic :: Software Development :: Testing
|
|
23
|
-
License-File: LICENSE
|
|
24
|
-
|
|
25
|
-
|
|
26
1
|
pytest-tap is a reporting plugin for pytest that outputs
|
|
27
2
|
`Test Anything Protocol (TAP) <http://testanything.org/>`_ data.
|
|
28
3
|
TAP is a line based test protocol for recording test data in a standard way.
|
|
29
4
|
|
|
30
|
-
|
|
31
|
-
Developer documentation is on
|
|
32
|
-
`Read the Docs <https://tappy.readthedocs.io/>`_.
|
|
5
|
+
Use ``pytest --tap`` after installing to get started.
|
|
33
6
|
|
|
7
|
+
Follow `GitHub <https://github.com/python-tap/pytest-tap>`_
|
|
8
|
+
for more information or to follow this plugin's development.
|
|
9
|
+
Additional developer documentation about Python and TAP is on
|
|
10
|
+
`Read the Docs <https://tappy.readthedocs.io/>`_.
|
|
34
11
|
|
|
35
12
|
Releases
|
|
36
13
|
========
|
|
37
14
|
|
|
15
|
+
Version 3.5, January 30, 2025
|
|
16
|
+
-----------------------------
|
|
17
|
+
|
|
18
|
+
* Diagnostics now output logs, stdout, stderr for failed tests.
|
|
19
|
+
Use the standard ``--show-capture`` flag to control the output.
|
|
20
|
+
* Diagnostics can display for passing tests using the
|
|
21
|
+
``--tap-log-passing-tests`` flag.
|
|
22
|
+
* Add support for Python 3.12.
|
|
23
|
+
* Add support for Python 3.13.
|
|
24
|
+
* Drop support for Python 3.8 (it is end-of-life).
|
|
25
|
+
|
|
26
|
+
Version 3.4, July 15, 2023
|
|
27
|
+
--------------------------
|
|
28
|
+
|
|
29
|
+
* Deprecate ``--tap-stream`` in favor of ``--tap`` for streaming mode.
|
|
30
|
+
* When using xdist, report the plan at the beginning of execution.
|
|
31
|
+
* Add support for Python 3.11.
|
|
32
|
+
* Drop support for Python 3.7 (it is end-of-life).
|
|
33
|
+
* Drop support for Python 3.6 (it is end-of-life).
|
|
34
|
+
* Drop support for PyPy.
|
|
35
|
+
|
|
38
36
|
Version 3.3, October 27, 2021
|
|
39
37
|
-----------------------------
|
|
40
38
|
|
|
@@ -113,5 +111,3 @@ Version 1.9, Released June 11, 2016
|
|
|
113
111
|
|
|
114
112
|
* Initial release as stand-alone plugin.
|
|
115
113
|
The version number aligns with tappy.
|
|
116
|
-
|
|
117
|
-
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pytest-tap"
|
|
3
|
+
version = "3.5"
|
|
4
|
+
description = "Test Anything Protocol (TAP) reporting plugin for pytest"
|
|
5
|
+
readme = "docs/releases.rst"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Matt Layman", email = "matthewlayman@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
license = { text = "BSD" }
|
|
10
|
+
homepage = "https://github.com/python-tap/pytest-tap"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"pytest>=3.0",
|
|
13
|
+
"tap.py>=3.2,<4.0"
|
|
14
|
+
]
|
|
15
|
+
requires-python = ">=3.9"
|
|
16
|
+
keywords = ["TAP", "unittest", "pytest"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 5 - Production/Stable",
|
|
19
|
+
"Framework :: Pytest",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: BSD License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Topic :: Software Development :: Testing"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.entry-points.pytest11]
|
|
32
|
+
tap = "pytest_tap.plugin"
|
|
33
|
+
|
|
34
|
+
[dependency-groups]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest-tap",
|
|
37
|
+
"tox>=4.24.1",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
requires = ["hatchling"]
|
|
42
|
+
build-backend = "hatchling.build"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.sdist]
|
|
45
|
+
include = [
|
|
46
|
+
"/src",
|
|
47
|
+
"/docs",
|
|
48
|
+
"/tests",
|
|
49
|
+
]
|
|
50
|
+
sources = ["src"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.wheel]
|
|
53
|
+
sources = ["src"]
|
|
54
|
+
packages = ["pytest_tap"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
pythonpath = [".", "src"]
|
|
58
|
+
|
|
59
|
+
[tool.uv.sources]
|
|
60
|
+
pytest-tap = { workspace = true }
|
|
61
|
+
|
|
62
|
+
[tool.ruff.lint]
|
|
63
|
+
select = [
|
|
64
|
+
# pycodestyle
|
|
65
|
+
"E",
|
|
66
|
+
"W",
|
|
67
|
+
# Pyflakes
|
|
68
|
+
"F",
|
|
69
|
+
# pyupgrade
|
|
70
|
+
"UP",
|
|
71
|
+
# flake8-bandit
|
|
72
|
+
"S",
|
|
73
|
+
# flake8-bugbear
|
|
74
|
+
"B",
|
|
75
|
+
# flake8-simplify
|
|
76
|
+
"SIM",
|
|
77
|
+
# isort
|
|
78
|
+
"I",
|
|
79
|
+
]
|
|
80
|
+
ignore = [
|
|
81
|
+
# bandit: Use of `assert` detected
|
|
82
|
+
"S101",
|
|
83
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.5"
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from tap.formatter import format_as_diagnostics
|
|
6
|
+
from tap.tracker import Tracker
|
|
7
|
+
|
|
8
|
+
SHOW_CAPTURE_LOG = ("log", "all")
|
|
9
|
+
SHOW_CAPTURE_OUT = ("stdout", "all")
|
|
10
|
+
SHOW_CAPTUER_ERR = ("stderr", "all")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TAPPlugin:
|
|
14
|
+
def __init__(self, config: pytest.Config) -> None:
|
|
15
|
+
self._tracker = Tracker(
|
|
16
|
+
outdir=config.option.tap_outdir,
|
|
17
|
+
combined=config.option.tap_combined,
|
|
18
|
+
streaming=config.option.tap_stream,
|
|
19
|
+
stream=sys.stdout,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if self._tracker.streaming:
|
|
23
|
+
reporter = config.pluginmanager.getplugin("terminalreporter")
|
|
24
|
+
if reporter:
|
|
25
|
+
config.pluginmanager.unregister(reporter)
|
|
26
|
+
# A common pytest pattern is to use test functions without classes.
|
|
27
|
+
# The header looks really dumb for that pattern because it puts
|
|
28
|
+
# out a lot of line noise since every function gets its own header.
|
|
29
|
+
# Disable it automatically for streaming.
|
|
30
|
+
self._tracker.header = False
|
|
31
|
+
|
|
32
|
+
self.show_capture = config.option.showcapture
|
|
33
|
+
self.log_passing_tests = config.option.tap_log_passing_tests
|
|
34
|
+
|
|
35
|
+
@pytest.hookimpl()
|
|
36
|
+
def pytest_runtestloop(self, session):
|
|
37
|
+
"""Output the plan line first."""
|
|
38
|
+
option = session.config.option
|
|
39
|
+
if option.tap_stream or option.tap_combined:
|
|
40
|
+
self._tracker.set_plan(session.testscollected)
|
|
41
|
+
|
|
42
|
+
@pytest.hookimpl(optionalhook=True)
|
|
43
|
+
def pytest_xdist_node_collection_finished(self, node, ids):
|
|
44
|
+
"""Output the plan line first when using xdist."""
|
|
45
|
+
if self._tracker.streaming or self._tracker.combined:
|
|
46
|
+
self._tracker.set_plan(len(ids))
|
|
47
|
+
|
|
48
|
+
@pytest.hookimpl()
|
|
49
|
+
def pytest_runtest_logreport(self, report: pytest.TestReport):
|
|
50
|
+
"""Add a test result to the tracker."""
|
|
51
|
+
is_trackable_result = (
|
|
52
|
+
(report.when == "setup" and report.outcome == "skipped")
|
|
53
|
+
or (report.when == "setup" and report.outcome == "failed")
|
|
54
|
+
or report.when == "call"
|
|
55
|
+
)
|
|
56
|
+
if not is_trackable_result:
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
description = str(report.location[0]) + "::" + str(report.location[2])
|
|
60
|
+
testcase = report.location[0]
|
|
61
|
+
|
|
62
|
+
# Handle xfails first because they report in unusual ways.
|
|
63
|
+
# Non-strict xfails will include `wasxfail` while strict xfails won't.
|
|
64
|
+
if hasattr(report, "wasxfail"):
|
|
65
|
+
reason = ""
|
|
66
|
+
# pytest adds an ugly "reason: " for expectedFailure
|
|
67
|
+
# even though the standard library doesn't accept a reason
|
|
68
|
+
# for that decorator.
|
|
69
|
+
# Ignore the "reason: " from pytest.
|
|
70
|
+
if report.wasxfail and report.wasxfail != "reason: ":
|
|
71
|
+
reason = f": {report.wasxfail}"
|
|
72
|
+
|
|
73
|
+
if report.skipped:
|
|
74
|
+
directive = f"TODO expected failure{reason}"
|
|
75
|
+
self._tracker.add_not_ok(testcase, description, directive=directive)
|
|
76
|
+
elif report.passed:
|
|
77
|
+
directive = f"TODO unexpected success{reason}"
|
|
78
|
+
self._tracker.add_ok(testcase, description, directive=directive)
|
|
79
|
+
elif report.passed:
|
|
80
|
+
diagnostics = None
|
|
81
|
+
if self.log_passing_tests:
|
|
82
|
+
diagnostics = _make_as_diagnostics(report, self.show_capture)
|
|
83
|
+
self._tracker.add_ok(testcase, description, diagnostics=diagnostics)
|
|
84
|
+
elif report.failed:
|
|
85
|
+
diagnostics = _make_as_diagnostics(report, self.show_capture)
|
|
86
|
+
|
|
87
|
+
# pytest treats an unexpected success from unitest.expectedFailure
|
|
88
|
+
# as a failure.
|
|
89
|
+
# To match up with TAPTestResult and the TAP spec, treat the pass
|
|
90
|
+
# as an ok with a todo directive instead.
|
|
91
|
+
if "Unexpected success" in str(report.longrepr):
|
|
92
|
+
self._tracker.add_ok(
|
|
93
|
+
testcase, description, directive="TODO unexpected success"
|
|
94
|
+
)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
# A strict xfail that passes (i.e., XPASS) should be marked as a failure.
|
|
98
|
+
# The only indicator that strict xfail occurred
|
|
99
|
+
# for XPASS is to check longrepr.
|
|
100
|
+
if (
|
|
101
|
+
isinstance(report.longrepr, str)
|
|
102
|
+
and "[XPASS(strict)]" in report.longrepr
|
|
103
|
+
):
|
|
104
|
+
self._tracker.add_not_ok(
|
|
105
|
+
testcase,
|
|
106
|
+
description,
|
|
107
|
+
directive=f"unexpected success: {report.longrepr}",
|
|
108
|
+
)
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
self._tracker.add_not_ok(testcase, description, diagnostics=diagnostics)
|
|
112
|
+
elif report.skipped:
|
|
113
|
+
reason = report.longrepr[2].split(":", 1)[1].strip() # type: ignore
|
|
114
|
+
self._tracker.add_skip(testcase, description, reason)
|
|
115
|
+
|
|
116
|
+
@pytest.hookimpl()
|
|
117
|
+
def pytest_unconfigure(self, config: pytest.Config):
|
|
118
|
+
"""Dump the results."""
|
|
119
|
+
self._tracker.generate_tap_reports()
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def pytest_addoption(parser):
|
|
123
|
+
"""Include all the command line options."""
|
|
124
|
+
group = parser.getgroup("terminal reporting", "reporting", after="general")
|
|
125
|
+
group.addoption(
|
|
126
|
+
"--tap",
|
|
127
|
+
default=False,
|
|
128
|
+
dest="tap_stream",
|
|
129
|
+
action="store_true",
|
|
130
|
+
help="Stream TAP output instead of the default test runner output.",
|
|
131
|
+
)
|
|
132
|
+
# Deprecated, but keeping for backwards compatibility.
|
|
133
|
+
group.addoption(
|
|
134
|
+
"--tap-stream", default=False, action="store_true", help=argparse.SUPPRESS
|
|
135
|
+
)
|
|
136
|
+
group.addoption(
|
|
137
|
+
"--tap-files",
|
|
138
|
+
default=False,
|
|
139
|
+
action="store_true",
|
|
140
|
+
help="Store all TAP test results into individual files per test case.",
|
|
141
|
+
)
|
|
142
|
+
group.addoption(
|
|
143
|
+
"--tap-combined",
|
|
144
|
+
default=False,
|
|
145
|
+
action="store_true",
|
|
146
|
+
help="Store all TAP test results into a combined output file.",
|
|
147
|
+
)
|
|
148
|
+
group.addoption(
|
|
149
|
+
"--tap-outdir",
|
|
150
|
+
metavar="path",
|
|
151
|
+
help=(
|
|
152
|
+
"An optional output directory to write TAP files to. "
|
|
153
|
+
"If the directory does not exist, it will be created."
|
|
154
|
+
),
|
|
155
|
+
)
|
|
156
|
+
group.addoption(
|
|
157
|
+
"--tap-log-passing-tests",
|
|
158
|
+
default=False,
|
|
159
|
+
action="store_true",
|
|
160
|
+
help="Capture log information for passing tests to TAP report",
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@pytest.hookimpl(trylast=True)
|
|
165
|
+
def pytest_configure(config: pytest.Config) -> None:
|
|
166
|
+
"""Enable the plugin if the TAP flags are used."""
|
|
167
|
+
# The help printing uses the terminalreporter,
|
|
168
|
+
# which is unregistered by the streaming mode.
|
|
169
|
+
if config.option.help:
|
|
170
|
+
return
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
config.option.tap_stream
|
|
174
|
+
or config.option.tap_combined
|
|
175
|
+
or config.option.tap_files
|
|
176
|
+
):
|
|
177
|
+
config.pluginmanager.register(TAPPlugin(config), "tapplugin")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _make_as_diagnostics(report, show_capture):
|
|
181
|
+
"""Format a report as TAP diagnostic output."""
|
|
182
|
+
lines = report.longreprtext.splitlines(keepends=True)
|
|
183
|
+
|
|
184
|
+
if show_capture in SHOW_CAPTURE_LOG:
|
|
185
|
+
if lines:
|
|
186
|
+
lines[-1] += "\n"
|
|
187
|
+
lines += ["--- Captured Log ---\n"] + (
|
|
188
|
+
report.caplog.splitlines(keepends=True) or [""]
|
|
189
|
+
)
|
|
190
|
+
if show_capture in SHOW_CAPTURE_OUT:
|
|
191
|
+
if lines:
|
|
192
|
+
lines[-1] += "\n"
|
|
193
|
+
lines += ["--- Captured Out ---\n"] + (
|
|
194
|
+
report.capstdout.splitlines(keepends=True) or [""]
|
|
195
|
+
)
|
|
196
|
+
if show_capture in SHOW_CAPTUER_ERR:
|
|
197
|
+
if lines:
|
|
198
|
+
lines[-1] += "\n"
|
|
199
|
+
lines += ["--- Captured Err ---\n"] + (
|
|
200
|
+
report.capstderr.splitlines(keepends=True) or [""]
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return format_as_diagnostics(lines)
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
def test_includes_options(testdir):
|
|
2
|
+
"""All options are present in the help."""
|
|
3
|
+
result = testdir.runpytest("--help")
|
|
4
|
+
|
|
5
|
+
expected_option_flags = [
|
|
6
|
+
"*--tap *",
|
|
7
|
+
"*--tap-files*",
|
|
8
|
+
"*--tap-combined*",
|
|
9
|
+
"*--tap-outdir=path*",
|
|
10
|
+
"*--tap-log-passing-tests*",
|
|
11
|
+
]
|
|
12
|
+
result.stdout.fnmatch_lines(expected_option_flags)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_handle_help_with_stream(testdir):
|
|
16
|
+
"""The help prints when the stream option is given.
|
|
17
|
+
|
|
18
|
+
This demonstrates behavior reported in:
|
|
19
|
+
https://github.com/python-tap/pytest-tap/issues/59
|
|
20
|
+
"""
|
|
21
|
+
result = testdir.runpytest("--tap", "-h")
|
|
22
|
+
|
|
23
|
+
expected_option_flags = ["*--tap *"]
|
|
24
|
+
result.stdout.fnmatch_lines(expected_option_flags)
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
from tap.tracker import ENABLE_VERSION_13
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_stream(testdir, sample_test_file):
|
|
5
|
+
"""Results are streamed to stdout."""
|
|
6
|
+
result = testdir.runpytest_subprocess("--tap-stream")
|
|
7
|
+
|
|
8
|
+
result.stdout.fnmatch_lines(
|
|
9
|
+
[
|
|
10
|
+
"1..6",
|
|
11
|
+
"ok 1 test_stream.py::test_ok",
|
|
12
|
+
"not ok 2 test_stream.py::test_not_ok",
|
|
13
|
+
"ok 3 test_stream.py::test_params[foo]",
|
|
14
|
+
"ok 4 test_stream.py::test_params[bar]",
|
|
15
|
+
"ok 5 test_stream.py::test_skipped # SKIP some reason",
|
|
16
|
+
"not ok 6 test_stream.py::test_broken # TODO expected failure: a reason",
|
|
17
|
+
]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_stream_simple_flag(testdir, sample_test_file):
|
|
22
|
+
"""Results are streamed to stdout when the shorter streaming flag."""
|
|
23
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
24
|
+
|
|
25
|
+
result.stdout.fnmatch_lines(
|
|
26
|
+
[
|
|
27
|
+
"1..6",
|
|
28
|
+
"ok 1 test_stream_simple_flag.py::test_ok",
|
|
29
|
+
"not ok 2 test_stream_simple_flag.py::test_not_ok",
|
|
30
|
+
"ok 3 test_stream_simple_flag.py::test_params[foo]",
|
|
31
|
+
"ok 4 test_stream_simple_flag.py::test_params[bar]",
|
|
32
|
+
"ok 5 test_stream_simple_flag.py::test_skipped # SKIP some reason",
|
|
33
|
+
"not ok 6 test_stream_simple_flag.py::test_broken "
|
|
34
|
+
"# TODO expected failure: a reason",
|
|
35
|
+
]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_combined(testdir, sample_test_file):
|
|
40
|
+
"""Tests are combined into a single output file."""
|
|
41
|
+
testdir.runpytest_subprocess("--tap-combined")
|
|
42
|
+
|
|
43
|
+
testresults = testdir.tmpdir.join("testresults.tap")
|
|
44
|
+
assert testresults.check()
|
|
45
|
+
actual_results = [
|
|
46
|
+
line.strip() for line in testresults.readlines() if not line.startswith("#")
|
|
47
|
+
]
|
|
48
|
+
expected_results = [
|
|
49
|
+
"1..6",
|
|
50
|
+
"ok 1 test_combined.py::test_ok",
|
|
51
|
+
"not ok 2 test_combined.py::test_not_ok",
|
|
52
|
+
"ok 3 test_combined.py::test_params[foo]",
|
|
53
|
+
"ok 4 test_combined.py::test_params[bar]",
|
|
54
|
+
"ok 5 test_combined.py::test_skipped # SKIP some reason",
|
|
55
|
+
"not ok 6 test_combined.py::test_broken # TODO expected failure: a reason",
|
|
56
|
+
]
|
|
57
|
+
# If the dependencies for version 13 happen to be installed, tweak the output.
|
|
58
|
+
if ENABLE_VERSION_13:
|
|
59
|
+
expected_results.insert(0, "TAP version 13")
|
|
60
|
+
assert actual_results == expected_results
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_files(testdir, sample_test_file):
|
|
64
|
+
"""Tests are split into separate files."""
|
|
65
|
+
testdir.makepyfile(
|
|
66
|
+
test_other_file="""
|
|
67
|
+
def test_other_ok():
|
|
68
|
+
assert True
|
|
69
|
+
"""
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
testdir.runpytest_subprocess("--tap-files")
|
|
73
|
+
|
|
74
|
+
sample_tap = testdir.tmpdir.join("test_files.py.tap")
|
|
75
|
+
assert sample_tap.check()
|
|
76
|
+
other_tap = testdir.tmpdir.join("test_other_file.py.tap")
|
|
77
|
+
assert other_tap.check()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_outdir(testdir, sample_test_file):
|
|
81
|
+
"""Tests are put in the output directory."""
|
|
82
|
+
testdir.runpytest_subprocess("--tap-outdir", "results", "--tap-combined")
|
|
83
|
+
|
|
84
|
+
outdir = testdir.tmpdir.join("results")
|
|
85
|
+
testresults = outdir.join("testresults.tap")
|
|
86
|
+
assert testresults.check()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_logging(testdir, sample_test_file):
|
|
90
|
+
"""Test logs are added to TAP diagnostics."""
|
|
91
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
92
|
+
result.stdout.fnmatch_lines(
|
|
93
|
+
[
|
|
94
|
+
"# --- Captured Log ---",
|
|
95
|
+
"*Running test_not_ok*",
|
|
96
|
+
"# --- Captured Out ---",
|
|
97
|
+
"# --- Captured Err ---",
|
|
98
|
+
]
|
|
99
|
+
)
|
|
100
|
+
result.stdout.no_fnmatch_line("*Running test_ok*")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_log_passing_tests(testdir, sample_test_file):
|
|
104
|
+
"""Test logs are added to TAP diagnostics."""
|
|
105
|
+
result = testdir.runpytest_subprocess(
|
|
106
|
+
"--tap", "--tap-log-passing-tests", "--log-level", "INFO"
|
|
107
|
+
)
|
|
108
|
+
result.stdout.fnmatch_lines(
|
|
109
|
+
[
|
|
110
|
+
"# --- Captured Log ---",
|
|
111
|
+
"*Running test_ok*",
|
|
112
|
+
]
|
|
113
|
+
)
|
|
114
|
+
result.stdout.no_fnmatch_line("*Debug logging info*")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_xfail_no_reason(testdir):
|
|
118
|
+
"""xfails output gracefully when no reason is provided."""
|
|
119
|
+
testdir.makepyfile(
|
|
120
|
+
"""
|
|
121
|
+
import pytest
|
|
122
|
+
|
|
123
|
+
@pytest.mark.xfail(strict=False)
|
|
124
|
+
def test_unexpected_success():
|
|
125
|
+
assert True
|
|
126
|
+
|
|
127
|
+
@pytest.mark.xfail(strict=False)
|
|
128
|
+
def test_expected_failure():
|
|
129
|
+
assert False
|
|
130
|
+
"""
|
|
131
|
+
)
|
|
132
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
133
|
+
|
|
134
|
+
result.stdout.fnmatch_lines(
|
|
135
|
+
[
|
|
136
|
+
"ok 1 test_xfail_no_reason.py::test_unexpected_success "
|
|
137
|
+
"# TODO unexpected success",
|
|
138
|
+
"not ok 2 test_xfail_no_reason.py::test_expected_failure "
|
|
139
|
+
"# TODO expected failure",
|
|
140
|
+
]
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def test_xfail_nonstrict(testdir):
|
|
145
|
+
"""Non-strict xfails are treated as TODO directives."""
|
|
146
|
+
testdir.makepyfile(
|
|
147
|
+
"""
|
|
148
|
+
import pytest
|
|
149
|
+
|
|
150
|
+
@pytest.mark.xfail(strict=False, reason='a reason')
|
|
151
|
+
def test_unexpected_success():
|
|
152
|
+
assert True
|
|
153
|
+
|
|
154
|
+
@pytest.mark.xfail(strict=False, reason='a reason')
|
|
155
|
+
def test_expected_failure():
|
|
156
|
+
assert False
|
|
157
|
+
"""
|
|
158
|
+
)
|
|
159
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
160
|
+
|
|
161
|
+
result.stdout.fnmatch_lines(
|
|
162
|
+
[
|
|
163
|
+
"ok 1 test_xfail_nonstrict.py::test_unexpected_success "
|
|
164
|
+
"# TODO unexpected success: a reason",
|
|
165
|
+
"not ok 2 test_xfail_nonstrict.py::test_expected_failure "
|
|
166
|
+
"# TODO expected failure: a reason",
|
|
167
|
+
]
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_xfail_strict(testdir):
|
|
172
|
+
"""xfail strict mode handles expected behavior."""
|
|
173
|
+
testdir.makepyfile(
|
|
174
|
+
"""
|
|
175
|
+
import pytest
|
|
176
|
+
|
|
177
|
+
@pytest.mark.xfail(strict=True, reason='a reason')
|
|
178
|
+
def test_unexpected_success():
|
|
179
|
+
assert True
|
|
180
|
+
|
|
181
|
+
@pytest.mark.xfail(strict=True, reason='a reason')
|
|
182
|
+
def test_expected_failure():
|
|
183
|
+
assert False
|
|
184
|
+
"""
|
|
185
|
+
)
|
|
186
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
187
|
+
|
|
188
|
+
result.stdout.fnmatch_lines(
|
|
189
|
+
[
|
|
190
|
+
"not ok 1 test_xfail_strict.py::test_unexpected_success "
|
|
191
|
+
"# unexpected success: [XPASS(strict)] a reason",
|
|
192
|
+
"not ok 2 test_xfail_strict.py::test_expected_failure "
|
|
193
|
+
"# TODO expected failure: a reason",
|
|
194
|
+
]
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_unittest_expected_failure(testdir):
|
|
199
|
+
"""The plugin handles unittest's expectedFailure decorator behavior."""
|
|
200
|
+
testdir.makepyfile(
|
|
201
|
+
"""
|
|
202
|
+
import pytest
|
|
203
|
+
import unittest
|
|
204
|
+
|
|
205
|
+
class TestExpectedFailure(unittest.TestCase):
|
|
206
|
+
@unittest.expectedFailure
|
|
207
|
+
def test_when_failing(self):
|
|
208
|
+
assert False
|
|
209
|
+
|
|
210
|
+
@unittest.expectedFailure
|
|
211
|
+
def test_when_passing(self):
|
|
212
|
+
assert True
|
|
213
|
+
"""
|
|
214
|
+
)
|
|
215
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
216
|
+
|
|
217
|
+
expected = [
|
|
218
|
+
"not ok 1 test_unittest_expected_failure.py::"
|
|
219
|
+
"TestExpectedFailure.test_when_failing # TODO expected failure",
|
|
220
|
+
"ok 2 test_unittest_expected_failure.py::"
|
|
221
|
+
"TestExpectedFailure.test_when_passing # TODO unexpected success",
|
|
222
|
+
]
|
|
223
|
+
result.stdout.fnmatch_lines(expected)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def test_setup_failure(testdir):
|
|
227
|
+
"""A failure in test setup is marked as an error.
|
|
228
|
+
|
|
229
|
+
See https://github.com/python-tap/pytest-tap/issues/39.
|
|
230
|
+
"""
|
|
231
|
+
testdir.makepyfile(
|
|
232
|
+
"""
|
|
233
|
+
import pytest
|
|
234
|
+
|
|
235
|
+
@pytest.fixture
|
|
236
|
+
def bad_fixture():
|
|
237
|
+
raise Exception('boom')
|
|
238
|
+
|
|
239
|
+
def test_with_bad_fixture(bad_fixture):
|
|
240
|
+
assert True
|
|
241
|
+
"""
|
|
242
|
+
)
|
|
243
|
+
result = testdir.runpytest_subprocess("--tap")
|
|
244
|
+
|
|
245
|
+
result.stdout.fnmatch_lines(
|
|
246
|
+
["1..1", "not ok 1 test_setup_failure.py::test_with_bad_fixture"]
|
|
247
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""The xdist plugin isn't installed so these tests check against the hook contract."""
|
|
2
|
+
|
|
3
|
+
from unittest import mock
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from pytest_tap.plugin import TAPPlugin
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.parametrize(
|
|
11
|
+
"combined, stream, expected",
|
|
12
|
+
[
|
|
13
|
+
(False, True, True),
|
|
14
|
+
(True, False, True),
|
|
15
|
+
(False, False, False),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
18
|
+
def test_sets_plan_streaming(combined, stream, expected):
|
|
19
|
+
"""The plan is set for the given mode conditions by a node's collection report."""
|
|
20
|
+
config = mock.Mock()
|
|
21
|
+
config.option.tap_outdir = "."
|
|
22
|
+
config.option.tap_combined = combined
|
|
23
|
+
config.option.tap_stream = stream
|
|
24
|
+
plugin = TAPPlugin(config)
|
|
25
|
+
node = mock.Mock()
|
|
26
|
+
test_ids = ["a", "b", "c"]
|
|
27
|
+
|
|
28
|
+
plugin.pytest_xdist_node_collection_finished(node, test_ids)
|
|
29
|
+
|
|
30
|
+
assert (plugin._tracker.plan == 3) is expected
|
pytest-tap-3.3/MANIFEST.in
DELETED
pytest-tap-3.3/README.rst
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
pytest-tap
|
|
2
|
-
==========
|
|
3
|
-
|
|
4
|
-
|version| |license| |travis| |travismac| |appveyor| |coverage|
|
|
5
|
-
|
|
6
|
-
.. |version| image:: https://img.shields.io/pypi/v/pytest-tap.svg
|
|
7
|
-
:target: https://pypi.python.org/pypi/pytest-tap
|
|
8
|
-
:alt: PyPI version
|
|
9
|
-
.. |license| image:: https://img.shields.io/pypi/l/pytest-tap.svg
|
|
10
|
-
:target: https://raw.githubusercontent.com/python-tap/pytest-tap/master/LICENSE
|
|
11
|
-
:alt: BSD license
|
|
12
|
-
.. |coverage| image:: https://img.shields.io/codecov/c/github/python-tap/pytest-tap.svg
|
|
13
|
-
:target: https://codecov.io/github/python-tap/pytest-tap
|
|
14
|
-
:alt: Coverage
|
|
15
|
-
|
|
16
|
-
Test Anything Protocol (TAP) reporting plugin for
|
|
17
|
-
`pytest <http://pytest.org/latest/>`_
|
|
18
|
-
|
|
19
|
-
The plugin outputs test results as TAP data in a variety of formats.
|
|
20
|
-
See the `tappy documentation <http://tappy.readthedocs.io/en/latest/producers.html#pytest-tap-plugin>`_
|
|
21
|
-
for more information on usage.
|
|
22
|
-
|
|
23
|
-
Install
|
|
24
|
-
-------
|
|
25
|
-
|
|
26
|
-
.. code-block:: console
|
|
27
|
-
|
|
28
|
-
$ pip install pytest-tap
|
|
29
|
-
|
|
30
|
-
Usage
|
|
31
|
-
-----
|
|
32
|
-
|
|
33
|
-
This is an example usage from the plugin's test suite.
|
|
34
|
-
|
|
35
|
-
.. code-block:: console
|
|
36
|
-
|
|
37
|
-
$ pytest --tap-stream
|
|
38
|
-
1..12
|
|
39
|
-
ok 1 - TestPlugin.test_generates_reports_for_combined
|
|
40
|
-
ok 2 - TestPlugin.test_generates_reports_for_files
|
|
41
|
-
ok 3 - TestPlugin.test_generates_reports_for_stream
|
|
42
|
-
ok 4 - TestPlugin.test_includes_options
|
|
43
|
-
ok 5 - TestPlugin.test_skips_reporting_with_no_output_option
|
|
44
|
-
ok 6 - TestPlugin.test_track_when_call_report
|
|
45
|
-
ok 7 - TestPlugin.test_tracker_combined_set
|
|
46
|
-
ok 8 - TestPlugin.test_tracker_outdir_set
|
|
47
|
-
ok 9 - TestPlugin.test_tracker_stream_set
|
|
48
|
-
ok 10 - TestPlugin.test_tracks_not_ok
|
|
49
|
-
ok 11 - TestPlugin.test_tracks_ok
|
|
50
|
-
ok 12 - TestPlugin.test_tracks_skip
|
|
51
|
-
|
|
52
|
-
Contributing
|
|
53
|
-
------------
|
|
54
|
-
|
|
55
|
-
The project welcomes contributions of all kinds.
|
|
56
|
-
Check out the `contributing guidelines <https://github.com/python-tap/pytest-tap/blob/master/.github/contributing.md>`_
|
|
57
|
-
for tips on how to get started.
|
pytest-tap-3.3/docs/releases.rst
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
Releases
|
|
2
|
-
========
|
|
3
|
-
|
|
4
|
-
Version 3.3, October 27, 2021
|
|
5
|
-
-----------------------------
|
|
6
|
-
|
|
7
|
-
* Add support for Python 3.10.
|
|
8
|
-
* Fix bug with help printing when streaming mode is enabled (#59).
|
|
9
|
-
* Drop support for Python 3.5 (it is end-of-life).
|
|
10
|
-
* Remove unmaintained (and likely inaccurate) locale info.
|
|
11
|
-
|
|
12
|
-
Version 3.2, November 7, 2020
|
|
13
|
-
-----------------------------
|
|
14
|
-
|
|
15
|
-
* Add support for Python 3.8.
|
|
16
|
-
* Add support for Python 3.9.
|
|
17
|
-
* Handle ``unittest.expectedFailure`` and ``pytest.xfail``
|
|
18
|
-
in a way that is more consistent
|
|
19
|
-
with the TAP specification.
|
|
20
|
-
|
|
21
|
-
Version 3.1, Released March 25, 2020
|
|
22
|
-
------------------------------------
|
|
23
|
-
|
|
24
|
-
* Fix reporting that was broken by the removal
|
|
25
|
-
of a deprecated feature in pytest 5.4.
|
|
26
|
-
|
|
27
|
-
Version 3.0, Released January 28, 2020
|
|
28
|
-
--------------------------------------
|
|
29
|
-
|
|
30
|
-
* Drop support for Python 2.
|
|
31
|
-
|
|
32
|
-
Version 2.5, Released December 26, 2019
|
|
33
|
-
---------------------------------------
|
|
34
|
-
|
|
35
|
-
* Last supported version for Python 2.
|
|
36
|
-
* Pin tap.py to a version range that supports Python 2.
|
|
37
|
-
|
|
38
|
-
Version 2.4, Released October 21, 2019
|
|
39
|
-
--------------------------------------
|
|
40
|
-
|
|
41
|
-
* Handle failures that occur from setup.
|
|
42
|
-
This will catch errors that may happen in fixtures.
|
|
43
|
-
* Drop support for Python 3.4 (it is end-of-life).
|
|
44
|
-
* Add support for Python 3.7.
|
|
45
|
-
|
|
46
|
-
Version 2.3, Released September 16, 2018
|
|
47
|
-
----------------------------------------
|
|
48
|
-
|
|
49
|
-
* Improve xfail handling.
|
|
50
|
-
Honor strict xfail mode.
|
|
51
|
-
Use TODO instead of SKIP directive to better align with TAP specification.
|
|
52
|
-
* Output the plan line (``1..N``) first.
|
|
53
|
-
|
|
54
|
-
Version 2.2, Released January 9, 2018
|
|
55
|
-
-------------------------------------
|
|
56
|
-
|
|
57
|
-
* Update output format to match closer to pytest styling.
|
|
58
|
-
* Drop support for Python 3.3 (it is end-of-life).
|
|
59
|
-
|
|
60
|
-
Version 2.1, Released August 12, 2017
|
|
61
|
-
-------------------------------------
|
|
62
|
-
|
|
63
|
-
* Add support for Python 3.6.
|
|
64
|
-
* Fix crash when running with pytest-xdist (#27).
|
|
65
|
-
|
|
66
|
-
Version 2.0, Released August 1, 2016
|
|
67
|
-
------------------------------------
|
|
68
|
-
|
|
69
|
-
* Update to tap.py 2.0.
|
|
70
|
-
This update drops the indirect dependencies on nose and pygments.
|
|
71
|
-
* Improve handling of skips and xfails.
|
|
72
|
-
* Suppress ``# TAP results for TestCase`` for streaming.
|
|
73
|
-
This header makes little sense for pytest's test function paradigm.
|
|
74
|
-
Including the header generated extra noise for each function.
|
|
75
|
-
* Drop support for Python 2.6
|
|
76
|
-
|
|
77
|
-
Version 1.9, Released June 11, 2016
|
|
78
|
-
-----------------------------------
|
|
79
|
-
|
|
80
|
-
* Initial release as stand-alone plugin.
|
|
81
|
-
The version number aligns with tappy.
|
pytest-tap-3.3/setup.cfg
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
[bumpversion]
|
|
2
|
-
current_version = 3.3
|
|
3
|
-
commit = True
|
|
4
|
-
tag = True
|
|
5
|
-
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
|
6
|
-
serialize = {major}.{minor}
|
|
7
|
-
|
|
8
|
-
[bumpversion:file:setup.py]
|
|
9
|
-
|
|
10
|
-
[bumpversion:file:src/pytest_tap/__init__.py]
|
|
11
|
-
|
|
12
|
-
[metadata]
|
|
13
|
-
license-file = LICENSE
|
|
14
|
-
|
|
15
|
-
[flake8]
|
|
16
|
-
max-line-length = 88
|
|
17
|
-
|
|
18
|
-
[egg_info]
|
|
19
|
-
tag_build =
|
|
20
|
-
tag_date = 0
|
|
21
|
-
|
pytest-tap-3.3/setup.py
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
pytest-tap is a reporting plugin for pytest that outputs
|
|
3
|
-
`Test Anything Protocol (TAP) <http://testanything.org/>`_ data.
|
|
4
|
-
TAP is a line based test protocol for recording test data in a standard way.
|
|
5
|
-
|
|
6
|
-
Follow development on `GitHub <https://github.com/python-tap/pytest-tap>`_.
|
|
7
|
-
Developer documentation is on
|
|
8
|
-
`Read the Docs <https://tappy.readthedocs.io/>`_.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from setuptools import find_packages, setup
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if __name__ == "__main__":
|
|
15
|
-
with open("docs/releases.rst", "r") as f:
|
|
16
|
-
releases = f.read()
|
|
17
|
-
|
|
18
|
-
long_description = __doc__ + "\n\n" + releases
|
|
19
|
-
|
|
20
|
-
setup(
|
|
21
|
-
name="pytest-tap",
|
|
22
|
-
version="3.3",
|
|
23
|
-
url="https://github.com/python-tap/pytest-tap",
|
|
24
|
-
license="BSD",
|
|
25
|
-
author="Matt Layman",
|
|
26
|
-
author_email="matthewlayman@gmail.com",
|
|
27
|
-
description="Test Anything Protocol (TAP) reporting plugin for pytest",
|
|
28
|
-
long_description=long_description,
|
|
29
|
-
packages=find_packages(where="src"),
|
|
30
|
-
package_dir={"": "src"},
|
|
31
|
-
entry_points={"pytest11": ["tap = pytest_tap.plugin"]},
|
|
32
|
-
include_package_data=True,
|
|
33
|
-
zip_safe=False,
|
|
34
|
-
platforms="any",
|
|
35
|
-
install_requires=["pytest>=3.0", "tap.py>=3.0,<4.0"],
|
|
36
|
-
classifiers=[
|
|
37
|
-
"Development Status :: 5 - Production/Stable",
|
|
38
|
-
"Framework :: Pytest",
|
|
39
|
-
"Intended Audience :: Developers",
|
|
40
|
-
"License :: OSI Approved :: BSD License",
|
|
41
|
-
"Operating System :: OS Independent",
|
|
42
|
-
"Programming Language :: Python :: 3.6",
|
|
43
|
-
"Programming Language :: Python :: 3.7",
|
|
44
|
-
"Programming Language :: Python :: 3.8",
|
|
45
|
-
"Programming Language :: Python :: 3.9",
|
|
46
|
-
"Programming Language :: Python :: 3.10",
|
|
47
|
-
"Programming Language :: Python :: Implementation :: PyPy",
|
|
48
|
-
"Topic :: Software Development :: Testing",
|
|
49
|
-
],
|
|
50
|
-
keywords=["TAP", "unittest", "pytest"],
|
|
51
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.3"
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
from tap.formatter import format_as_diagnostics
|
|
5
|
-
from tap.tracker import Tracker
|
|
6
|
-
|
|
7
|
-
# Because of how pytest hooks work, there is not much choice
|
|
8
|
-
# except to use module level state. Ugh.
|
|
9
|
-
tracker = Tracker()
|
|
10
|
-
ENABLED = False
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def pytest_addoption(parser):
|
|
14
|
-
"""Include all the command line options."""
|
|
15
|
-
group = parser.getgroup("terminal reporting", "reporting", after="general")
|
|
16
|
-
group.addoption(
|
|
17
|
-
"--tap-stream",
|
|
18
|
-
default=False,
|
|
19
|
-
action="store_true",
|
|
20
|
-
help="Stream TAP output instead of the default test runner output.",
|
|
21
|
-
)
|
|
22
|
-
group.addoption(
|
|
23
|
-
"--tap-files",
|
|
24
|
-
default=False,
|
|
25
|
-
action="store_true",
|
|
26
|
-
help="Store all TAP test results into individual files per test case.",
|
|
27
|
-
)
|
|
28
|
-
group.addoption(
|
|
29
|
-
"--tap-combined",
|
|
30
|
-
default=False,
|
|
31
|
-
action="store_true",
|
|
32
|
-
help="Store all TAP test results into a combined output file.",
|
|
33
|
-
)
|
|
34
|
-
group.addoption(
|
|
35
|
-
"--tap-outdir",
|
|
36
|
-
metavar="path",
|
|
37
|
-
help=(
|
|
38
|
-
"An optional output directory to write TAP files to. "
|
|
39
|
-
"If the directory does not exist, it will be created."
|
|
40
|
-
),
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@pytest.mark.trylast
|
|
45
|
-
def pytest_configure(config):
|
|
46
|
-
"""Set all the options before the test run."""
|
|
47
|
-
# The help printing uses the terminalreporter,
|
|
48
|
-
# which is unregistered by the streaming mode.
|
|
49
|
-
if config.option.help:
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
global ENABLED
|
|
53
|
-
ENABLED = (
|
|
54
|
-
config.option.tap_stream
|
|
55
|
-
or config.option.tap_combined
|
|
56
|
-
or config.option.tap_files
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
tracker.outdir = config.option.tap_outdir
|
|
60
|
-
tracker.combined = config.option.tap_combined
|
|
61
|
-
if config.option.tap_stream:
|
|
62
|
-
reporter = config.pluginmanager.getplugin("terminalreporter")
|
|
63
|
-
if reporter:
|
|
64
|
-
config.pluginmanager.unregister(reporter)
|
|
65
|
-
tracker.streaming = True
|
|
66
|
-
tracker.stream = sys.stdout
|
|
67
|
-
# A common pytest pattern is to use test functions without classes.
|
|
68
|
-
# The header looks really dumb for that pattern because it puts
|
|
69
|
-
# out a lot of line noise since every function gets its own header.
|
|
70
|
-
# Disable it automatically for streaming.
|
|
71
|
-
tracker.header = False
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def pytest_runtestloop(session):
|
|
75
|
-
"""Output the plan line first."""
|
|
76
|
-
option = session.config.option
|
|
77
|
-
if ENABLED and (option.tap_stream or option.tap_combined):
|
|
78
|
-
tracker.set_plan(session.testscollected)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def pytest_runtest_logreport(report):
|
|
82
|
-
"""Add a test result to the tracker."""
|
|
83
|
-
if not ENABLED:
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
is_trackable_result = (
|
|
87
|
-
(report.when == "setup" and report.outcome == "skipped")
|
|
88
|
-
or (report.when == "setup" and report.outcome == "failed")
|
|
89
|
-
or report.when == "call"
|
|
90
|
-
)
|
|
91
|
-
if not is_trackable_result:
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
description = str(report.location[0]) + "::" + str(report.location[2])
|
|
95
|
-
testcase = report.location[0]
|
|
96
|
-
|
|
97
|
-
# Handle xfails first because they report in unusual ways.
|
|
98
|
-
# Non-strict xfails will include `wasxfail` while strict xfails won't.
|
|
99
|
-
if hasattr(report, "wasxfail"):
|
|
100
|
-
reason = ""
|
|
101
|
-
# pytest adds an ugly "reason: " for expectedFailure
|
|
102
|
-
# even though the standard library doesn't accept a reason for that decorator.
|
|
103
|
-
# Ignore the "reason: " from pytest.
|
|
104
|
-
if report.wasxfail and report.wasxfail != "reason: ":
|
|
105
|
-
reason = ": {}".format(report.wasxfail)
|
|
106
|
-
|
|
107
|
-
if report.skipped:
|
|
108
|
-
directive = "TODO expected failure{}".format(reason)
|
|
109
|
-
tracker.add_not_ok(testcase, description, directive=directive)
|
|
110
|
-
elif report.passed:
|
|
111
|
-
directive = "TODO unexpected success{}".format(reason)
|
|
112
|
-
tracker.add_ok(testcase, description, directive=directive)
|
|
113
|
-
elif report.passed:
|
|
114
|
-
tracker.add_ok(testcase, description)
|
|
115
|
-
elif report.failed:
|
|
116
|
-
diagnostics = _make_as_diagnostics(report)
|
|
117
|
-
|
|
118
|
-
# pytest treats an unexpected success from unitest.expectedFailure as a failure.
|
|
119
|
-
# To match up with TAPTestResult and the TAP spec, treat the pass
|
|
120
|
-
# as an ok with a todo directive instead.
|
|
121
|
-
if isinstance(report.longrepr, str) and "Unexpected success" in report.longrepr:
|
|
122
|
-
tracker.add_ok(testcase, description, directive="TODO unexpected success")
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
# A strict xfail that passes (i.e., XPASS) should be marked as a failure.
|
|
126
|
-
# The only indicator that strict xfail occurred for XPASS is to check longrepr.
|
|
127
|
-
if isinstance(report.longrepr, str) and "[XPASS(strict)]" in report.longrepr:
|
|
128
|
-
tracker.add_not_ok(
|
|
129
|
-
testcase,
|
|
130
|
-
description,
|
|
131
|
-
directive="unexpected success: {}".format(report.longrepr),
|
|
132
|
-
)
|
|
133
|
-
return
|
|
134
|
-
|
|
135
|
-
tracker.add_not_ok(testcase, description, diagnostics=diagnostics)
|
|
136
|
-
elif report.skipped:
|
|
137
|
-
reason = report.longrepr[2].split(":", 1)[1].strip()
|
|
138
|
-
tracker.add_skip(testcase, description, reason)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _make_as_diagnostics(report):
|
|
142
|
-
"""Format a report as TAP diagnostic output."""
|
|
143
|
-
lines = report.longreprtext.splitlines(keepends=True)
|
|
144
|
-
return format_as_diagnostics(lines)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def pytest_unconfigure(config):
|
|
148
|
-
"""Dump the results."""
|
|
149
|
-
if ENABLED:
|
|
150
|
-
tracker.generate_tap_reports()
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
AUTHORS
|
|
2
|
-
LICENSE
|
|
3
|
-
MANIFEST.in
|
|
4
|
-
README.rst
|
|
5
|
-
setup.cfg
|
|
6
|
-
setup.py
|
|
7
|
-
docs/releases.rst
|
|
8
|
-
src/pytest_tap/__init__.py
|
|
9
|
-
src/pytest_tap/plugin.py
|
|
10
|
-
src/pytest_tap.egg-info/PKG-INFO
|
|
11
|
-
src/pytest_tap.egg-info/SOURCES.txt
|
|
12
|
-
src/pytest_tap.egg-info/dependency_links.txt
|
|
13
|
-
src/pytest_tap.egg-info/entry_points.txt
|
|
14
|
-
src/pytest_tap.egg-info/not-zip-safe
|
|
15
|
-
src/pytest_tap.egg-info/requires.txt
|
|
16
|
-
src/pytest_tap.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pytest_tap
|
|
File without changes
|