Search code examples
pythonpytestpytest-cov

pytest-cov showing no coverage


I have a python library named CorGE with the following structure

  • CorGE
    • src
      • __init__.py
      • CorGE
        • __init__.py
        • collect.py
        • command.py
    • tests
      • __init__.py
      • test_collect.py

and I'm trying to produce a coverage report with pytest-cov. Every example/doc I've seen has been something like this

pytest CorGE/tests/ --cov CorGE/

or this

python -m coverage run --source=CorGE/src/CorGE -m pytest CorGE/tests/

but this produces a NoCoverageWarning

CoverageWarning: No data was collected. (no-data-collected)

and a report like this

Name                    Stmts   Miss  Cover
-------------------------------------------
src/CorGE/__init__.py       0      0   100%
src/CorGE/collect.py      127    127     0%
-------------------------------------------
TOTAL                     127    127     0%

Am I just misunderstanding how to use this coverage tool? I've put a whole day into trying different variations on these commands and nothing seems to work. Would love any insight from someone who knows more about this.

Here's the test file, just in case somehow it's the problem, like not calling the src file properly or something.

import os
import shutil
import tempfile
import unittest

from CorGE.command import main

class CommandTests(unittest.TestCase):
    def setUp(self):
        self.temp_dir = tempfile.mkdtemp()

        # collect_genomes input
        self.data_dir = os.path.join('/'.join(__file__.split('/')[:-1]), "test-data")
        self.ncbi_species_fp = os.path.join(self.data_dir, "TEST_TXIDS")
        self.ncbi_accessions_fp = os.path.join(self.data_dir, "TEST_ACCS")
        self.local_db_fp = os.path.join(self.data_dir, "TEST_LOCAL/")

        # collect_genomes outputs
        self.nucl_fp = os.path.join(self.temp_dir, "nucleotide/")
        self.prot_fp = os.path.join(self.temp_dir, "protein/")
        self.outgroup_fp = os.path.join(self.temp_dir, "outgroup/")
    
    def tearDown(self):
        shutil.rmtree(self.temp_dir)
    
    def test_collect_genomes(self):
        main([
            "collect_genomes",
            self.temp_dir,
            "--ncbi_species", self.ncbi_species_fp,
            "--ncbi_accessions", self.ncbi_accessions_fp,
            "--local", self.local_db_fp,
            # --outgroup left as default "2173"
        ])

        self.assertEqual(os.listdir(self.outgroup_fp).sort(), ['GCF_000016525.1.faa', 'GCF_000016525.1.fna'].sort())
        self.assertEqual(os.listdir(self.nucl_fp).sort(), ['GCF_000012885.1.fna', 'GCF_000007725.1.fna', 'GCF_000020965.1.fna',\
            'GCF_001735525.1.fna', 'GCF_007197645.1.fna', 'GCF_001375595.1.fna', 'GCF_000218545.1.fna', 'GCF_000010525.1\n.fna',\
            'GCF_000378225.1.fna', 'GCF_900111765.1.fna', 'GCF_023159115.1.fna'].sort())
        self.assertEqual(os.listdir(self.prot_fp).sort(), ['GCF_000012885.1.faa', 'GCF_000007725.1.faa', 'GCF_000020965.1.faa',\
            'GCF_001735525.1.faa', 'GCF_007197645.1.faa', 'GCF_001375595.1.faa', 'GCF_000218545.1.faa', 'GCF_000010525.1\n.faa',\
            'GCF_000378225.1.faa', 'GCF_900111765.1.faa', 'GCF_023159115.1.faa'].sort())


if __name__ == "__main__":
    unittest.main()


Solution

  • OK I figured out how to make this work but I am thoroughly unsatisfied with my solution. The change I made was to install CorGE in development mode instead of normally with pip install -e . and then everything started working.

    I'm now running pytest --cov . from the root CorGE directory and getting:

    ---------- coverage: platform linux, python 3.10.2-final-0 -----------
    Name                    Stmts   Miss  Cover
    -------------------------------------------
    setup.py                    2      2     0%
    src/CorGE/__init__.py       0      0   100%
    src/CorGE/collect.py      127     19    85%
    src/CorGE/command.py       43      5    88%
    src/CorGE/extract.py      193    167    13%
    src/__init__.py             0      0   100%
    tests/__init__.py           0      0   100%
    tests/test_command.py      35      1    97%
    -------------------------------------------
    TOTAL                     400    194    52%
    

    Why this works, I don't know. Why it doesn't work without this, I don't know even more. Hopefully this helps anyone else frustrated by this in the future.