Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Json report #825

Merged
merged 1 commit into from
Aug 31, 2019
Merged

Json report #825

merged 1 commit into from
Aug 31, 2019

Conversation

Bachmann1234
Copy link
Contributor

@Bachmann1234 Bachmann1234 commented Jul 15, 2019

The goal of this pr is to eventually lead to closing #720

Some example reports from a non trivial project
without Contexts: https://gist.github.com/Bachmann1234/418311192ebff1faca1e3fc54453602c
with Contexts: https://gist.github.com/Bachmann1234/bb799bdc5978a81a1e26daeb1881b950

command help:

venv ❯ coverage --help
Coverage.py, version 5.0a7 with C extension
Measure, collect, and report on code coverage in Python programs.

usage: coverage <command> [options] [args]

Commands:
    annotate    Annotate source files with execution information.
    combine     Combine a number of data files.
    erase       Erase previously collected coverage data.
    help        Get help on using coverage.py.
    html        Create an HTML report.
    json        Create a JSON report of coverage results.
    report      Report coverage stats on modules.
    run         Run a Python program and measure code execution.
    xml         Create an XML report of coverage results.

Use "coverage help <command>" for detailed help on any command.
Full documentation is at https://coverage.readthedocs.io/en/coverage-5.0a7
venv ❯ coverage json --help
Usage: coverage json [options] [modules]

Generate a JSON report of coverage results.

Options:
  --fail-under=MIN      Exit with a status of 2 if the total coverage is less
                        than MIN.
  -i, --ignore-errors   Ignore errors while reading source files.
  --include=PAT1,PAT2,...
                        Include only files whose paths match one of these
                        patterns. Accepts shell-style wildcards, which must be
                        quoted.
  --omit=PAT1,PAT2,...  Omit files whose paths match one of these patterns.
                        Accepts shell-style wildcards, which must be quoted.
  -o OUTFILE            Write the JSON report to this file. Defaults to
                        'coverage.json'
  --pretty-print        Print the json formatted for human readers
  --show-contexts       Show contexts for covered lines.
  --contexts=PAT1,PAT2,...
                        Only display data from lines covered in the given
                        contexts. Accepts shell-style wildcards, which must be
                        quoted.
  --debug=OPTS          Debug options, separated by commas. [env:
                        COVERAGE_DEBUG]
  -h, --help            Get help on this command.
  --rcfile=RCFILE       Specify configuration file. By default '.coveragerc',
                        'setup.cfg' and 'tox.ini' are tried. [env:
                        COVERAGE_RCFILE]

Full documentation is at https://coverage.readthedocs.io/en/coverage-5.0a7

simple report:

{
    "meta": {
        "version": "5.0a7",
        "timestamp": "2019-08-18T13:50:07.353011",
        "branch_coverage": true,
        "show_contexts": false
    },
    "files": {
        "a.py": {
            "executed_lines": [
                1,
                2
            ],
            "summary": {
                "covered_lines": 2,
                "num_statements": 3,
                "percent_covered": 60.0,
                "missing_lines": 1,
                "excluded_lines": 0,
                "num_branches": 2,
                "num_partial_branches": 1
            },
            "missing_lines": [
                3
            ],
            "excluded_lines": []
        }
    },
    "totals": {
        "covered_lines": 2,
        "num_statements": 3,
        "percent_covered": 60.0,
        "missing_lines": 1,
        "excluded_lines": 0,
        "num_branches": 2,
        "num_partial_branches": 1
    }
}

TODO:

  • Iterate on the schema
    
  • document the report in the formal docs
    

cov.json_report(a, outfile=output_path)
with open(output_path) as result_file:
parsed_result = json.loads(result_file.read())
del(parsed_result['meta']['timestamp'])

This comment was marked as resolved.

This comment was marked as resolved.

@nedbat
Copy link
Owner

nedbat commented Jul 22, 2019

Thanks for this. I haven't had time to look at it yet, but will get to it soon!

@Bachmann1234
Copy link
Contributor Author

@nedbat no worries! I'm in no rush. I would love the feedback whenever you have time. However, I am not blocked as I still need to make time to finish up the tests and such.

@codecov-io
Copy link

codecov-io commented Aug 1, 2019

