A new syntax for writing tests

Jean-Michel Pichavant jeanmichel at sequans.com
Thu Aug 5 11:17:05 CEST 2010

Jonathan Fine wrote:
> Hi
> I just discovered today a new syntax for writing tests.  The basic 
> idea is to write a function that contains some statements, and run it 
> via a decorator.  I wonder if anyone had seen this pattern before, and 
> how you feel about it.  For myself, I quite like it.
> Let's suppose we want to test this trivial (of course) class.
>     class Adder(object):
>         def __init__(self):
>             self.value = 0
>         def plus(self, delta):
>             self.value += delta
> The test the class you need a runner.  In this case it is quite simple.
>     def runner(script, expect):
>         '''Create an adder, run script, expect value.'''
>         adder = Adder()
>         script(adder)
>         return adder.value
> We can now create (and run if we wish) a test.  To do this we write
>     @testit(runner, 4)
>     def whatever(a):
>         '''Two plus two is four.'''
>         a.plus(2)
>         a.plus(2)
> Depending on the exact value of the testit decorator (which in the end 
> is up to you) we can store the test, or execute it immediately, or do 
> something else.
> The simplest implementation prints:
>     OK: Two plus two is four.
> for this passing test, and
>     Fail: Two plus four is five.
>       expect 5
>       actual 6
> for a test that fails.
> Here is the testit decorator used to produce the above output:
>     def testit(runner, expect):
>         '''Test statements decorator.'''
>         def next(script):
>             actual = runner(script, expect)
>             if actual == expect:
>                 print 'OK:', script.__doc__
>             else:
>                 print 'Fail:', script.__doc__
>                 print '  expect', expect
>                 print '  actual', actual
>         return next
> You can pick this code, for at least the next 30 days, at
>     http://dpaste.com/hold/225056/
> For me the key benefit is that writing the test is really easy.  
> Here's a test I wrote earlier today.
> @testit(runner, '''<a att="value"><b/></a>''')
> def whatever(tb):
>     tb.start('a', {'att': 'value'})
>     tb.start('b')
>     tb.end('b')
>     tb.end('a')
> If the test has a set-up and tear-down, this can be handled in the 
> runner, as can the test script raising an expected or unexpected 
> exception.

"The unittest module provides a rich set of tools for constructing and 
running tests. This section demonstrates that a small subset of the 
tools suffice to meet the needs of most users."


As you can see, a much more featured test framework already exists.

There's nothing wrong in a new test framework, but it has to be better 
than the existing one in some situations.


More information about the Python-list mailing list