Search code examples
perlcode-coveragecpan

Coverage report for Perl modules by cpancover.com


cpancover.com produces reports on the code coverage of Perl modules.

I understand it's just a webserver using Devel::Cover, but I would like to simply understand the meaning of reports like: http://cpancover.com/latest/JSON-PP-4.02/blib-lib-JSON-PP-pm--condition.html

where a table has columns like:

  • !l
  • l&&!r
  • l&&r

Can you, please, link a relevant document to understand this or provide me some initial guidance to these reports?


Solution

  • l and r refer to the right-hand side and left-hand side of the expression, and the number represents the number of times the associated expression was true.

    For example, there is a coverage of 0 for l && !r for the following expression:

    exists $self->{'true'} and exists $self->{'false'} 
    

    That means that 0 tests cover the situation where the following is true:

    (exists $self->{'true'}) && !(exists $self->{'false'})
    

    Logical-and and logical-or have two inputs that can take each of two values.

    +-----------------+-----------------+
    | Left-hand side  | Right-hand side |
    +-----------------+-----------------+
    | False           | False           |
    | False           | True            |
    | True            | False           |
    | True            | True            |
    +-----------------+-----------------+
    

    However, because of short-circuiting, Perl doesn't always evaluate the right-hand side. The cases are really the following:

    +-----------------------------------+
    | Logical AND                       |
    +-----------------+-----------------+
    | Left-hand side  | Right-hand side |
    +-----------------+-----------------+
    | False           | -               |
    | True            | False           |
    | True            | True            |
    +-----------------+-----------------+
    
    +-----------------------------------+
    | Logical OR                        |
    +-----------------+-----------------+
    | Left-hand side  | Right-hand side |
    +-----------------+-----------------+
    | False           | False           |
    | False           | True            |
    | True            | -               |
    +-----------------+-----------------+
    

    Devel::Cover is reporting which of these sets of inputs have been tested.

    +--------------------------------------------------------+
    | Logical AND                                            |
    +--------------------+-----------------+-----------------+
    | Devel::Cover label | Left-hand side  | Right-hand side |
    +--------------------+-----------------+-----------------+
    | !l                 | False           | -               |
    | l && !r            | True            | False           |
    | l && r             | True            | True            |
    +--------------------+-----------------+-----------------+
    
    +--------------------------------------------------------+
    | Logical OR                                             |
    +--------------------+-----------------+-----------------+
    | Devel::Cover label | Left-hand side  | Right-hand side |
    +--------------------+-----------------+-----------------+
    | l                  | True            | -               |
    | !l && r            | False           | True            |
    | !l && !r           | False           | False           |
    +--------------------+-----------------+-----------------+
    

    If we look at the first line of the linked page, we see

    !l        2
    l && !r   0
    l && r    2
    

    for

    exists $self->{'true'} and exists $self->{'false'} 
    

    That means

    !l       meaning  !(exists $self->{'true'})                               was true  2  times.
    l && !r  meaning  (exists $self->{'true'}) && !(exists $self->{'false'})  was true  0  times.
    l && r   meaning  (exists $self->{'true'}) && (exists $self->{'false'})   was true  2  times.
    

    This means that (exists $self->{'true'}) && !(exists $self->{'false'}) being true was never tested.