Codecov Report

Merging #825 into master will increase coverage by 0.01%.
The diff coverage is 98.51%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #825      +/-   ##
==========================================
+ Coverage   92.33%   92.34%   +0.01%     
==========================================
  Files          83       85       +2     
  Lines       11201    11302     +101     
  Branches     1141     1146       +5     
==========================================
+ Hits        10342    10437      +95     
- Misses        723      724       +1     
- Partials      136      141       +5
Impacted Files Coverage Δ
coverage/config.py 98.31% <100%> (+0.02%) ⬆️
coverage/jsonreport.py 100% <100%> (ø)
coverage/xmlreport.py 100% <100%> (ø) ⬆️
tests/test_cmdline.py 100% <100%> (ø) ⬆️
tests/test_config.py 100% <100%> (ø) ⬆️
coverage/results.py 96.53% <100%> (+0.02%) ⬆️
coverage/control.py 86.8% <100%> (-1.97%) ⬇️
tests/test_json.py 100% <100%> (ø)
coverage/cmdline.py 90.36% <80%> (+0.16%) ⬆️
coverage/report.py 98% <95.83%> (-2%) ⬇️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 790f0b3...d22c847. Read the comment docs.

@Bachmann1234
Copy link
Contributor Author

howdy! Just checking in to say im still alive. I updated my local master and then rebased this branch to keep it from getting stale. Im thinking ill have some time this weekend to beef up the tests a bit and look at the other todos.

@Bachmann1234 Bachmann1234 force-pushed the json_report branch 2 times, most recently from f7020a4 to 52216fe Compare August 4, 2019 23:01
@Bachmann1234 Bachmann1234 changed the title [WIP] Json report Json report Aug 4, 2019
@Bachmann1234
Copy link
Contributor Author

Ok, think I got decent tests on this the config file is tested so the only thing this needs (I think) is review/confirmation on the schema and then I need to write some docs.

@Bachmann1234
Copy link
Contributor Author

updated from master

Copy link
Owner

@nedbat nedbat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matt, thanks so much for taking this on! My comments run the gamut, I hope you don't mind some pedantry on the English :)

from coverage.misc import isolate_module
from tests.coveragetest import UsingModulesMixin, CoverageTest

os = isolate_module(os)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this in our own test files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

)
json_pretty_print = optparse.make_option(
'', '--pretty-print', action='store_true',
help="print the json formatted for human readers",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capital P.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

Opts.contexts,
] + GLOBAL_ARGS,
usage="[options] [modules]",
description="Generate an JSON report of coverage results."
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an JSON"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

@@ -755,6 +788,7 @@ def unglob_args(args):
report Report coverage stats on modules.
run Run a Python program and measure code execution.
xml Create an XML report of coverage results.
json Create a JSON report of coverage results.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go between "html" and "report" (alphabetically)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

