Skip to content

Commit

Permalink
- fixed isolation module not handling pytest.Collector if returned
Browse files Browse the repository at this point in the history
  by Module.collect();
  • Loading branch information
jaltmayerpizzorno committed May 15, 2024
1 parent 1d5834e commit e438f95
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/slipcover/isolate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest
import sys


class IsolateItem(pytest.Item):
Expand All @@ -22,15 +21,23 @@ def run_forked(self):
def runforked():
module = pytest.Module.from_parent(parent=self.parent, path=self.path)
reports = list()
for it in module.collect():
reports.extend(ptf.forked_run_report(it))
return marshal.dumps([self.config.hook.pytest_report_to_serializable(report=r) for r in reports])

def collect_and_run(collector):
for it in collector.collect():
if isinstance(it, pytest.Collector):
collect_and_run(it)
else:
reports.extend(ptf.forked_run_report(it))

collect_and_run(module)

return marshal.dumps([self.config.hook.pytest_report_to_serializable(config=self.config, report=r) for r in reports])

ff = py.process.ForkedFunc(runforked)
result = ff.waitfinish()

if result.retval is not None:
reports = [self.config.hook.pytest_report_from_serializable(data=r) for r in marshal.loads(result.retval)]
reports = [self.config.hook.pytest_report_from_serializable(config=self.config, data=r) for r in marshal.loads(result.retval)]
else:
reports = [ptf.report_process_crash(self, result)]

Expand Down Expand Up @@ -64,4 +71,5 @@ def pytest_runtestloop(self, session):


if __name__ == "__main__":
import sys
sys.exit(pytest.main(sys.argv[1:], plugins=[IsolatePlugin()]))
26 changes: 26 additions & 0 deletions tests/test_isolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,29 @@ def test_foo():
# can't capture coverage if the process gets killed
if not (p == failing and fail_kind == 'kill'):
assert str(p) in cov['files']


def test_isolate_module_yields_collector(tmp_path, monkeypatch):
# A pytest.Collector.collect()'s return value may include not only pytest.Item,
# but also pytest.Collector.
#
# Here we test for this by including a class within the test module:
# when the module is being collected, pytest.Module.collect() will include
# a pytest.Class collector to actually collect items from within the class.

out = tmp_path / "out.json"

monkeypatch.chdir(tmp_path)
tests_dir = Path('tests')
tests_dir.mkdir()

test = seq2p(tests_dir, 1)
test.write_text("""\
class TestClass:
def test_foo(self):
assert True
""")

p = subprocess.run([sys.executable, '-m', 'slipcover', '--json', '--out', str(out),
'-m', 'slipcover.isolate', tests_dir], check=False)
assert p.returncode == pytest.ExitCode.OK

0 comments on commit e438f95

Please sign in to comment.