A new syntax for writing tests

jfine jonathan.fine1 at googlemail.com
Thu Aug 5 17:06:03 CEST 2010


On 5 Aug, 14:52, Jean-Michel Pichavant <jeanmic... at sequans.com> wrote:
> jfine wrote:
> > On 5 Aug, 10:17, Jean-Michel Pichavant <jeanmic... at sequans.com> wrote:
>
> >> Jonathan Fine wrote:
>
> >>> Hi
>
> >>> I just discovered today anewsyntaxfor 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.
>
> >> Hi,
>
> >> "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."
>
> >> sourcehttp://docs.python.org/library/unittest.html
>
> >> As you can see, a much more featured test framework already exists.
>
> >> There's nothing wrong in anewtest framework, but it has to be better
> >> than the existing one in some situations.
>
> > Chalk and cheese.
>
> > My concern is to make tests easy to write, and that is something that
> > unittest is, in my view, not good at.  It is, as you say, a *test
> > framework*.
>
> > I've not written a test framework.  I've found what seems to be anew
> > *syntax* for writing tests.  Tests written in thenewsyntaxcan be
> > run in the unittest (or any other) framework.
>
> > --
> > Jonathan
>
> Well, I never used unittest, but the given example in the doc is pretty
> much simple.
> I'm still scratching my head.

I think you'd understand better if you used unittest.  For example,
try coding my test (with say 10 distinct tests of a class more
complicated than Adder) using unittest.  I think you'll see the point
when you get to number 5.

Here, for reference, is my complete code for one test.  See how it
scales.
         http://dpaste.com/hold/225056/  (available for at least 30
days).

--
Jonathan




More information about the Python-list mailing list