omit=None, include=None, contexts=None, pretty_print=None,
show_contexts=None
):
"""Generate an JSON report of coverage results.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an JSON"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

output_path = os.path.join(self.temp_dir, "a.json")
cov.json_report(a, outfile=output_path)
with open(output_path) as result_file:
parsed_result = json.loads(result_file.read())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

json.load

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

self.data.set_query_contexts(self.config.report_contexts)
meta = {
"version": __version__,
"timestamp": str(int(time.time())),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would ISO8601 be more friendly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in my head I was thinking time.time() would be easier for machine parsing. However its not like ISO8601 would be hard... and it has the benefit of being much more human readable. So sure thing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually looking at this it may have been me doing what xml was doing. Changed to isoformat

reported_file.update({
'arcs_missing': analysis.missing_branch_arcs(),
'arcs_executed': analysis.arcs_executed(),
'arcs_unpredicted': analysis.arcs_unpredicted(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value isn't usually in reports (I think?). I'd rather leave it out that confuse people at first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the references to arcs and just stuck with the branch percentages in totals

'arcs_missing': analysis.missing_branch_arcs(),
'arcs_executed': analysis.arcs_executed(),
'arcs_unpredicted': analysis.arcs_unpredicted(),
'missing_branch_arcs': analysis.missing_branch_arcs(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've reported this twice (also as 'arcs_missing'). I wonder if we should avoid "arcs" in this report, since it's nerdy and internal. Reports tend to talk about "branches".

Also, this value is a dict, while "arcs_executed" is a list of pairs. Let's make them uniform, and both be a list of pairs.

'missing_lines': nums.n_missing,
}
reported_file = {
'executed_lines': list(sorted(analysis.statements)),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

analysis.statements is not the executed lines, it's the executable lines. And, awkwardly, it looks like Analysis computed "executed" but does not make it available...?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Analysis also has excluded, which could be in the report.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@Bachmann1234
Copy link
Contributor Author

Matt, thanks so much for taking this on! My comments run the gamut, I hope you don't mind some pedantry on the English :)

Not at all. If anything I should be a tad bit embarrassed for "an json" :-P

Looks like a mixture of small things and at least one or two big errors on my part to correct. I collected all the feedback. Left a few comments and will start working though this. Thanks!

@Bachmann1234
Copy link
Contributor Author

Handled a lot of the smaller feedback. Still have more to look at though

@Bachmann1234
Copy link
Contributor Author

#825 (comment)

This piece of feedback is still outstanding. We don't need the summary block but I find when looking at the full reports its nice to have these "summary stats" grouped together. Separating these properties from what I have perceived as the more raw data.

So I see it as a tradeoff between making the report a bit easier on the human eye while making it mildly more annoying for the computer to parse since you have to go down one more level to access these properties.

You see it when just scrolling though a non trivial report
https://gist.github.com/Bachmann1234/bb799bdc5978a81a1e26daeb1881b950

^^ diff cover with contexts enabled.

@Bachmann1234
Copy link
Contributor Author

I think all other feedback has been addressed and I updated the readme to reflect the updated state of the code

@Bachmann1234
Copy link
Contributor Author

Bachmann1234 commented Aug 18, 2019

updated pr from latest master

@@ -332,6 +332,10 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest):
hello = world
; comments still work.
names = Jane/John/Jenny

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint reports trailing space here. There's a .editorconfig file in this repo, if you enable it in your editor, it will handle these things automatically.

@nedbat
Copy link
Owner

nedbat commented Aug 24, 2019

On the structure of the JSON: OK, files will have a "summary" key.

This is very close to merging! You'll need to squash the commits. I can add docs, unless you want to take a pass at it. I wonder if people will want us to explain the JSON structure? I hope not.. :)

There's also CHANGES.rst and CONTRIBUTORS.txt, which I can tweak up if you like.

@Bachmann1234
Copy link
Contributor Author

added myself to contributors and added a line to changes. Squashed everything down to one commit. I can take a stab at the docs.

@Bachmann1234 Bachmann1234 force-pushed the json_report branch 2 times, most recently from c60a8d3 to 436eff6 Compare August 29, 2019 01:29
are outputted with whitespace formatted for human consumption (True) or for
minimum file size (False)

``json_show_contexts`` (boolean, default false): should the json report include
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stole the language for this line from the HTML section. I worry its a tad awkward because "on each line" is not quite right in the json context. Its not like the HTML report where every line literally has something I can hover over and see the contexts.

Its more like "Include data in the report showing the contexts recorded for each line"

@Bachmann1234
Copy link
Contributor Author

Bachmann1234 commented Aug 29, 2019

Ok @nedbat I took a stab at the docs. One place I considered making an update but left alone was the FAQ there is a question that references the XML and HTML reports

**Q: I use nose to run my tests, and its coverage plugin doesn't let me create
HTML or XML reports. What should I do?**

I could change that to 'HTML, JSON, or XML' reports if you want but I did not think it added much.

the doc changes are in this commit 436eff6

@nedbat
Copy link
Owner

nedbat commented Aug 29, 2019

@Bachmann1234 this looks great. I am ready to merge it, and will make some minor edits after that. Squash the commits, and let's get this to master-town! :)

@Bachmann1234
Copy link
Contributor Author

@nedbat Squashed down to one commit and ready to go

@Bachmann1234
Copy link
Contributor Author

I have a watch on the repo so ill keep an eye out for any issues around this (or if something else catches my eye). Im sure something will come up. Also you know how to get ahold of me :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants