Hi,
While toying with the code for #844 , I was trying to find the coverage of tests of what I was altering, but I couldn't locate the report. And with some upcoming changes for the new GUI, Python 3, and new features and bug fixes, probably having the test coverage reported for the current code will help preventing regressions.
I've been learning a bit more about Coverage.py, and have some local results, but nothing that would work on Travis-CI yet. Here's a list of subtasks that I think have to be completed for the report to be available to all here in Github.
prove and shell script.travis-ci.yml.travis.yml file)Running the tests with prove and shell script makes it a little more difficult to get the coverage for cylc test-battery, but I have it working (kinda) locally. Still needs a few kicks until it works as expected, but for most small tests I've been doing it reported the correct coverage.
Not sure if the chunks for tests will work with the coverage. What I saw in other projects, was the matrix feature from Travis CI being used for running multiple versions of Python/Cython/etc. And then when generating the report, it would execute for only one value of the matrix.
Our case is somewhat special, as I believe we would need an aggregated report, with the total coverage of the 4 chunks that we have right now.
Also never used Codacy for coverage, only coveralls and sonarqube, but so far it looks good! Will update the ticket later, but if anybody has some more information about coverage, feel free to chime in :-)
Thanks @kinow - yes it would be really good to get coverage tests working this year; it sounds a little more difficult than I had imagined!
Indeed it is @hjoliver ! Doable, bit of fun, but Travis CI and the chunks feature are quite a challenge.
I have a local report that I could even upload somewhere. Even though my check-software is saying FOUND for almost all dependencies (missing preprint and texlive only), I am not sure if there is any other configuration that would enable more tests.
My notes for running the tests are in some post-its and a text file on my desktop here. So documenting here how to get coverage for the tests, so that I can run this again in other workstation if necessary - or if anybody would like to take a look.
pip install coverage.That should put the executable coverage in your $PATH
Normally you would run something like coverage run nosetests. Where coverage run is simply going to have a chance to prepare and start collecting coverage of your python code. But as running cylc test-battery actually involves running shell scripts and utilities to get the python code running, the best example from coverage.py documentation is the part about subprocesses, with a few tweaks.
First, you will need a .coveragerc in the project root, with the content similar to:
[run]
parallel = True
branch = True
cover_pylib = False
data_file=/home/user/workspace/cylc/.coverage
source=
./bin
./lib
#debug=
# callers
# dataio
# multiprocess
# dataio
# dataop
# pid
# plugin
# process
# sys
# trace
timid = False
[report]
exclude_lines =
pragma: no cover
def __repr__
raise NotImplementedError
if __name__ == .__main__.:
def parse_args
ignore_errors = False
precision=2
show_missing=True
Read the coverage.py documentation for details about each key in the ini configuration file. The data_file is necessary, as some tests appear to result in the coverage file .coverage in sub directories.
Every time you run coverage.py, it will produce a .coverage file. But as we have the parallel set, then coverage.py will output something like .coverage.computer.12345, which are hostname and process ID. In the end, there will be several .coverage____ files in the root directory.
As mentioned in the previous section, one cannot simply run coverage run cylc test-battery. The cylc in that command line is a shell script, and coverage.py will just give up collecting coverage after that, regardless of all the effort you have put in making that configuration file (I spent quite some time until I realized that).
Similarly to Jacoco/Cobertura/Clover+XDebug and so many other tools, you have to "tell coverage.py to instrument the code". There are two ways of doing that, documentation in the subprocess documentation section mentioned here before.
The way that worked for me, was with a .pth file. This file, when put in certain locations, will always be executed before a Python script. The hack, used for coverage.py, is that you can also load modules, and execute them.
So we can instruct all Python processes in our system to always start coverage. That will alert coverage.py that we want it to instrument the code and collect coverage. In my enviroment (a Ubuntu LTS with system Python, not Anaconda), I created the file /usr/lib/python2.7/dist-packages/cylc.pth.
import sys; import coverage; import os; os.environ['COVERAGE_PROCESS_START'] = "/home/kinow/workspace/cylc/.coveragerc"; coverage.process_startup();
_(I entered some garbage in this file, and in different locations, and simply started python in a terminal, until I got a few places where it worked, and I could confirm it was being loaded...)_
Now you can finally run the Cylc tests as you would normally do, and coverage.py will take care to collect the coverage. As you enabled parallel = True, you will have multiple .coverage output files. Well done! よーし!
cylc test-battery
If you have experience with Java's Emma/Jacoco, this will be a pretty common task, that works exactly the same way.
Given you have multiple coverage output files, you can combine all these files with
coverage combine --append
The --append is a new feature (4.1 or 4.2 I think) that, instead of overwriting values, will sum up and report the totals in the coverage (NB probably useful for the _chunk_ feature in Travis CI).
Finally, you can report the coverage in the terminal with
coverage report
Or get a HTML report with
coverage html
By default the HTML report is created under the folder ./htmlcov.
Each configuration in the configuration file .coveragerc corresponds more or less to a task in this pipeline. Where run contains information for running the tests, report will be used when combining and reporting the results, and html can also be used for changing style, title, and location of the coverage HTML.
This text was quickly written to offload the notes from post-its over my desk, and from a confusing text file from my desktop. My current workstation contains a working set up, but I intend to re-read these notes and re-run step by step, reviewing and correcting it, in the near future on another workstation.
More to come about Travis CI later on :walking_man:
@kinow - out of interest, have your experiments resulted in ball-park coverage estimates yet?
(We should bear in mind that the old GUI is a known black spot, and that coverage may also be degraded by batch-system and remote-specific tests that get skipped in the default set-up, but I guess we should still "bite the bullet" and try to figure this out).
@hjoliver I had an old copy of the htmlcov folder, but must have deleted. By chance, I came have lunch at home as I have to take some documents to another building nearby, so left the tests running. Used the latest version from the master branch. Here's the output of my check-software:
cylc check-software
Checking your software...
Individual results:
==========================================================================================
Package (version requirements) Outcome (version found)
==========================================================================================
*REQUIRED SOFTWARE*
Python (2.6+, <3)............................FOUND & min. version MET (2.7.15.candidate.1)
*OPTIONAL SOFTWARE for the GUI & dependency graph visualisation*
Python:pygtk (2.0+)......................................FOUND & min. version MET (2.24.0)
graphviz (any)..............................................................FOUND (2.40.1)
Python:pygraphviz (any)......................................................FOUND (1.3.1)
*OPTIONAL SOFTWARE for the HTML User Guide*
ImageMagick (any)..........................................................FOUND (6.9.7-4)
*OPTIONAL SOFTWARE for the HTTPS communications layer*
Python:urllib3 (any)..........................................................FOUND (1.23)
Python:OpenSSL (any)........................................................FOUND (18.0.0)
Python:requests (2.4.2+).................................FOUND & min. version MET (2.19.1)
*OPTIONAL SOFTWARE for the configuration templating*
Python:EmPy (any)............................................................FOUND (3.3.2)
*OPTIONAL SOFTWARE for the LaTeX User Guide*
TeX:framed (any)...............................................................FOUND (n/a)
TeX (3.0+)...........................................FOUND & min. version MET (3.14159265)
TeX:tocloft (any)..............................................................FOUND (n/a)
TeX:tex4ht (any)...............................................................FOUND (n/a)
TeX:preprint (any)...........................................................NOT FOUND (-)
TeX:texlive (any)............................................................NOT FOUND (-)
==========================================================================================
Summary:
****************************
Core requirements: ok
Full-functionality: not ok
****************************
Some tests failed, but I believe it must be something that I'm missing:
Test Summary Report
-------------------
tests/authentication/05-full-control.t (Wstat: 0 Tests: 12 Failed: 4)
Failed tests: 2-5
tests/authentication/02-state-totals.t (Wstat: 0 Tests: 10 Failed: 4)
Failed tests: 2-5
tests/authentication/06-suite-override.t (Wstat: 0 Tests: 12 Failed: 4)
Failed tests: 2-5
tests/syntax/00-pep8.t (Wstat: 0 Tests: 3 Failed: 1)
Failed test: 3
tests/authentication/03-full-read.t (Wstat: 0 Tests: 11 Failed: 4)
Failed tests: 2-5
tests/authentication/04-shutdown.t (Wstat: 0 Tests: 12 Failed: 4)
Failed tests: 2-5
tests/authentication/07-sha-hash.t (Wstat: 0 Tests: 12 Failed: 4)
Failed tests: 2-5
tests/authentication/01-description.t (Wstat: 0 Tests: 10 Failed: 4)
Failed tests: 2-5
tests/job-submission/16-timeout.t (Wstat: 0 Tests: 4 Failed: 1)
Failed test: 3
tests/authentication/00-identity.t (Wstat: 0 Tests: 17 Failed: 8)
Failed tests: 2-5, 10-13
Files=659, Tests=2437, 2264 wallclock secs ( 2.19 usr 0.77 sys + 1412.94 cusr 274.67 csys = 1690.57 CPU)
Result: FAIL
It created 12116 .coverage.localhost.123.123 coverage output files, which after combine --append result in a single file sized 213K.
_(the settings must need some tweaking, as it apparently included a file from my $PATH which is not related to cylc: Couldn't parse '/home/kinow/bin/a2dp.py' as Python source: 'invalid syntax' at line 118... will investigate later)_
I'm uploading it to a GitHub repository with the pages setting enabled. This way will be easier to review the coverage numbers we have right now. During my tests, I had a simplified script, that covered just the print_tree function. Later, I started running more tests, and checking lib/parsec/validate.py, and lib/cylc/config.py, which I believe are interesting & important files :-)
| File | Coverage |
| ------------- | ------------- |
| lib/cylc/config.py | 34.91% |
| lib/parsec/validate.py | 57.41% |
I am not too crazy about trying to achieve 100% coverage. Instead, normally I try to have enough coverage in the important parts of the system, and later slowly add more as necessary (tests have a cost associated with writing and maintaining them after all).
But I am really looking forward to what's going to happen once we have a proper coverage solution. From past experience, adding coverage to a project that exists for a while, normally has some positive results such as:
SuiteAdapterZorkAbc with 90% coverage, while SuiteAdapterZorba has 10%. Some times it's just because the design of the classes is different, maybe one was added later, and needs an update so that it's easier to test)Thanks, this is going to be useful.
Committed here https://github.com/kinow/kinow.github.io, which in theory should be available at https://kinow.github.io/index.html, but I guess it's cached somewhere with the previous test site I had there.
If you see a different page, try again in a few seconds, or clone the repo and open locally, and you should be able to navigate the results. That's the default output of Coverage.py.
Wow, this is really useful information!
One thing is, we should exclude bundled external packages (which are only bundled with Cylc for pragrmatic reasons, and should have their own tests): lib/jinja2, lib/cherrypy, lib/markupsafe.
Can we also exclude the current GUI and just acknowledge that this is not tested at all (but is stable and static, and soon to be replaced).
One thing is, we should exclude bundled external packages (which are only bundled with Cylc for pragrmatic reasons, and should have their own tests): lib/jinja2, lib/cherrypy, lib/markupsafe.
Oh, good point. That's fairly easy. Right now I'm simply telling Coverage.py what are the source directories (bin & lib). But I can combine that with omit key. Only limitation is that it's not possible to use the source directories + the include key, as they are exclusive.
Can we also exclude the current GUI and just acknowledge that this is not tested at all (but is stable and static, and soon to be replaced).
+1
Got a branch with a working setup. But here are some important notes:
--partial argument). However, the Python utility doesn't support it. Instead, you have to use the JAR--final argument..travis.yml to use stages instead of matrix.test, and the second is report. If you do not specify a stage name, Travis assumes you meant the last available stage, or test if no previous stage.coverage xml. To prevent that from stopping the whole coverage analysis of all chunks, we need to use --ignore-warnings with the coverage xml command..travis.pth file didn't work on Travis-CI very well, but I found a post with a nice set up for the sitecustomize.py. Basically, it consists in running PYTHONPATH=.travis, and having a sitecustomize.py in that folder. This way we can run a script before each Python script, starting up the coverage process.@kinow - #2766 is merged - can we close this now?
Yup, forgot we had an issue too, sorry. Closing.
Most helpful comment
Indeed it is @hjoliver ! Doable, bit of fun, but Travis CI and the chunks feature are quite a challenge.
I have a local report that I could even upload somewhere. Even though my
check-softwareis sayingFOUNDfor almost all dependencies (missing preprint and texlive only), I am not sure if there is any other configuration that would enable more tests.My notes for running the tests are in some post-its and a text file on my desktop here. So documenting here how to get coverage for the tests, so that I can run this again in other workstation if necessary - or if anybody would like to take a look.
Install coverage.py with
pip install coverage.That should put the executable
coveragein your$PATHConfigure coverage.py
Normally you would run something like
coverage run nosetests. Wherecoverage runis simply going to have a chance to prepare and start collecting coverage of your python code. But as runningcylc test-batteryactually involves running shell scripts and utilities to get the python code running, the best example from coverage.py documentation is the part about subprocesses, with a few tweaks.First, you will need a
.coveragercin the project root, with the content similar to:Read the coverage.py documentation for details about each key in the ini configuration file. The
data_fileis necessary, as some tests appear to result in the coverage file.coveragein sub directories.Every time you run coverage.py, it will produce a
.coveragefile. But as we have theparallelset, then coverage.py will output something like.coverage.computer.12345, which are hostname and process ID. In the end, there will be several.coverage____files in the root directory.Running coverage.py
As mentioned in the previous section, one cannot simply run
coverage run cylc test-battery. Thecylcin that command line is a shell script, and coverage.py will just give up collecting coverage after that, regardless of all the effort you have put in making that configuration file (I spent quite some time until I realized that).Similarly to Jacoco/Cobertura/Clover+XDebug and so many other tools, you have to "tell coverage.py to instrument the code". There are two ways of doing that, documentation in the subprocess documentation section mentioned here before.
The way that worked for me, was with a
.pthfile. This file, when put in certain locations, will always be executed before a Python script. The hack, used for coverage.py, is that you can also load modules, and execute them.So we can instruct all Python processes in our system to always start coverage. That will alert coverage.py that we want it to instrument the code and collect coverage. In my enviroment (a Ubuntu LTS with system Python, not Anaconda), I created the file
/usr/lib/python2.7/dist-packages/cylc.pth._(I entered some garbage in this file, and in different locations, and simply started
pythonin a terminal, until I got a few places where it worked, and I could confirm it was being loaded...)_Now you can finally run the Cylc tests as you would normally do, and coverage.py will take care to collect the coverage. As you enabled
parallel = True, you will have multiple.coverageoutput files. Well done! よーし!cylc test-batteryCombining the multiple .coverage files
If you have experience with Java's Emma/Jacoco, this will be a pretty common task, that works exactly the same way.
Given you have multiple coverage output files, you can combine all these files with
coverage combine --appendThe
--appendis a new feature (4.1 or 4.2 I think) that, instead of overwriting values, will sum up and report the totals in the coverage (NB probably useful for the _chunk_ feature in Travis CI).Reporting the coverage
Finally, you can report the coverage in the terminal with
coverage reportOr get a HTML report with
coverage htmlBy default the HTML report is created under the folder
./htmlcov.Notes about the configuration file
Each configuration in the configuration file
.coveragerccorresponds more or less to a task in this pipeline. Whereruncontains information for running the tests,reportwill be used when combining and reporting the results, andhtmlcan also be used for changing style, title, and location of the coverage HTML.Final notes
This text was quickly written to offload the notes from post-its over my desk, and from a confusing text file from my desktop. My current workstation contains a working set up, but I intend to re-read these notes and re-run step by step, reviewing and correcting it, in the near future on another workstation.
More to come about Travis CI later on :walking_man: