Skip to content

Commit 342720e

Browse files
Only store failed tests mpl-pytest (#113)
* Only include failed tests when uploading * test: try a failure live * Update ultraplot/tests/test_1dplots.py --------- Co-authored-by: Matthew R. Becker <beckermr@users.noreply.github.com>
1 parent 43c26b8 commit 342720e

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

.github/workflows/build-ultraplot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
micromamba activate ultraplot-dev
8282
mkdir -p results
8383
python -c "import ultraplot as plt; plt.config.Configurator()._save_yaml('ultraplot.yml')"
84-
pytest --mpl --mpl-baseline-path=baseline --mpl-generate-summary=html --mpl-results-path=./results/ --mpl-default-style="./ultraplot.yml"
84+
pytest --mpl --mpl-baseline-path=baseline --mpl-generate-summary=html --mpl-results-path=./results/ --mpl-default-style="./ultraplot.yml" --store-failed-only ultraplot/tests
8585
8686
# Return the html output of the comparison even if failed
8787
- name: Upload comparison failures

ultraplot/tests/conftest.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import os, shutil, pytest, re
2+
from pathlib import Path
3+
import warnings
4+
5+
warnings.simplefilter("ignore")
6+
warnings.filterwarnings(
7+
"ignore", message="Bad key .* in file .*ultraplot.yml", module="matplotlib"
8+
)
9+
10+
11+
# Define command line option
12+
def pytest_addoption(parser):
13+
parser.addoption(
14+
"--store-failed-only",
15+
action="store_true",
16+
help="Store only failed matplotlib comparison images",
17+
)
18+
19+
20+
class StoreFailedMplPlugin:
21+
def __init__(self, config):
22+
self.config = config
23+
24+
# Get base directories as Path objects
25+
self.result_dir = Path(config.getoption("--mpl-results-path", "./results"))
26+
self.baseline_dir = Path(config.getoption("--mpl-baseline-path", "./baseline"))
27+
28+
print(f"Store Failed MPL Plugin initialized")
29+
print(f"Result dir: {self.result_dir}")
30+
31+
def _has_mpl_marker(self, report: pytest.TestReport):
32+
"""Check if the test has the mpl_image_compare marker."""
33+
return report.keywords.get("mpl_image_compare", False)
34+
35+
def _remove_success(self, report: pytest.TestReport):
36+
"""Remove successful test images."""
37+
38+
pattern = r"(?P<sep>::|/)|\[|\]|\.py"
39+
name = re.sub(
40+
pattern,
41+
lambda m: "." if m.group("sep") else "_" if m.group(0) == "[" else "",
42+
report.nodeid,
43+
)
44+
target = (self.result_dir / name).absolute()
45+
if target.is_dir():
46+
print(f"Removing {report.nodeid}")
47+
shutil.rmtree(target)
48+
else:
49+
print(f"Did not find {report.nodeid}")
50+
51+
@pytest.hookimpl(trylast=True)
52+
def pytest_runtest_logreport(self, report):
53+
"""Hook that processes each test report."""
54+
if report.when == "call":
55+
# Delete successfull tests
56+
if report.failed == False:
57+
if self._has_mpl_marker(report):
58+
self._remove_success(report)
59+
else:
60+
print(f"{report.failed=}")
61+
print(f"Skipping {report.nodeid}")
62+
63+
64+
# Register the plugin if the option is used
65+
def pytest_configure(config):
66+
print("Configuring StoreFailedMplPlugin")
67+
try:
68+
if config.getoption("--store-failed-only", False):
69+
print("Registering StoreFailedMplPlugin")
70+
config.pluginmanager.register(StoreFailedMplPlugin(config))
71+
except Exception as e:
72+
print(f"Error during plugin configuration: {e}")

0 commit comments

Comments
 (0)