Skip to content

Instantly share code, notes, and snippets.

@mgedmin
Last active December 15, 2015 05:59
Show Gist options
  • Save mgedmin/5213342 to your computer and use it in GitHub Desktop.
Save mgedmin/5213342 to your computer and use it in GitHub Desktop.
Hack to plot number of failing tests while working

I was trying to see how hard it would be to port Paste to Python 3.

Paste uses nose. nosetests prints something like

FAILED (errors=90, failures=5)                                                   

at the end of the test run. I wanted to plot the number of failures to see how I was progressing:

./run32
vi ...
./run32
vi ...
./run32
./plot

"plot"

You see the number of failures increasing initially, since fixing an ImportError lets nose try to run more and more tests, and some of those, unsurprisingly, fail.

My test run script (run33):

#!/bin/sh
savelog -l -q -c 100 .testoutput
tox -e py33 2>&1 | tee .testoutput
grep -a '^\(ERROR:\|FAIL:\|FAILED\)' .testoutput
less .testoutput

it uses tox, which is awesome, with this trivial tox.ini:

[tox]
envlist = py26,py27

[testenv]
deps = nose
commands = nosetests

And here's the horrible plot script:

#!/usr/bin/python
import glob, re, subprocess
files = glob.glob('.testoutput*')
age = {fn: -1 if fn == '.testoutput' else int(fn.split('.')[-1])
       for fn in files if fn == '.testoutput' or fn.split('.')[-1].isdigit()}
files.sort(key=age.get, reverse=True)
failures = {}
rx = re.compile(r'^FAILED \(errors=(\d+), failures=(\d+)\)$', re.MULTILINE)
max_errors = 120
with open('.plot', 'w') as p:
    for fn in files:
        with open(fn) as f:
            for line in f:
                m = rx.match(line)
                if m:
                    errors, failures = [int(g) for g in m.groups()]
                    p.write('%d %d %d\n' % (errors, failures, errors+failures))
                    max_errors = max(max_errors, errors+failures)
p = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
p.stdin.write('set xr [0:%d]\n' % len(files))
p.stdin.write('set yr [0:%d]\n' % max_errors)
p.stdin.write('set style fill solid\n')
p.stdin.write('set xlabel "Runs"\n')
p.stdin.write('plot ".plot" using 3 title "Failing tests" with boxes\n')
p.stdin.flush()
p.wait() # have to ^C it :(

I used gnuplot because I didn't want to muck about with installing matplotlib in a virtualenv or something. I kind of regret that now, because gnuplot is not very friendly. I should've just apt-get installed python-matplotlib, I think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment