Skip to content

Commit 7fc69d6

Browse files
committed
support xdist via pickling the per-worker results
1 parent 1117ba5 commit 7fc69d6

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

cwltest/plugin.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import argparse
44
import json
55
import os
6+
import pickle # nosec
67
import time
78
import traceback
89
from collections.abc import Iterator
@@ -389,15 +390,59 @@ def pytest_configure(config: pytest.Config) -> None:
389390
config.cwl_results = cwl_results # type: ignore[attr-defined]
390391

391392

392-
def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
393+
def _zip_results(
394+
cwl_results: list[tuple[dict[str, Any], utils.TestResult]],
395+
) -> tuple[list[dict[str, Any]], list[utils.TestResult]]:
396+
tests, results = (list(item) for item in zip(*cwl_results))
397+
return tests, results
398+
399+
400+
def pytest_sessionfinish(session: pytest.Session) -> None:
393401
"""Generate badges."""
402+
cwl_badgedir = session.config.getoption("cwl_badgedir")
403+
if not cwl_badgedir:
404+
return
405+
394406
cwl_results = cast(
395407
list[tuple[dict[str, Any], utils.TestResult]],
396-
getattr(session.config, "cwl_results", None),
408+
session.config.cwl_results, # type: ignore[attr-defined]
397409
)
398-
if not cwl_results:
399-
return
400-
tests, results = (list(item) for item in zip(*cwl_results))
410+
411+
if session.config.pluginmanager.has_plugin("xdist"):
412+
import xdist # type: ignore[import-untyped]
413+
414+
directory = cast(
415+
pytest.TempPathFactory,
416+
session.config._tmp_path_factory, # type: ignore[attr-defined]
417+
).getbasetemp()
418+
if xdist.is_xdist_worker(session):
419+
if not cwl_results:
420+
return
421+
pickle_filename = f"cwltest_{xdist.get_xdist_worker_id(session)}.pickle"
422+
with (directory.parent / pickle_filename).open("wb") as handle:
423+
pickle.dump(
424+
_zip_results(cwl_results), handle, protocol=pickle.HIGHEST_PROTOCOL
425+
)
426+
return
427+
428+
if xdist.is_xdist_controller(session):
429+
tests: list[dict[str, Any]] = []
430+
results: list[utils.TestResult] = []
431+
for pickle_filepath in directory.glob("cwltest_*"):
432+
with pickle_filepath.open("rb") as handle:
433+
new_tests, new_results = pickle.load(handle) # nosec
434+
tests.extend(new_tests)
435+
results.extend(new_results)
436+
else:
437+
if not cwl_results:
438+
return
439+
tests, results = _zip_results(cwl_results)
440+
441+
else:
442+
if not cwl_results:
443+
return
444+
tests, results = _zip_results(cwl_results)
445+
401446
(
402447
total,
403448
passed,
@@ -409,8 +454,8 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
409454
nunsupported,
410455
_,
411456
) = utils.parse_results(results, tests)
412-
if cwl_badgedir := session.config.getoption("cwl_badgedir"):
413-
utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported)
457+
458+
utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported)
414459

415460

416461
def pytest_addhooks(pluginmanager: pytest.PytestPluginManager) -> None:

tests/test_plugin.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,35 @@ def test_badgedir(pytester: pytest.Pytester) -> None:
8888
_load_v1_0_dir(path)
8989
badge_path = path.parent / "cwl-badges"
9090
assert not badge_path.exists()
91-
pytester.runpytest(
91+
result = pytester.runpytest_inprocess(
9292
"-k", "conformance_test_v1.0.cwltest.yml", "--cwl-badgedir", str(badge_path)
9393
)
94+
result.assert_outcomes(passed=2)
95+
assert badge_path.exists()
96+
assert (badge_path / "command_line_tool.json").exists()
97+
assert (badge_path / "command_line_tool.md").exists()
98+
assert (badge_path / "required.json").exists()
99+
assert (badge_path / "required.md").exists()
100+
101+
102+
def test_badgedir_xdist(pytester: pytest.Pytester) -> None:
103+
"""Test the pytest plugin creates the badges directory even with xdist."""
104+
path = pytester.copy_example("conformance_test_v1.0.cwltest.yml")
105+
shutil.copy(
106+
get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py"
107+
)
108+
_load_v1_0_dir(path)
109+
badge_path = path.parent / "cwl-badges"
110+
assert not badge_path.exists()
111+
result = pytester.runpytest_inprocess(
112+
"-n",
113+
"2",
114+
"-k",
115+
"conformance_test_v1.0.cwltest.yml",
116+
"--cwl-badgedir",
117+
str(badge_path),
118+
)
119+
result.assert_outcomes(passed=2)
94120
assert badge_path.exists()
95121
assert (badge_path / "command_line_tool.json").exists()
96122
assert (badge_path / "command_line_tool.md").exists()

0 commit comments

Comments
 (0)