def test_inclusion_list(diff, git_diff): unstaged_input = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) _set_git_diff_output(diff, git_diff, "", "", unstaged_input) assert len(diff._get_included_diff_results()) == 3 assert ["", "", unstaged_input] == diff._get_included_diff_results()
def test_git_source_paths_with_supported_extensions(diff, git_diff): # Configure the git diff output _set_git_diff_output( diff, git_diff, git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}), git_diff_output({ "subdir/file2.py": line_numbers(3, 10), "file3.py": [0] }), git_diff_output({"README.md": line_numbers(3, 10)}), ) # Set supported extensions diff._supported_extensions = ["py"] # Get the source paths in the diff source_paths = diff.src_paths_changed() # Validate the source paths, README.md should be left out assert len(source_paths) == 3 assert source_paths[0] == "file3.py" assert source_paths[1] == "subdir/file1.py" assert source_paths[2] == "subdir/file2.py"
def test_ignore_unstaged_inclusion(git_diff): reporter = GitDiffReporter(git_diff=git_diff, ignore_unstaged=True) unstaged_input = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) _set_git_diff_output(reporter, git_diff, "", "", unstaged_input) assert reporter._get_included_diff_results() == ["", ""]
def test_git_repeat_lines(diff, git_diff): # Same committed, staged, and unstaged lines diff_output = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) _set_git_diff_output(diff, git_diff, diff_output, diff_output, diff_output) # Get the lines changed in the diff lines_changed = diff.lines_changed("subdir/file1.py") # Validate the lines changed assert lines_changed == line_numbers(3, 10) + line_numbers(34, 47)
def test_duplicate_source_paths(diff, git_diff): # Duplicate the output for committed, staged, and unstaged changes diff_output = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) _set_git_diff_output(diff, git_diff, diff_output, diff_output, diff_output) # Get the source paths in the diff source_paths = diff.src_paths_changed() # Should see only one copy of source files assert len(source_paths) == 1 assert source_paths[0] == "subdir/file1.py"
def test_ignore_lines_outside_src(diff, git_diff): # Add some lines at the start of the diff, before any # source files are specified diff_output = git_diff_output({"subdir/file1.py": line_numbers(3, 10)}) main_diff = "\n".join(["- deleted line", "+ added line", diff_output]) # Configure the git diff output _set_git_diff_output(diff, git_diff, main_diff, "", "") # Get the lines changed in the diff lines_changed = diff.lines_changed("subdir/file1.py") # Validate the lines changed assert lines_changed == line_numbers(3, 10)
def test_git_path_selection(mocker, diff, git_diff, include, exclude, expected): old_cwd = os.getcwd() with tempfile.TemporaryDirectory() as tmp_dir: # change the working directory into the temp directory so that globs are working os.chdir(tmp_dir) diff = GitDiffReporter(git_diff=git_diff, exclude=exclude, include=include) main_dir = Path(tmp_dir) (main_dir / "file3.py").touch() subdir1 = main_dir / "subdir1" subdir1.mkdir() (subdir1 / "file1.py").touch() subdir2 = main_dir / "subdir2" subdir2.mkdir() (subdir2 / "file2.py").touch() # Configure the git diff output _set_git_diff_output( diff, git_diff, git_diff_output({ "subdir1/file1.py": line_numbers(3, 10) + line_numbers(34, 47) }), git_diff_output({ "subdir2/file2.py": line_numbers(3, 10), "file3.py": [0] }), git_diff_output(dict(), deleted_files=["README.md"]), ) # Get the source paths in the diff mocker.patch.object(os.path, "abspath", lambda path: f"{tmp_dir}/{path}") source_paths = diff.src_paths_changed() # Validate the source paths # They should be in alphabetical order assert source_paths == expected # change back to the previous working directory os.chdir(old_cwd)
def test_include_untracked(mocker, git_diff): reporter = GitDiffReporter(git_diff=git_diff, include_untracked=True) diff_output = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) _set_git_diff_output(reporter, git_diff, staged_diff=diff_output, untracked=["u1.py", " u2.py"]) open_mock = mocker.mock_open(read_data="1\n2\n3\n") mocker.patch("diff_cover.diff_reporter.open", open_mock) changed = reporter.src_paths_changed() assert sorted(changed) == [" u2.py", "subdir/file1.py", "u1.py"] assert reporter.lines_changed("u1.py") == [1, 2, 3] assert reporter.lines_changed(" u2.py") == [1, 2, 3]
def test_inter_diff_conflict(diff, git_diff): # Commit changes to lines 3 through 10 added_diff = git_diff_output({"file.py": line_numbers(3, 10)}) # Delete the lines we modified deleted_lines = [] for line in added_diff.split("\n"): # Any added line becomes a deleted line if line.startswith("+"): deleted_lines.append(line.replace("+", "-")) # No need to include lines we already deleted elif line.startswith("-"): pass # Keep any other line else: deleted_lines.append(line) deleted_diff = "\n".join(deleted_lines) # Try all combinations of diff conflicts combinations = [ (added_diff, deleted_diff, ""), (added_diff, "", deleted_diff), ("", added_diff, deleted_diff), (added_diff, deleted_diff, deleted_diff), ] for (main_diff, staged_diff, unstaged_diff) in combinations: # Set up so we add lines, then delete them _set_git_diff_output(diff, git_diff, main_diff, staged_diff, unstaged_diff) assert diff.lines_changed("file.py") == []
def test_git_deleted_lines(diff, git_diff): # Configure the git diff output _set_git_diff_output( diff, git_diff, git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}), git_diff_output({ "subdir/file2.py": line_numbers(3, 10), "file3.py": [0] }), git_diff_output(dict(), deleted_files=["README.md"]), ) # Get the lines changed in the diff lines_changed = diff.lines_changed("README.md") # Validate no lines changed assert len(lines_changed) == 0
def test_git_source_paths(diff, git_diff): # Configure the git diff output _set_git_diff_output( diff, git_diff, git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}), git_diff_output({ "subdir/file2.py": line_numbers(3, 10), "file3.py": [0] }), git_diff_output(dict(), deleted_files=["README.md"]), ) # Get the source paths in the diff source_paths = diff.src_paths_changed() # Validate the source paths # They should be in alphabetical order assert len(source_paths) == 4 assert source_paths[0] == "file3.py" assert source_paths[1] == "README.md" assert source_paths[2] == "subdir/file1.py" assert source_paths[3] == "subdir/file2.py"
def test_git_line_within_hunk(diff, git_diff): main_diff = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) # Surround hunk in main (lines 3 to 10) surround = git_diff_output({"subdir/file1.py": line_numbers(2, 11)}) # Within hunk in main (lines 34 to 47) within = git_diff_output({"subdir/file1.py": line_numbers(35, 46)}) # Lines in staged / unstaged overlap with hunks in main _set_git_diff_output(diff, git_diff, main_diff, surround, within) # Get the lines changed in the diff lines_changed = diff.lines_changed("subdir/file1.py") # Validate the lines changed assert lines_changed == line_numbers(2, 11) + line_numbers(34, 47)
def test_git_overlapping_lines(diff, git_diff): main_diff = git_diff_output( {"subdir/file1.py": line_numbers(3, 10) + line_numbers(34, 47)}) # Overlap, extending the end of the hunk (lines 3 to 10) overlap_1 = git_diff_output({"subdir/file1.py": line_numbers(5, 14)}) # Overlap, extending the beginning of the hunk (lines 34 to 47) overlap_2 = git_diff_output({"subdir/file1.py": line_numbers(32, 37)}) # Lines in staged / unstaged overlap with lines in main _set_git_diff_output(diff, git_diff, main_diff, overlap_1, overlap_2) # Get the lines changed in the diff lines_changed = diff.lines_changed("subdir/file1.py") # Validate the lines changed assert lines_changed == line_numbers(3, 14) + line_numbers(32, 47)