Merge lp:~mpontillo/maas/code-coverage into lp:~maas-committers/maas/trunk

Proposed by Mike Pontillo
Status: Merged
Approved by: Mike Pontillo
Approved revision: no longer in the source branch.
Merged at revision: 3580
Proposed branch: lp:~mpontillo/maas/code-coverage
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 169 lines (+54/-7)
5 files modified
.bzrignore (+3/-1)
.coveragerc (+10/-0)
Makefile (+20/-1)
buildout.cfg (+18/-5)
required-packages/dev (+3/-0)
To merge this branch: bzr merge lp:~mpontillo/maas/code-coverage
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Raphaël Badin (community) Needs Fixing
Mike Pontillo (community) Abstain
Review via email: mp+251210@code.launchpad.net

Commit message

Run code coverage during "make test", and add build targets to generate coverage reports.

Description of the change

Change "make test" to run the coverage report. Add build targets to generate XML output (for Jenkins) or HTML output (for developers) from the coverage data.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) :
review: Abstain
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Note: python-coverage is only required if you want to create a human readable (or machine readable) report from the '.coverage' file. In the future, Jenkins should run the target to create the XML report, and expose it through the web interface. (the Cobertura plugin can be used for this.)

Revision history for this message
Raphaël Badin (rvb) wrote :

This looks generally good but you're missing a couple of dependencies.

[0]

This is an excerpt of what make test spits out: http://paste.ubuntu.com/10445321/. As you can see, most lines relate to non-MAAS modules. Isn't it possible to not clutter the output like that?

[1]

The HTML report has lines for the test modules themselves. This is a bit weird. I understand that this can be useful in some cases (to detect dead code in tests) but can't we do something about this? (Like put them on a different page or something). What do you think?

[2]

Looks like you're missing a couple of dependencies here.
$ make coverage-report
rm -rf htmlcov
python-coverage html --include 'src/*'
Couldn't find static file 'jquery.hotkeys.js'
make: *** [coverage-report] Error 1

$ sudo apt-get install libjs-jquery-hotkeys
[...]

$ make coverage-report
rm -rf htmlcov
python-coverage html --include 'src/*'
Couldn't find static file 'jquery.isonscreen.js'
make: *** [coverage-report] Error 1

$ sudo apt-get install libjs-jquery-isonscreen

$ make coverage-report
rm -rf htmlcov
python-coverage html --include 'src/*'
Couldn't find static file 'jquery.tablesorter.min.js'
make: *** [coverage-report] Error 1

$ sudo apt-get install libjs-jquery-tablesorter

review: Needs Fixing
Revision history for this message
Gavin Panella (allenap) wrote :

A few comments. I think this is really cool, thank you so much for doing it.

I got a little carried away and made some changes of my own to address my own comments. I also changed some things. The principle is the same though. My patch to your branch: http://paste.ubuntu.com/10452649/

So, basically, it's Needs Fixing, but I'd vote Approve if you can stomach my proposed changes. I hope that's okay.

review: Needs Fixing
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Raphael, I like including the tests in the report for the reason you mention, but agree it would be nice to hide them, since they get in the way (and give a false impression of coverage percentage, assuming they all run!). I don't really like the sorting in the report; the test directories are sorted and appear inline with the code under test.

My original thought was to create a "coverage" target that did the same thing as the "test" target, but my Makefile skills are rusty, so I couldn't figure out how to do it without duplicating code in the Makefile. Then I considered a couple of use cases:

(1) You might want to run coverage manually, then invoke the 'make' targets to create the report
(2) You might want to run a coverage report even if the tests fail, so that you can see which lines of code were executed.

For those reasons, I didn't make the coverage targets depend on the 'test' target. But I think there's a good argument to be made for doing so, and perhaps we should create helper scripts for running the tests, and invoke *those* from the Makefile, rather than adding individual commands to the Makefile.

Nice catch on the dependencies. I suppose I must have had those packages installed already. I don't know why they aren't dependencies of python-coverage; seems like that was overlooked when that was packaged..?

Gavin, thanks for your patch! I applied and pushed it into the review branch. I'll test out your changes.

Revision history for this message
Gavin Panella (allenap) wrote :

With that patch applied, you can do something like:

  rm coverage.data
  bin/test.cluster --with-coverage
  make coverage-report

and get a report for just the cluster. That's another reason not to connect coverage.data to the test target.

Also, if you do:

  make coverage-report

before creating any coverage data, make will exit with an explanation of what you need to do.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (77.1 KiB)

The attempt to merge lp:~mpontillo/maas/code-coverage into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Get:2 http://security.ubuntu.com trusty-security Release [62.0 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates Release [62.0 kB]
Get:5 http://security.ubuntu.com trusty-security/main Sources [71.4 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Get:6 http://security.ubuntu.com trusty-security/universe Sources [17.9 kB]
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [220 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [87.7 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [181 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [105 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [446 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [254 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Fetched 1,509 kB in 2s (556 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport distro-info dnsutils firefox freeipmi-tools gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm pep8 postgresql pyflakes python-bson python-bzrlib python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-iscpy python-jinja2 python-jsonschema python-lockfile python-lxml python-mock python-netaddr python-netifaces python-nose python-oauth pyth...

Revision history for this message
Gavin Panella (allenap) wrote :

Sorry, I gave you an error in my patch.

Revision history for this message
Mike Pontillo (mpontillo) wrote :

Thanks. I thought I fixed that, but later realized I had edited the output file in bin/. I'll wait for the full test run to complete before I try to land it again...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2015-02-17 23:19:09 +0000
3+++ .bzrignore 2015-02-27 22:08:16 +0000
4@@ -1,7 +1,6 @@
5 *.egg
6 *.egg-info
7 *.log
8-./.coverage
9 ./.db.lock
10 ./.installed.cfg
11 ./.noseids
12@@ -12,6 +11,9 @@
13 ./acceptance/source
14 ./bin
15 ./build
16+./coverage
17+./coverage.data
18+./coverage.xml
19 ./db
20 ./develop-eggs
21 ./dist
22
23=== added file '.coveragerc'
24--- .coveragerc 1970-01-01 00:00:00 +0000
25+++ .coveragerc 2015-02-27 22:08:16 +0000
26@@ -0,0 +1,10 @@
27+[run]
28+data_file = coverage.data
29+
30+[report]
31+exclude_lines =
32+ # Have to re-enable the standard pragma
33+ pragma: no cover
34+
35+ # Don't complain if tests don't hit defensive assertion code:
36+ raise NotImplementedError
37
38=== modified file 'Makefile'
39--- Makefile 2015-02-27 14:29:16 +0000
40+++ Makefile 2015-02-27 22:08:16 +0000
41@@ -166,8 +166,24 @@
42 test: test-scripts-all = $(wildcard bin/test.*)
43 # Don't run bin/test.e2e for now; it breaks.
44 test: test-scripts = $(filter-out bin/test.e2e,$(test-scripts-all))
45+test: export NOSE_WITH_COVERAGE = 1
46 test: build
47- echo $(test-scripts) | xargs -n1 env
48+ @$(RM) coverage.data
49+ @echo $(test-scripts) | xargs --verbose -n1 env
50+
51+coverage-report: coverage/index.html
52+ sensible-browser $< > /dev/null 2>&1 &
53+
54+coverage.xml: coverage.data
55+ python-coverage xml --include 'src/*' -o $@
56+
57+coverage/index.html: coverage.data
58+ @$(RM) -r $(@D)
59+ python-coverage html --include 'src/*' -d $(@D)
60+
61+coverage.data:
62+ @$(error Use `$(MAKE) test` to generate coverage data, or invoke a \
63+ test script using the `--with-coverage` flag)
64
65 lint: lint-py lint-js lint-doc
66
67@@ -246,6 +262,8 @@
68 $(RM) docs/api.rst
69 $(RM) -r docs/_autosummary docs/_build
70 $(RM) -r man/.doctrees
71+ $(RM) coverage.data coverage.xml
72+ $(RM) -r coverage
73
74 distclean: clean stop
75 $(RM) -r bin include lib local
76@@ -277,6 +295,7 @@
77 build
78 check
79 clean
80+ coverage-report
81 dbharness
82 distclean
83 doc
84
85=== modified file 'buildout.cfg'
86--- buildout.cfg 2015-02-19 15:17:15 +0000
87+++ buildout.cfg 2015-02-27 22:08:16 +0000
88@@ -92,11 +92,12 @@
89 sys.argv[1:1] = [
90 "test", "--noinput", "--exclude=provisioningserver",
91 "--exclude=maastesting", "--exclude=maascli",
92- "--logging-level=INFO", "--logging-clear-handlers",
93+ "--cover-package=maas,maasserver,metadataserver",
94 # Reduce the logging level to INFO here as
95 # DebuggingLoggerMiddleware logs the content of all the
96 # requests at DEBUG level: we don't want this in the
97 # tests as it's too verbose.
98+ "--logging-level=INFO", "--logging-clear-handlers",
99 ]
100 scripts = test.region
101 extra-paths =
102@@ -120,7 +121,10 @@
103 entry-points =
104 test.cli=nose.core:TestProgram
105 initialization =
106- sys.argv[1:1] = ["--where=src/maascli"]
107+ sys.argv[1:1] = [
108+ "--where=src/maascli",
109+ "--cover-package=apiclient,maascli",
110+ ]
111 extra-paths = ${cli:extra-paths}
112 scripts =
113 test.cli
114@@ -145,7 +149,10 @@
115 entry-points =
116 test.testing=nose.core:TestProgram
117 initialization =
118- sys.argv[1:1] = ["--where=src/maastesting"]
119+ sys.argv[1:1] = [
120+ "--where=src/maastesting",
121+ "--cover-package=maastesting",
122+ ]
123 extra-paths = ${common:extra-paths}
124 scripts =
125 test.testing
126@@ -181,7 +188,10 @@
127 test.cluster=nose.core:TestProgram
128 initialization =
129 ${common:initialization}
130- sys.argv[1:1] = ["--where=src/provisioningserver"]
131+ sys.argv[1:1] = [
132+ "--where=src/provisioningserver",
133+ "--cover-package=provisioningserver",
134+ ]
135 extra-paths = ${cluster:extra-paths}
136 scripts =
137 test.cluster
138@@ -194,7 +204,10 @@
139 test.config=nose.core:TestProgram
140 initialization =
141 ${common:initialization}
142- sys.argv[1:1] = ["--where=etc/maas/templates/commissioning-user-data"]
143+ sys.argv[1:1] = [
144+ "--where=etc/maas/templates/commissioning-user-data",
145+ "--cover-package=snippets",
146+ ]
147 extra-paths = ${common:extra-paths}
148 scripts =
149 test.config
150
151=== modified file 'required-packages/dev'
152--- required-packages/dev 2015-02-26 12:31:44 +0000
153+++ required-packages/dev 2015-02-27 22:08:16 +0000
154@@ -5,12 +5,15 @@
155 firefox
156 gjs
157 ipython
158+libjs-jquery
159+libjs-jquery-hotkeys
160 libjs-yui3-full
161 make
162 nodejs-legacy
163 npm
164 pep8
165 pyflakes
166+python-coverage
167 python-extras
168 python-fixtures
169 python-flake8