Skip to content

Commit

Permalink
- added --merge argument, to facilitate merging coverage results;
Browse files Browse the repository at this point in the history
  • Loading branch information
jaltmayerpizzorno committed Apr 4, 2024
1 parent 8f42095 commit 25fa1e3
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
34 changes: 34 additions & 0 deletions src/slipcover/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,33 @@ def wrapper(*pargs, **kwargs):
return wrapper


def merge_files(args):
"""Merges coverage files."""
try:
with args.merge[0].open() as jf:
merged = json.load(jf)
except Exception as e:
print(f"Error reading in {args.merge[0]}: {e}")
return 1

try:
for f in args.merge[1:]:
with f.open() as jf:
sc.merge_coverage(merged, json.load(jf))
except Exception as e:
print(f"Error merging in {f}: {e}")
return 1

try:
with args.out.open("w", encoding='utf-8') as jf:
json.dump(merged, jf)
except Exception as e:
print(e)
return 1

return 0


def main():
import argparse

Expand Down Expand Up @@ -116,6 +143,7 @@ def main():

g = ap.add_mutually_exclusive_group(required=True)
g.add_argument('-m', dest='module', nargs=1, help="run given module as __main__")
g.add_argument('--merge', nargs='+', type=Path, help="merge JSON coverage files, saving to --out")
g.add_argument('script', nargs='?', type=Path, help="the script to run")
ap.add_argument('script_or_module_args', nargs=argparse.REMAINDER)

Expand All @@ -126,6 +154,12 @@ def main():
else:
args = ap.parse_args(sys.argv[1:])


if args.merge:
if not args.out: ap.error("--out is required with --merge")
return merge_files(args)


base_path = Path(args.script).resolve().parent if args.script \
else Path('.').resolve()

Expand Down
47 changes: 41 additions & 6 deletions tests/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,8 @@ def test_merge_coverage(tmp_path, monkeypatch, do_branch):
check_summaries(a)


@pytest.mark.parametrize("branch_in", ['a', 'b'])
def test_merge_coverage_branch_coverage_disagree(tmp_path, monkeypatch, branch_in):
@pytest.fixture
def cov_merge_fixture(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)

(tmp_path / "t.py").write_text("""\
Expand All @@ -802,16 +802,22 @@ def test_merge_coverage_branch_coverage_disagree(tmp_path, monkeypatch, branch_i
print("all done!") # 11
""")

yield tmp_path



@pytest.mark.parametrize("branch_in", ['a', 'b'])
def test_merge_coverage_branch_coverage_disagree(cov_merge_fixture, branch_in):
subprocess.run([sys.executable, '-m', 'slipcover'] +\
(['--branch'] if branch_in == 'a' else []) +\
['--json', '--out', tmp_path / "a.json", "t.py"], check=True)
['--json', '--out', "a.json", "t.py"], check=True)
subprocess.run([sys.executable, '-m', 'slipcover'] +\
(['--branch'] if branch_in == 'b' else []) +\
['--json', '--out', tmp_path / "b.json", "t.py", "X"], check=True)
['--json', '--out', "b.json", "t.py", "X"], check=True)

with (tmp_path / "a.json").open() as f:
with Path("a.json").open() as f:
a = json.load(f)
with (tmp_path / "b.json").open() as f:
with Path("b.json").open() as f:
b = json.load(f)

assert [1, 3, 4, 8, 11] == a['files']['t.py']['executed_lines']
Expand Down Expand Up @@ -852,3 +858,32 @@ def test_pytest_forked(tmp_path):
cov = cov['files'][test_file]
assert [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14] == cov['executed_lines']
assert [] == cov['missing_lines']


def test_merge_flag(cov_merge_fixture):
subprocess.run([sys.executable, '-m', 'slipcover', '--branch',
'--json', '--out', "a.json", "t.py"], check=True)
subprocess.run([sys.executable, '-m', 'slipcover', '--branch',
'--json', '--out', "b.json", "t.py", "X"], check=True)

subprocess.run([sys.executable, '-m', 'slipcover', '--merge',
'a.json', 'b.json', '--out', 'c.json'], check=True)

with Path("c.json").open() as f:
c = json.load(f)

assert [1, 3, 4, 6, 8, 11] == c['files']['t.py']['executed_lines']
assert [9] == c['files']['t.py']['missing_lines']
assert True == c['meta']['branch_coverage']

check_summaries(c)


def test_merge_flag_no_out(cov_merge_fixture):
subprocess.run([sys.executable, '-m', 'slipcover', '--branch',
'--json', '--out', "a.json", "t.py"], check=True)
subprocess.run([sys.executable, '-m', 'slipcover', '--branch',
'--json', '--out', "b.json", "t.py", "X"], check=True)

with pytest.raises(subprocess.CalledProcessError):
subprocess.run([sys.executable, '-m', 'slipcover', '--merge', 'a.json', 'b.json'], check=True)

0 comments on commit 25fa1e3

Please sign in to comment.