diff-cover 10.2.1__tar.gz → 10.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diff_cover-10.2.1 → diff_cover-10.3.0}/PKG-INFO +78 -1
- {diff_cover-10.2.1 → diff_cover-10.3.0}/README.rst +77 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/diff_cover_tool.py +19 -1
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/report_generator.py +10 -1
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/snippets.py +110 -14
- {diff_cover-10.2.1 → diff_cover-10.3.0}/pyproject.toml +1 -1
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_diff_cover_tool.py +10 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_report_generator.py +33 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_snippets.py +128 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/LICENSE +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/NOTICE +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/__init__.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/command_runner.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/config_parser.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/diff_quality_tool.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/diff_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/git_diff.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/git_path.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/hook.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/hookspecs.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/console_coverage_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/console_quality_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/external_style.css +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/github_coverage_annotations.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/html_coverage_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/html_quality_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/markdown_coverage_report.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/markdown_quality_report.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/snippet_content.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/snippet_content.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/snippet_content.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/templates/snippet_style.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/util.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/violationsreporters/__init__.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/violationsreporters/base.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/violationsreporters/java_violations_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/diff_cover/violationsreporters/violations_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/__init__.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/conftest.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/add_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/add_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/add_json_report.json +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/add_json_report_float.json +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/add_markdown_report.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/changed_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/changed_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/coverage.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/coverage1.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/coverage2.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/coverage_missing_lines.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/cpp_functions_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/cpp_functions_coverage.lcov +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/delete_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/delete_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/dotnet_coverage.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/empty.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/empty_pycodestyle_violations.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/expand_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/external_css_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/external_style.css +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_add.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_changed.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_code_dupe.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_cpp.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_cpp_functions.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_delete.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_dotnet.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_external_css.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_lua.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_moved.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_mult.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_python.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_subdir.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_typescript.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_typescript_branches.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_unicode.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_violations.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/git_diff_violations_two_files.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/hello.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/hi.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/html_report_empty.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/html_report_one_snippet.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/html_report_two_snippets.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/lcov.info +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/lua_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/luacoverage.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/markdown_report_one_snippet.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/markdown_report_two_snippets.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/moved_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/moved_coverage.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/moved_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/mult_inputs_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/mult_inputs_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report.json +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report_external_css.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pycodestyle_violations_report_float.json +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pyflakes_two_files.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pyflakes_violations_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pyflakes_violations_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_dupe.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_dupe_violations_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_violations_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_violations_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylint_violations_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/pylintrc +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_cpp_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_cpp_coverage.lcov +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_python_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_python_coverage.lcov +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_typescript_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/real_typescript_coverage.lcov +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/show_uncovered_lines_console.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet.css +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_8859.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_arabic_output.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_default.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_invalid_violations.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_list.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_list.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_list2.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_list3.md +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_no_filename_ext.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_src.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_src2.cpp +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_src3.cpp +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_unicode.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_unicode.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/snippet_unicode_html_output.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/subdir_coverage_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/subdir_coverage_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/test_src.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/typescript_branches_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/typescript_branches_coverage.lcov +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/unicode_console_report.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/unicode_coverage.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/unicode_html_report.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/unicode_test_src.txt +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/fixtures/violations_test_file.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/helpers.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/snippet_list_unicode.html +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_clover_violations_reporter/test.xml +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_clover_violations_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_config_parser.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_diff_cover_main.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_diff_quality_main.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_diff_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_git_diff.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_git_diff_file.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_git_path.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_integration.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_java_violations_reporter.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_util.py +0 -0
- {diff_cover-10.2.1 → diff_cover-10.3.0}/tests/test_violations_reporter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: diff_cover
|
|
3
|
-
Version: 10.
|
|
3
|
+
Version: 10.3.0
|
|
4
4
|
Summary: Run coverage and linting reports on diffs
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: See Contributors
|
|
@@ -320,6 +320,83 @@ It can be enabled by using the ``-q``/``--quiet`` flag:
|
|
|
320
320
|
|
|
321
321
|
If enabled, the tool will only print errors and failures but no information or warning messages.
|
|
322
322
|
|
|
323
|
+
Showing Covered and Uncovered Lines
|
|
324
|
+
-----------------------------------
|
|
325
|
+
By default the console report only lists the percentage of covered lines.
|
|
326
|
+
|
|
327
|
+
``diff-cover`` can also show the individual lines that lack coverage on the
|
|
328
|
+
console with ``--show-uncovered``:
|
|
329
|
+
|
|
330
|
+
.. code:: bash
|
|
331
|
+
|
|
332
|
+
diff-cover coverage.xml --show-uncovered
|
|
333
|
+
|
|
334
|
+
When generating an HTML report, ``--show-covered`` additionally highlights the
|
|
335
|
+
covered diff lines (in green), alongside the existing missing-line (red)
|
|
336
|
+
highlighting:
|
|
337
|
+
|
|
338
|
+
.. code:: bash
|
|
339
|
+
|
|
340
|
+
diff-cover coverage.xml --html-report report.html --show-covered
|
|
341
|
+
|
|
342
|
+
Source Roots
|
|
343
|
+
------------
|
|
344
|
+
For ``jacoco`` coverage reports, ``diff-cover`` needs to know the source
|
|
345
|
+
directories in order to map coverage data back to source files. Provide one or
|
|
346
|
+
more directories with ``--src-roots`` (defaults to ``src/main/java`` and
|
|
347
|
+
``src/test/java``):
|
|
348
|
+
|
|
349
|
+
.. code:: bash
|
|
350
|
+
|
|
351
|
+
diff-cover coverage.xml --src-roots src/main/java src/test/java
|
|
352
|
+
|
|
353
|
+
Report Root Path
|
|
354
|
+
----------------
|
|
355
|
+
``diff-quality`` resolves violation report paths relative to the current working
|
|
356
|
+
directory. If your quality tool was run from a different directory, use
|
|
357
|
+
``--report-root-path`` to specify the root path that should be used when
|
|
358
|
+
generating the report:
|
|
359
|
+
|
|
360
|
+
.. code:: bash
|
|
361
|
+
|
|
362
|
+
diff-quality --violations=pycodestyle --report-root-path=path/to/root
|
|
363
|
+
|
|
364
|
+
External CSS File
|
|
365
|
+
-----------------
|
|
366
|
+
By default an HTML report embeds its styles inline. To write the CSS into a
|
|
367
|
+
separate file instead, use ``--external-css-file``:
|
|
368
|
+
|
|
369
|
+
.. code:: bash
|
|
370
|
+
|
|
371
|
+
diff-cover coverage.xml --html-report report.html --external-css-file report.css
|
|
372
|
+
diff-quality --violations=pycodestyle --html-report report.html --external-css-file report.css
|
|
373
|
+
|
|
374
|
+
Diff Range Notation
|
|
375
|
+
-------------------
|
|
376
|
+
When comparing branches, ``diff-cover`` and ``diff-quality`` use the ``...``
|
|
377
|
+
git diff range notation by default (changes on the current branch since it
|
|
378
|
+
diverged from the compare branch). To use the ``..`` notation instead (all
|
|
379
|
+
differences between the two branches), pass ``--diff-range-notation``:
|
|
380
|
+
|
|
381
|
+
.. code:: bash
|
|
382
|
+
|
|
383
|
+
diff-cover coverage.xml --diff-range-notation=..
|
|
384
|
+
diff-quality --violations=pycodestyle --diff-range-notation=..
|
|
385
|
+
|
|
386
|
+
See the `git diff documentation`_ for details on the two notations.
|
|
387
|
+
|
|
388
|
+
.. _git diff documentation: https://git-scm.com/docs/git-diff
|
|
389
|
+
|
|
390
|
+
Ignore Whitespace
|
|
391
|
+
-----------------
|
|
392
|
+
To ignore any and all whitespace changes when computing the diff, use
|
|
393
|
+
``--ignore-whitespace``:
|
|
394
|
+
|
|
395
|
+
.. code:: bash
|
|
396
|
+
|
|
397
|
+
diff-cover coverage.xml --ignore-whitespace
|
|
398
|
+
diff-quality --violations=pycodestyle --ignore-whitespace
|
|
399
|
+
|
|
323
400
|
Compatibility with multi-line statements
|
|
324
401
|
----------------------------------------
|
|
325
402
|
``diff-cover`` relies on the comparison of diff reports and coverage reports, and does not report
|
|
@@ -288,6 +288,83 @@ It can be enabled by using the ``-q``/``--quiet`` flag:
|
|
|
288
288
|
|
|
289
289
|
If enabled, the tool will only print errors and failures but no information or warning messages.
|
|
290
290
|
|
|
291
|
+
Showing Covered and Uncovered Lines
|
|
292
|
+
-----------------------------------
|
|
293
|
+
By default the console report only lists the percentage of covered lines.
|
|
294
|
+
|
|
295
|
+
``diff-cover`` can also show the individual lines that lack coverage on the
|
|
296
|
+
console with ``--show-uncovered``:
|
|
297
|
+
|
|
298
|
+
.. code:: bash
|
|
299
|
+
|
|
300
|
+
diff-cover coverage.xml --show-uncovered
|
|
301
|
+
|
|
302
|
+
When generating an HTML report, ``--show-covered`` additionally highlights the
|
|
303
|
+
covered diff lines (in green), alongside the existing missing-line (red)
|
|
304
|
+
highlighting:
|
|
305
|
+
|
|
306
|
+
.. code:: bash
|
|
307
|
+
|
|
308
|
+
diff-cover coverage.xml --html-report report.html --show-covered
|
|
309
|
+
|
|
310
|
+
Source Roots
|
|
311
|
+
------------
|
|
312
|
+
For ``jacoco`` coverage reports, ``diff-cover`` needs to know the source
|
|
313
|
+
directories in order to map coverage data back to source files. Provide one or
|
|
314
|
+
more directories with ``--src-roots`` (defaults to ``src/main/java`` and
|
|
315
|
+
``src/test/java``):
|
|
316
|
+
|
|
317
|
+
.. code:: bash
|
|
318
|
+
|
|
319
|
+
diff-cover coverage.xml --src-roots src/main/java src/test/java
|
|
320
|
+
|
|
321
|
+
Report Root Path
|
|
322
|
+
----------------
|
|
323
|
+
``diff-quality`` resolves violation report paths relative to the current working
|
|
324
|
+
directory. If your quality tool was run from a different directory, use
|
|
325
|
+
``--report-root-path`` to specify the root path that should be used when
|
|
326
|
+
generating the report:
|
|
327
|
+
|
|
328
|
+
.. code:: bash
|
|
329
|
+
|
|
330
|
+
diff-quality --violations=pycodestyle --report-root-path=path/to/root
|
|
331
|
+
|
|
332
|
+
External CSS File
|
|
333
|
+
-----------------
|
|
334
|
+
By default an HTML report embeds its styles inline. To write the CSS into a
|
|
335
|
+
separate file instead, use ``--external-css-file``:
|
|
336
|
+
|
|
337
|
+
.. code:: bash
|
|
338
|
+
|
|
339
|
+
diff-cover coverage.xml --html-report report.html --external-css-file report.css
|
|
340
|
+
diff-quality --violations=pycodestyle --html-report report.html --external-css-file report.css
|
|
341
|
+
|
|
342
|
+
Diff Range Notation
|
|
343
|
+
-------------------
|
|
344
|
+
When comparing branches, ``diff-cover`` and ``diff-quality`` use the ``...``
|
|
345
|
+
git diff range notation by default (changes on the current branch since it
|
|
346
|
+
diverged from the compare branch). To use the ``..`` notation instead (all
|
|
347
|
+
differences between the two branches), pass ``--diff-range-notation``:
|
|
348
|
+
|
|
349
|
+
.. code:: bash
|
|
350
|
+
|
|
351
|
+
diff-cover coverage.xml --diff-range-notation=..
|
|
352
|
+
diff-quality --violations=pycodestyle --diff-range-notation=..
|
|
353
|
+
|
|
354
|
+
See the `git diff documentation`_ for details on the two notations.
|
|
355
|
+
|
|
356
|
+
.. _git diff documentation: https://git-scm.com/docs/git-diff
|
|
357
|
+
|
|
358
|
+
Ignore Whitespace
|
|
359
|
+
-----------------
|
|
360
|
+
To ignore any and all whitespace changes when computing the diff, use
|
|
361
|
+
``--ignore-whitespace``:
|
|
362
|
+
|
|
363
|
+
.. code:: bash
|
|
364
|
+
|
|
365
|
+
diff-cover coverage.xml --ignore-whitespace
|
|
366
|
+
diff-quality --violations=pycodestyle --ignore-whitespace
|
|
367
|
+
|
|
291
368
|
Compatibility with multi-line statements
|
|
292
369
|
----------------------------------------
|
|
293
370
|
``diff-cover`` relies on the comparison of diff reports and coverage reports, and does not report
|
|
@@ -45,6 +45,10 @@ DIFF_RANGE_NOTATION_HELP = (
|
|
|
45
45
|
)
|
|
46
46
|
QUIET_HELP = "Only print errors and failures"
|
|
47
47
|
SHOW_UNCOVERED = "Show uncovered lines on the console"
|
|
48
|
+
SHOW_COVERED_HELP = (
|
|
49
|
+
"Also highlight covered diff lines (in green) in the HTML coverage report, "
|
|
50
|
+
"in addition to the existing missing-line (red) highlighting."
|
|
51
|
+
)
|
|
48
52
|
EXPAND_COVERAGE_REPORT = (
|
|
49
53
|
"Append missing lines in coverage reports based on the hits of the previous line."
|
|
50
54
|
)
|
|
@@ -99,6 +103,13 @@ def parse_coverage_args(argv):
|
|
|
99
103
|
"--show-uncovered", action="store_true", default=None, help=SHOW_UNCOVERED
|
|
100
104
|
)
|
|
101
105
|
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
"--show-covered",
|
|
108
|
+
action="store_true",
|
|
109
|
+
default=None,
|
|
110
|
+
help=SHOW_COVERED_HELP,
|
|
111
|
+
)
|
|
112
|
+
|
|
102
113
|
parser.add_argument(
|
|
103
114
|
"--expand-coverage-report",
|
|
104
115
|
action="store_true",
|
|
@@ -193,6 +204,7 @@ def parse_coverage_args(argv):
|
|
|
193
204
|
|
|
194
205
|
defaults = {
|
|
195
206
|
"show_uncovered": False,
|
|
207
|
+
"show_covered": False,
|
|
196
208
|
"compare_branch": "origin/main",
|
|
197
209
|
"fail_under": 0,
|
|
198
210
|
"ignore_staged": False,
|
|
@@ -223,6 +235,7 @@ def generate_coverage_report(
|
|
|
223
235
|
src_roots=None,
|
|
224
236
|
quiet=False,
|
|
225
237
|
show_uncovered=False,
|
|
238
|
+
show_covered=False,
|
|
226
239
|
expand_coverage_report=False,
|
|
227
240
|
total_percent_float=False,
|
|
228
241
|
):
|
|
@@ -263,7 +276,11 @@ def generate_coverage_report(
|
|
|
263
276
|
if css_url is not None:
|
|
264
277
|
css_url = os.path.relpath(css_file, os.path.dirname(html_report))
|
|
265
278
|
reporter = HtmlReportGenerator(
|
|
266
|
-
coverage,
|
|
279
|
+
coverage,
|
|
280
|
+
diff,
|
|
281
|
+
css_url=css_url,
|
|
282
|
+
total_percent_float=total_percent_float,
|
|
283
|
+
show_covered=show_covered,
|
|
267
284
|
)
|
|
268
285
|
with open_file(html_report, "wb") as output_file:
|
|
269
286
|
reporter.generate_report(output_file)
|
|
@@ -398,6 +415,7 @@ def main(argv=None, directory=None):
|
|
|
398
415
|
src_roots=arg_dict["src_roots"],
|
|
399
416
|
quiet=quiet,
|
|
400
417
|
show_uncovered=arg_dict["show_uncovered"],
|
|
418
|
+
show_covered=arg_dict["show_covered"],
|
|
401
419
|
expand_coverage_report=arg_dict["expand_coverage_report"],
|
|
402
420
|
total_percent_float=arg_dict["total_percent_float"],
|
|
403
421
|
)
|
|
@@ -295,6 +295,7 @@ class TemplateReportGenerator(BaseReportGenerator):
|
|
|
295
295
|
diff_reporter,
|
|
296
296
|
css_url=None,
|
|
297
297
|
total_percent_float=False,
|
|
298
|
+
show_covered=False,
|
|
298
299
|
):
|
|
299
300
|
super().__init__(
|
|
300
301
|
violations_reporter,
|
|
@@ -302,6 +303,11 @@ class TemplateReportGenerator(BaseReportGenerator):
|
|
|
302
303
|
total_percent_float=total_percent_float,
|
|
303
304
|
)
|
|
304
305
|
self.css_url = css_url
|
|
306
|
+
# When True, the rendered HTML snippet for each source file will
|
|
307
|
+
# additionally highlight covered diff lines (in green) on top of
|
|
308
|
+
# the existing violation (red) highlighting. Defaults to False to
|
|
309
|
+
# preserve historical behaviour.
|
|
310
|
+
self.show_covered = show_covered
|
|
305
311
|
|
|
306
312
|
def generate_report(self, output_file):
|
|
307
313
|
"""
|
|
@@ -406,9 +412,12 @@ class TemplateReportGenerator(BaseReportGenerator):
|
|
|
406
412
|
# If we cannot load the file, then fail gracefully
|
|
407
413
|
formatted_snippets = {"html": [], "markdown": [], "terminal": []}
|
|
408
414
|
if self.include_snippets:
|
|
415
|
+
covered_lines = stats["covered_lines"] if self.show_covered else None
|
|
409
416
|
with contextlib.suppress(OSError):
|
|
410
417
|
formatted_snippets = Snippet.load_formatted_snippets(
|
|
411
|
-
src_path,
|
|
418
|
+
src_path,
|
|
419
|
+
stats["violation_lines"],
|
|
420
|
+
covered_lines=covered_lines,
|
|
412
421
|
)
|
|
413
422
|
|
|
414
423
|
stats.update(
|
|
@@ -4,6 +4,7 @@ in HTML reports.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import contextlib
|
|
7
|
+
import re
|
|
7
8
|
from tokenize import open as openpy
|
|
8
9
|
|
|
9
10
|
import chardet
|
|
@@ -23,7 +24,10 @@ class Snippet:
|
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
26
|
VIOLATION_COLOR = "#ffcccc"
|
|
27
|
+
COVERED_COLOR = "#ddffdd"
|
|
26
28
|
DIV_CSS_CLASS = "snippet"
|
|
29
|
+
COVERED_LINE_CSS_CLASS = "diff-cover-covered-line"
|
|
30
|
+
LINESPANS_PREFIX = "diff-cover-src-line"
|
|
27
31
|
|
|
28
32
|
# Number of extra lines to include before and after
|
|
29
33
|
# each snippet to provide context.
|
|
@@ -50,6 +54,7 @@ class Snippet:
|
|
|
50
54
|
last_line,
|
|
51
55
|
violation_lines,
|
|
52
56
|
lexer_name,
|
|
57
|
+
covered_lines=None,
|
|
53
58
|
):
|
|
54
59
|
"""
|
|
55
60
|
Create a source code snippet.
|
|
@@ -75,6 +80,10 @@ class Snippet:
|
|
|
75
80
|
programming language for this snippet.
|
|
76
81
|
See https://pygments.org/docs/lexers/
|
|
77
82
|
|
|
83
|
+
`covered_lines` is an optional list of line numbers
|
|
84
|
+
to highlight as covered. When omitted (the default),
|
|
85
|
+
no covered-line highlighting is rendered.
|
|
86
|
+
|
|
78
87
|
Raises a `ValueError` if `start_line` is less than 1
|
|
79
88
|
"""
|
|
80
89
|
if start_line < 1:
|
|
@@ -86,6 +95,7 @@ class Snippet:
|
|
|
86
95
|
self._last_line = last_line
|
|
87
96
|
self._violation_lines = violation_lines
|
|
88
97
|
self._lexer_name = lexer_name
|
|
98
|
+
self._covered_lines = covered_lines or []
|
|
89
99
|
|
|
90
100
|
@classmethod
|
|
91
101
|
def style_defs(cls):
|
|
@@ -95,21 +105,74 @@ class Snippet:
|
|
|
95
105
|
"""
|
|
96
106
|
formatter = HtmlFormatter()
|
|
97
107
|
formatter.style.highlight_color = cls.VIOLATION_COLOR
|
|
98
|
-
|
|
108
|
+
base_styles = formatter.get_style_defs()
|
|
109
|
+
# Append a rule for covered-line highlighting.
|
|
110
|
+
covered_style = (
|
|
111
|
+
f".{cls.COVERED_LINE_CSS_CLASS} "
|
|
112
|
+
f"{{ background-color: {cls.COVERED_COLOR}; }}"
|
|
113
|
+
)
|
|
114
|
+
return f"{base_styles}\n{covered_style}"
|
|
99
115
|
|
|
100
116
|
def html(self):
|
|
101
117
|
"""
|
|
102
118
|
Return an HTML representation of the snippet.
|
|
119
|
+
|
|
120
|
+
Violation lines are highlighted via Pygments' built-in
|
|
121
|
+
`hl_lines` mechanism. When the snippet was constructed with
|
|
122
|
+
`covered_lines`, those lines are additionally marked by adding
|
|
123
|
+
the covered-line CSS class to their per-line span, produced via
|
|
124
|
+
the `linespans` formatter option.
|
|
103
125
|
"""
|
|
104
|
-
|
|
126
|
+
formatter_kwargs = dict(
|
|
105
127
|
cssclass=self.DIV_CSS_CLASS,
|
|
106
128
|
linenos=True,
|
|
107
129
|
linenostart=self._start_line,
|
|
108
130
|
hl_lines=self._shift_lines(self._violation_lines, self._start_line),
|
|
109
131
|
lineanchors=self._src_filename,
|
|
110
132
|
)
|
|
133
|
+
# Only enable per-line `<span id="...">` wrapping when we actually
|
|
134
|
+
# need it for covered-line highlighting. This keeps the rendered
|
|
135
|
+
# HTML byte-for-byte identical to the historical output when no
|
|
136
|
+
# covered lines are supplied.
|
|
137
|
+
if self._covered_lines:
|
|
138
|
+
formatter_kwargs["linespans"] = self.LINESPANS_PREFIX
|
|
111
139
|
|
|
112
|
-
|
|
140
|
+
rendered = pygments.format(self.src_tokens(), HtmlFormatter(**formatter_kwargs))
|
|
141
|
+
|
|
142
|
+
if self._covered_lines:
|
|
143
|
+
# NOTE: do NOT shift these line numbers. Unlike `hl_lines`
|
|
144
|
+
# (which is snippet-relative, 1-based), Pygments' `linespans`
|
|
145
|
+
# IDs are emitted using the same numbering as `linenostart`,
|
|
146
|
+
# i.e. the absolute file line number. So we match the raw
|
|
147
|
+
# values from `_covered_lines` directly.
|
|
148
|
+
rendered = self._mark_covered_lines(rendered, self._covered_lines)
|
|
149
|
+
|
|
150
|
+
return rendered
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def _mark_covered_lines(cls, html, covered_file_lines):
|
|
154
|
+
"""
|
|
155
|
+
Add the covered-line CSS class to per-line spans whose line
|
|
156
|
+
number is in `covered_file_lines`.
|
|
157
|
+
|
|
158
|
+
`covered_file_lines` are absolute (file-relative) line numbers,
|
|
159
|
+
matching the IDs that Pygments emits via `linespans` when
|
|
160
|
+
`linenostart` is set to the snippet's starting line number.
|
|
161
|
+
"""
|
|
162
|
+
wanted = set(covered_file_lines)
|
|
163
|
+
if not wanted:
|
|
164
|
+
return html
|
|
165
|
+
|
|
166
|
+
prefix = cls.LINESPANS_PREFIX
|
|
167
|
+
css_class = cls.COVERED_LINE_CSS_CLASS
|
|
168
|
+
|
|
169
|
+
def _replace(match):
|
|
170
|
+
line_num = int(match.group(1))
|
|
171
|
+
if line_num in wanted:
|
|
172
|
+
return f'<span id="{prefix}-{line_num}" class="{css_class}">'
|
|
173
|
+
return match.group(0)
|
|
174
|
+
|
|
175
|
+
return re.sub(rf'<span id="{re.escape(prefix)}-(\d+)">', _replace, html)
|
|
113
176
|
|
|
114
177
|
def markdown(self):
|
|
115
178
|
"""
|
|
@@ -174,24 +237,38 @@ class Snippet:
|
|
|
174
237
|
return "".join([val for _, val in self._src_tokens])
|
|
175
238
|
|
|
176
239
|
@classmethod
|
|
177
|
-
def load_formatted_snippets(cls, src_path, violation_lines):
|
|
240
|
+
def load_formatted_snippets(cls, src_path, violation_lines, covered_lines=None):
|
|
178
241
|
"""
|
|
179
242
|
Load snippets from the file at `src_path` and format
|
|
180
243
|
them as HTML and as plain text.
|
|
181
244
|
Returns a dictionary containing the two types of formatting
|
|
182
245
|
results for code snippets.
|
|
183
246
|
|
|
247
|
+
If `covered_lines` is provided (non-empty), the HTML output will
|
|
248
|
+
additionally render snippets around those lines and highlight
|
|
249
|
+
them as covered. Markdown and terminal output is unchanged
|
|
250
|
+
regardless of `covered_lines`, to keep those formats stable.
|
|
251
|
+
|
|
184
252
|
See `load_snippets()` for details.
|
|
185
253
|
"""
|
|
186
254
|
|
|
187
|
-
#
|
|
188
|
-
|
|
255
|
+
# Snippets used for markdown/terminal output keep the historical
|
|
256
|
+
# behaviour: ranges only around violation lines, no covered-line
|
|
257
|
+
# information attached.
|
|
258
|
+
violation_only_snippets = cls.load_snippets(src_path, violation_lines)
|
|
259
|
+
|
|
260
|
+
if covered_lines:
|
|
261
|
+
# HTML rendering also visualises covered diff lines, so widen
|
|
262
|
+
# the snippet ranges to include them and pass the covered list
|
|
263
|
+
# through to the snippet for per-line highlighting.
|
|
264
|
+
html_snippets = cls.load_snippets(src_path, violation_lines, covered_lines)
|
|
265
|
+
else:
|
|
266
|
+
html_snippets = violation_only_snippets
|
|
189
267
|
|
|
190
|
-
# ...render twice in different formats
|
|
191
268
|
return {
|
|
192
|
-
"html": [snippet.html() for snippet in
|
|
193
|
-
"markdown": [snippet.markdown() for snippet in
|
|
194
|
-
"terminal": [snippet.terminal() for snippet in
|
|
269
|
+
"html": [snippet.html() for snippet in html_snippets],
|
|
270
|
+
"markdown": [snippet.markdown() for snippet in violation_only_snippets],
|
|
271
|
+
"terminal": [snippet.terminal() for snippet in violation_only_snippets],
|
|
195
272
|
}
|
|
196
273
|
|
|
197
274
|
@classmethod
|
|
@@ -223,12 +300,17 @@ class Snippet:
|
|
|
223
300
|
return contents
|
|
224
301
|
|
|
225
302
|
@classmethod
|
|
226
|
-
def load_snippets(cls, src_path, violation_lines):
|
|
303
|
+
def load_snippets(cls, src_path, violation_lines, covered_lines=None):
|
|
227
304
|
"""
|
|
228
305
|
Load snippets from the file at `src_path` to show
|
|
229
306
|
violations on lines in the list `violation_lines`
|
|
230
307
|
(list of line numbers, starting at index 0).
|
|
231
308
|
|
|
309
|
+
If `covered_lines` is provided, those lines are also treated as
|
|
310
|
+
"interesting" when computing snippet ranges (so a fully-covered
|
|
311
|
+
file still yields snippets) and are stored on the resulting
|
|
312
|
+
`Snippet` instances for use during rendering.
|
|
313
|
+
|
|
232
314
|
The file at `src_path` should be a text file (not binary).
|
|
233
315
|
|
|
234
316
|
Returns a list of `Snippet` instances.
|
|
@@ -237,9 +319,15 @@ class Snippet:
|
|
|
237
319
|
"""
|
|
238
320
|
contents = cls.load_contents(src_path)
|
|
239
321
|
|
|
240
|
-
# Construct a list of snippet ranges
|
|
322
|
+
# Construct a list of snippet ranges. When `covered_lines` is
|
|
323
|
+
# provided, expand the set of "interesting" lines so we also
|
|
324
|
+
# render context around covered diff lines, not just violations.
|
|
241
325
|
src_lines = contents.split("\n")
|
|
242
|
-
|
|
326
|
+
if covered_lines:
|
|
327
|
+
interesting_lines = sorted(set(violation_lines) | set(covered_lines))
|
|
328
|
+
else:
|
|
329
|
+
interesting_lines = violation_lines
|
|
330
|
+
snippet_ranges = cls._snippet_ranges(len(src_lines), interesting_lines)
|
|
243
331
|
|
|
244
332
|
# Parse the source into tokens
|
|
245
333
|
token_stream, lexer = cls._parse_src(contents, src_path)
|
|
@@ -248,7 +336,15 @@ class Snippet:
|
|
|
248
336
|
token_groups = cls._group_tokens(token_stream, snippet_ranges)
|
|
249
337
|
|
|
250
338
|
return [
|
|
251
|
-
Snippet(
|
|
339
|
+
Snippet(
|
|
340
|
+
tokens,
|
|
341
|
+
src_path,
|
|
342
|
+
start,
|
|
343
|
+
end,
|
|
344
|
+
violation_lines,
|
|
345
|
+
lexer.name,
|
|
346
|
+
covered_lines=covered_lines,
|
|
347
|
+
)
|
|
252
348
|
for (start, end), tokens in sorted(token_groups.items())
|
|
253
349
|
]
|
|
254
350
|
|
|
@@ -37,6 +37,16 @@ def test_parse_with_no_report():
|
|
|
37
37
|
assert not arg_dict["ignore_unstaged"]
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
def test_show_covered_defaults_false():
|
|
41
|
+
arg_dict = parse_coverage_args(["reports/coverage.xml"])
|
|
42
|
+
assert arg_dict["show_covered"] is False
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_show_covered_flag():
|
|
46
|
+
arg_dict = parse_coverage_args(["reports/coverage.xml", "--show-covered"])
|
|
47
|
+
assert arg_dict["show_covered"] is True
|
|
48
|
+
|
|
49
|
+
|
|
40
50
|
def test_parse_with_multiple_reports():
|
|
41
51
|
argv = [
|
|
42
52
|
"reports/coverage.xml",
|
|
@@ -498,6 +498,39 @@ class TestHtmlReportGenerator(BaseReportGeneratorTest):
|
|
|
498
498
|
expected = load_fixture("html_report.html")
|
|
499
499
|
self.assert_report(expected)
|
|
500
500
|
|
|
501
|
+
@pytest.mark.usefixtures("use_default_values")
|
|
502
|
+
def test_show_covered_passes_covered_lines_to_snippets(self, coverage, diff):
|
|
503
|
+
"""
|
|
504
|
+
When `show_covered=True`, the html reporter should pass each
|
|
505
|
+
source file's covered lines into `Snippet.load_formatted_snippets`
|
|
506
|
+
so the snippet renderer can highlight them.
|
|
507
|
+
"""
|
|
508
|
+
report = HtmlReportGenerator(coverage, diff, show_covered=True)
|
|
509
|
+
report.generate_report(BytesIO())
|
|
510
|
+
|
|
511
|
+
calls = self._load_formatted_snippets.call_args_list
|
|
512
|
+
assert calls, "Expected snippet loading to be invoked"
|
|
513
|
+
for call in calls:
|
|
514
|
+
assert call.kwargs.get(
|
|
515
|
+
"covered_lines"
|
|
516
|
+
), "Expected covered_lines to be forwarded when show_covered=True"
|
|
517
|
+
|
|
518
|
+
@pytest.mark.usefixtures("use_default_values")
|
|
519
|
+
def test_show_covered_default_false_does_not_pass_covered_lines(
|
|
520
|
+
self, coverage, diff
|
|
521
|
+
):
|
|
522
|
+
"""
|
|
523
|
+
With the default `show_covered=False`, no covered_lines should be
|
|
524
|
+
passed to the snippet loader, preserving the historical behaviour.
|
|
525
|
+
"""
|
|
526
|
+
report = HtmlReportGenerator(coverage, diff)
|
|
527
|
+
report.generate_report(BytesIO())
|
|
528
|
+
|
|
529
|
+
calls = self._load_formatted_snippets.call_args_list
|
|
530
|
+
assert calls, "Expected snippet loading to be invoked"
|
|
531
|
+
for call in calls:
|
|
532
|
+
assert call.kwargs.get("covered_lines") is None
|
|
533
|
+
|
|
501
534
|
def test_empty_report(self):
|
|
502
535
|
# Have the dependencies return an empty report
|
|
503
536
|
# (this is the default)
|