from IPython.core.magic import register_line_magic @register_line_magic def runtests(line): import collections import time ip = get_ipython() tests = {} # search will only find things with __call__ methods (e.g. functions) for k, v in ip.user_ns.iteritems(): if k.startswith('test') and isinstance(v, collections.Callable): tests[k] = v print 'Collected {} tests.\n'.format(len(tests)) ok = 0 fail = {} error = {} t1 = time.time() for name, func in tests.iteritems(): print '{} ... '.format(name), try: func() except AssertionError as e: print 'fail' fail[name] = e except Exception as e: print 'error' error[name] = e else: print 'ok' ok += 1 t2 = time.time() if fail: print '' print 'Failures' print '========' for name, e in fail.iteritems(): print '{}: {}'.format(name, repr(e)) if error: print '' print 'Errors' print '======' for name, e in error.iteritems(): print '{}: {}'.format(name, repr(e)) print '' print 'Ran {} tests in {:.3g} seconds.'.format(len(tests), t2 - t1) print 'ok = {}, fail = {}, error = {}'.format(ok, len(fail), len(error)) def test_something(): assert True def test_fail(): assert 4 == 2, '4 != 2' def test_error(): raise ValueError('Sorry!') %runtests