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
=== modified file '.bzrignore'
--- .bzrignore 2015-02-17 23:19:09 +0000
+++ .bzrignore 2015-02-27 22:08:16 +0000
@@ -1,7 +1,6 @@
1*.egg1*.egg
2*.egg-info2*.egg-info
3*.log3*.log
4./.coverage
5./.db.lock4./.db.lock
6./.installed.cfg5./.installed.cfg
7./.noseids6./.noseids
@@ -12,6 +11,9 @@
12./acceptance/source11./acceptance/source
13./bin12./bin
14./build13./build
14./coverage
15./coverage.data
16./coverage.xml
15./db17./db
16./develop-eggs18./develop-eggs
17./dist19./dist
1820
=== added file '.coveragerc'
--- .coveragerc 1970-01-01 00:00:00 +0000
+++ .coveragerc 2015-02-27 22:08:16 +0000
@@ -0,0 +1,10 @@
1[run]
2data_file = coverage.data
3
4[report]
5exclude_lines =
6 # Have to re-enable the standard pragma
7 pragma: no cover
8
9 # Don't complain if tests don't hit defensive assertion code:
10 raise NotImplementedError
011
=== modified file 'Makefile'
--- Makefile 2015-02-27 14:29:16 +0000
+++ Makefile 2015-02-27 22:08:16 +0000
@@ -166,8 +166,24 @@
166test: test-scripts-all = $(wildcard bin/test.*)166test: test-scripts-all = $(wildcard bin/test.*)
167# Don't run bin/test.e2e for now; it breaks.167# Don't run bin/test.e2e for now; it breaks.
168test: test-scripts = $(filter-out bin/test.e2e,$(test-scripts-all))168test: test-scripts = $(filter-out bin/test.e2e,$(test-scripts-all))
169test: export NOSE_WITH_COVERAGE = 1
169test: build170test: build
170 echo $(test-scripts) | xargs -n1 env171 @$(RM) coverage.data
172 @echo $(test-scripts) | xargs --verbose -n1 env
173
174coverage-report: coverage/index.html
175 sensible-browser $< > /dev/null 2>&1 &
176
177coverage.xml: coverage.data
178 python-coverage xml --include 'src/*' -o $@
179
180coverage/index.html: coverage.data
181 @$(RM) -r $(@D)
182 python-coverage html --include 'src/*' -d $(@D)
183
184coverage.data:
185 @$(error Use `$(MAKE) test` to generate coverage data, or invoke a \
186 test script using the `--with-coverage` flag)
171187
172lint: lint-py lint-js lint-doc188lint: lint-py lint-js lint-doc
173189
@@ -246,6 +262,8 @@
246 $(RM) docs/api.rst262 $(RM) docs/api.rst
247 $(RM) -r docs/_autosummary docs/_build263 $(RM) -r docs/_autosummary docs/_build
248 $(RM) -r man/.doctrees264 $(RM) -r man/.doctrees
265 $(RM) coverage.data coverage.xml
266 $(RM) -r coverage
249267
250distclean: clean stop268distclean: clean stop
251 $(RM) -r bin include lib local269 $(RM) -r bin include lib local
@@ -277,6 +295,7 @@
277 build295 build
278 check296 check
279 clean297 clean
298 coverage-report
280 dbharness299 dbharness
281 distclean300 distclean
282 doc301 doc
283302
=== modified file 'buildout.cfg'
--- buildout.cfg 2015-02-19 15:17:15 +0000
+++ buildout.cfg 2015-02-27 22:08:16 +0000
@@ -92,11 +92,12 @@
92 sys.argv[1:1] = [92 sys.argv[1:1] = [
93 "test", "--noinput", "--exclude=provisioningserver",93 "test", "--noinput", "--exclude=provisioningserver",
94 "--exclude=maastesting", "--exclude=maascli",94 "--exclude=maastesting", "--exclude=maascli",
95 "--logging-level=INFO", "--logging-clear-handlers",95 "--cover-package=maas,maasserver,metadataserver",
96 # Reduce the logging level to INFO here as96 # Reduce the logging level to INFO here as
97 # DebuggingLoggerMiddleware logs the content of all the97 # DebuggingLoggerMiddleware logs the content of all the
98 # requests at DEBUG level: we don't want this in the98 # requests at DEBUG level: we don't want this in the
99 # tests as it's too verbose.99 # tests as it's too verbose.
100 "--logging-level=INFO", "--logging-clear-handlers",
100 ]101 ]
101scripts = test.region102scripts = test.region
102extra-paths =103extra-paths =
@@ -120,7 +121,10 @@
120entry-points =121entry-points =
121 test.cli=nose.core:TestProgram122 test.cli=nose.core:TestProgram
122initialization =123initialization =
123 sys.argv[1:1] = ["--where=src/maascli"]124 sys.argv[1:1] = [
125 "--where=src/maascli",
126 "--cover-package=apiclient,maascli",
127 ]
124extra-paths = ${cli:extra-paths}128extra-paths = ${cli:extra-paths}
125scripts =129scripts =
126 test.cli130 test.cli
@@ -145,7 +149,10 @@
145entry-points =149entry-points =
146 test.testing=nose.core:TestProgram150 test.testing=nose.core:TestProgram
147initialization =151initialization =
148 sys.argv[1:1] = ["--where=src/maastesting"]152 sys.argv[1:1] = [
153 "--where=src/maastesting",
154 "--cover-package=maastesting",
155 ]
149extra-paths = ${common:extra-paths}156extra-paths = ${common:extra-paths}
150scripts =157scripts =
151 test.testing158 test.testing
@@ -181,7 +188,10 @@
181 test.cluster=nose.core:TestProgram188 test.cluster=nose.core:TestProgram
182initialization =189initialization =
183 ${common:initialization}190 ${common:initialization}
184 sys.argv[1:1] = ["--where=src/provisioningserver"]191 sys.argv[1:1] = [
192 "--where=src/provisioningserver",
193 "--cover-package=provisioningserver",
194 ]
185extra-paths = ${cluster:extra-paths}195extra-paths = ${cluster:extra-paths}
186scripts =196scripts =
187 test.cluster197 test.cluster
@@ -194,7 +204,10 @@
194 test.config=nose.core:TestProgram204 test.config=nose.core:TestProgram
195initialization =205initialization =
196 ${common:initialization}206 ${common:initialization}
197 sys.argv[1:1] = ["--where=etc/maas/templates/commissioning-user-data"]207 sys.argv[1:1] = [
208 "--where=etc/maas/templates/commissioning-user-data",
209 "--cover-package=snippets",
210 ]
198extra-paths = ${common:extra-paths}211extra-paths = ${common:extra-paths}
199scripts =212scripts =
200 test.config213 test.config
201214
=== modified file 'required-packages/dev'
--- required-packages/dev 2015-02-26 12:31:44 +0000
+++ required-packages/dev 2015-02-27 22:08:16 +0000
@@ -5,12 +5,15 @@
5firefox5firefox
6gjs6gjs
7ipython7ipython
8libjs-jquery
9libjs-jquery-hotkeys
8libjs-yui3-full10libjs-yui3-full
9make11make
10nodejs-legacy12nodejs-legacy
11npm13npm
12pep814pep8
13pyflakes15pyflakes
16python-coverage
14python-extras17python-extras
15python-fixtures18python-fixtures
16python-flake819python-flake8