Impossible to track code coverage in device server code
Problem statement:
In Python it is very common to use the https://pypi.org/project/coverage/ library to track code coverage across unit tests. However, with PyTango this results in severe under reporting as any code in device servers is never correctly tracked. Neither through TestDeviceContext
or by manually inserting coverage statements into the init_device
.
Below is an example of how forcefully storing a coverage database was implemented in a device server. Using this approach the resulting coverage file remains empty not detecting any code covered.
class Example(Device):
@command()
def store_coverage(self):
try:
self.cov.stop()
self.cov.save()
logger.info("Stopped code coverage measurements")
except Exception:
pass
@command()
def start_coverage(self):
try:
import os
import atexit
import coverage
self.cov = coverage.Coverage(
config_file=os.getcwd() + "/.coveragerc",
data_file=os.getcwd() + "/.coverage",
data_suffix=True
)
self.cov.start()
logger.info("Started code coverage measurements: %s", os.getcwd())
atexit.register(self.store_coverage)
except Exception as e:
logger.exception("Could not configure for code coverage: %s", e)
Below is the coveragerc:
[run]
branch = True
source = example
concurrency = multiprocessing,thread,greenlet
parallel = True
[report]
ignore_errors = True
Suspected Cause: I Suspect the device server is actually started by forking or spawning a thread in the C++ layer and this prevent coverage from working correctly. Notice that setting the concurrency models in coveragerc has no effect.
Potential Solutions:
I really do not know enough of the interactions between tango and pytango to make a qualified suggestion on this but perhaps you can check settings COVERAGE_PROCESS_START
as environment variable and calling import coverage; coverage.process_startup()
for the import you can use monkeypatching in case the library is unavailable.