Coveragepy: Option to output lcov.info format?

Created on 16 Jun 2017  Ā·  11Comments  Ā·  Source: nedbat/coveragepy

Originally reported by Matthew Crenshaw (Bitbucket: sgtsquiggs, GitHub: sgtsquiggs)


So that we can use coverage.py with IDE plugins that read the standard lcov.info format and highlight covered/uncovered lines. Would be super great!


enhancement

Most helpful comment

Hope to see this being implemented soon!

If anyone needs a converting tool in the meantime, I created a simple converter here: https://github.com/chaychoong/coveragepy-lcov

All 11 comments

I am not working on this at the moment, and probably will not be implementing this any time soon. There's no reason this has to be built-in to coverage.py. You can get data from coverage in XML format, or using the data API, and create a file like this with separate code.

Original comment by Bojan Kogoj (Bitbucket: bojankogoj, GitHub: bojankogoj)


Any progress? I'd like to use vs code coverage plugin but it doesn't support current format

I'm a bit nervous about the language semantics assumed by this file format (list of functions found?), but that seems to be par for the course for any of these formats.

Original comment by Matthew Crenshaw (Bitbucket: sgtsquiggs, GitHub: sgtsquiggs)


lcov format

   Following  is  a  quick  description of the tracefile format as used by
   genhtml, geninfo and lcov.

   A tracefile is made up of several human-readable lines of text, divided
   into sections. If available, a tracefile begins with the testname which
   is stored in the following format:

     TN:<test name>

   For each source file referenced in the .da file,  there  is  a  section
   containing filename and coverage data:

     SF:<absolute path to the source file>

   Following is a list of line numbers for each function name found in the
   source file:

     FN:<line number of function start>,<function name>

   Next, there is a list of execution counts for each  instrumented  func‐
   tion:

     FNDA:<execution count>,<function name>

   This  list  is followed by two lines containing the number of functions
   found and hit:

     FNF:<number of functions found>
     FNH:<number of function hit>

   Branch coverage information is stored which one line per branch:

     BRDA:<line number>,<block number>,<branch number>,<taken>

   Block number and branch number are gcc internal  IDs  for  the  branch.
   Taken  is either '-' if the basic block containing the branch was never
   executed or a number indicating how often that branch was taken.

   Branch coverage summaries are stored in two lines:

     BRF:<number of branches found>
     BRH:<number of branches hit>

   Then there is a list of execution counts  for  each  instrumented  line
   (i.e. a line which resulted in executable code):

     DA:<line number>,<execution count>[,<checksum>]

   Note  that  there  may be an optional checksum present for each instru‐
   mented line. The current geninfo implementation uses  an  MD5  hash  as
   checksumming algorithm.

   At  the  end of a section, there is a summary about how many lines were
   found and how many were actually instrumented:

     LH:<number of lines with a non-zero execution count>
     LF:<number of instrumented lines>

   Each sections ends with:

     end_of_record

   In addition to the main source code file there  are  sections  for  all
   #included files which also contain executable code.

   Note that the absolute path of a source file is generated by interpret‐
   ing the contents of the respective .bb file  (see  gcov  (1)  for  more
   information  on  this  file type). Relative filenames are prefixed with
   the directory in which the .bb file is found.

   Note also that symbolic links to the .bb file will be resolved so  that
   the  actual  file  path  is  used  instead  of the path to a link. This
   approach is necessary for the mechanism to  work  with  the  /proc/gcov
   files.

Interesting idea. Do you have a link to information about the file format?

FWIW we've been using a patch for eons at work that has coverage generate LCOV files. Let me see about extricating that and making a PR.

Example non-great code posted as a PR to help kick things off. :)

We've gotten repeated requests to support python coverage in Bazel (https://bazel.build/) and integrating it in a multi-language situation (e.g., coverage for Python + C++) requires being able to generate lcov format.

I really haven't spend much time untangling this, are there any links to the specifics of the LCOV format or the specifics of what subset of that Bazel expects from LCOV files? (see also the comment thread on (https://github.com/nedbat/coveragepy/pull/863).

Bazel supports multi-language coverage, e.g., getting coverage results from Java, Python, and C++ from a single test run. However, in order to generate a combined report, all of these need to be converted into a single unified format. We've looked at different formats, and it seems like every coverage tool / implementation comes with its own format, and none is particularly prevalent. Our main restriction is that it shouldn't be too verbose (so XML might be a problem). Whatever format we standardize on in Bazel, we need to convert from all other formats to that one.

Right now, we're using lcov as our "standard" format, which is fairly simple, reasonably compact, and it's the same format Google uses internally (full disclosure: I work for Google). For large code bases, we're seeing multi-GB lcov outputs, so less compact could be problematic.

Ideally, whatever format we use also supports advanced features like branch coverage or edge coverage, but it's more important to settle on something than to have the latest and greatest features.

Each tool has to decide what lines to mark as covered. I would strongly recommend that it at least correctly annotate on a per-file level; there are potential uses for automatically selecting affected tests based on coverage information from a previous test run to reduce CI resource usage.

One more thing: Python is an exception, but we otherwise don't allow access to source code from the test run. Bazel sandboxes execution, and - by design - does not support general source access. We collect lcov from the test runs, and then generate an HTML report as a post-process during which we allow source access. As a corollary, the coverage tool should not put absolute paths into the output, because the sandbox is in a different file system location. We can post-process the data if necessary, but it's not ideal. Ideal is to use relative paths to the current working directory.

Hope to see this being implemented soon!

If anyone needs a converting tool in the meantime, I created a simple converter here: https://github.com/chaychoong/coveragepy-lcov

Was this page helpful?
0 / 5 - 0 ratings