William Troup
William Troup

Reputation: 13131

Get python unit test duration in seconds

Is there any way to get the total amount of time that "unittest.TextTestRunner().run()" has taken to run a specific unit test.

I'm using a for loop to test modules against certain scenarios (some having to be used and some not, so they run a few times), and I would like to print the total time it has taken to run all the tests.

Any help would be greatly appreciated.

Upvotes: 11

Views: 10756

Answers (5)

fish2000
fish2000

Reputation: 4435

I do this exactly as Eric postulated -- here's a decorator I use for tests (often more functional-test-y than strict unit tests)...

# -*- coding: utf-8 -*-
from __future__ import print_function
from functools import wraps
from pprint import pprint

WIDTH = 60

print_separator = lambda fill='-', width=WIDTH: print(fill * width)

def timedtest(function):
    """
    Functions so decorated will print the time they took to execute.

    Usage:

        import unittest

        class MyTests(unittest.TestCase):

            @timedtest
            def test_something(self):
                assert something is something_else
                # … etc

                # An optional return value is pretty-printed,
                # along with the timing values:
                return another_thing

    """
    @wraps(function)
    def wrapper(*args, **kwargs):
        print()
        print("TESTING: %s(…)" % getattr(function, "__name__", "<unnamed>"))
        print_separator()

        print()
        t1 = time.time()
        out = function(*args, **kwargs)
        t2 = time.time()
        dt = str((t2 - t1) * 1.00)
        dtout = dt[:(dt.find(".") + 4)]
        print_separator()

        if out is not None:
            print('RESULTS:')
            pprint(out, indent=4)

        print('Test finished in %s seconds' % dtout)
        print_separator('=')

        return out

    return wrapper

That's the core of it -- from there, if you want, you can stash the times in a database for analysis, or draw graphs, et cetera. A decorator like this (using @wraps(…) from the functools module) won't interfere with any of the dark magic that unit-test frameworks occasionally resort to.

Upvotes: 3

gabra
gabra

Reputation: 10544

Besides using datetime, you could also use time

from time import time

t0 = time()

# do your stuff here

print(time() - t0) # it will show in seconds

Upvotes: 1

Zaur Nasibov
Zaur Nasibov

Reputation: 22659

UPDATED, thanks to @Centralniak's comment.

How about simple

from datetime import datetime

tick = datetime.now()

# run the tests here   

tock = datetime.now()   
diff = tock - tick    # the result is a datetime.timedelta object
print(diff.total_seconds())

Upvotes: 13

icedwater
icedwater

Reputation: 4887

Following Eric's one-line answer I have a little snippet I work with here:

from datetime import datetime

class SomeTests(unittest.TestCase):
    """
    ... write the rest yourself! ...
    """

    def setUp(self):
        self.tick = datetime.now()

    def tearDown(self):
        self.tock = datetime.now()
        diff = self.tock - self.tick
        print (diff.microseconds / 1000), "ms"

    # all the other tests below

This works fine enough for me, for now, but I want to fix some minor formatting issues. The result ok is now on the next line, and FAIL has priority. This is ugly.

Upvotes: 3

Eric
Eric

Reputation: 3172

You could record start time in the setup function and then print elapsed time in cleanup.

Upvotes: 4

Related Questions