[ANN] Metatest 0.1.0

Jonathan Fine jfine at pytex.org
Wed Sep 19 02:38:07 EDT 2007


Ben Finney wrote:
> [Jonathan, please don't send me copies of messages sent to the
> discussion thread. I follow comp.lang.python via a non-mail interface,
> and it's irritating to get unwanted copies of messages via email.]

[Thank you for letting me know your preference.  For myself, I often 
appreciate it when people send me a copy directly.]

>>The line
>>     plus(2, '', _ex=TypeError)
>>causes something to be recorded,

<snip>

> That's confusing, then, for two reasons:
> 
> It looks like '_ex' is an argument to the 'plus' function, which
> otherwise (probably by design) looks exactly like a call to the 'plus'
> function the programmer is testing. 

Actually, 'plus' above is an instance of a class (which for now we will 
call PyUnknown) that has a __call__ method.  We know this because we 
imported it from metaclass.py.mymod.

It is, if you like, a /test surrogate/ or /instrumented wrapper/ for the 
function 'plus' in mymod.  And as such it has different properties.  For 
example, the '_ex' parameter has a special significance.

> Since this is, instead, an
> assertion *about* that function, it is misleading to see it as an
> argument *to* the function.

Although, by design, it looks like an argument to 'plus' in mymod, it is 
  as I said an argument to 'plus' in metatest.py.mymod, which is 
something completely different, namely a PyUnknown object.

We can think of test-first programming as
1.  Stating the problem to be solved.
2.  Solving that problem.

In mathematics, we often use unknowns when stating problems.  We can 
think of a PyUnknown as being analogous, in programming, to the unknowns 
we use in mathematics.

However, if the difference confuses one (and it can in some situations), 
then instead do
     from metatest.py.mymod import plus as mt_plus
and then the confusing line becomes
     mt_plus(2, '', _ex=TypeError)
which I think you will find much clearer.

> It uses the "leading-underscore" convention which means "this is not
> part of the public interface, and you'd better know what you're doing
> if you use this externally".

This convention is exactly that, a convention.  Conventions allow us to 
communicate efficiently, without spelling everything out.  Implicit in 
metatest are some other conventions or the like.  Oh, and this use of 
metatest does confirm to the convention, and extra knowledge is required 
to use leading underscore parameters.

>>Finally, if you can think of a better way of saying, in Python, "The
>>function call plus(2, '') raises a TypeError", please let me know,
>>and I'll consider using it in the next version of Metatest.
>  
> I would think an explicit function call that says what it's doing
> would be better. The unittest module implements this as:
> 
>     self.failUnlessRaises(TypeError, plus, 2, '')
<snip>
> which has the benefit of being explicit about what it's doing.

Well, you did not tell me what self is (althout I guessed it is an 
instance of a subclass of unittest.TestCase).  Nor did you tell me that 
this statement is part of a class method.

To my eye, your example puts the focus on failUnlessRaises and on 
TypeError.  I think the metatest way puts an equal focus on calling 
plus(2, '') and the result of this call.

I give a comparison of three ways of writing tests in my slides:
    http://metatest.sourceforge.net/doc/pyconuk2007/metatest.html#slide13

To summarise:  both metatest and unittest require the user to know 
something.  Once that something is known, the choices for the crucial 
test line are
     plus(2, '', _ex=TypeError)
     self.failUnlessRaises(TypeError, plus, 2, '')

I hope you know find the first option less confusing.  (It certainly is 
shorter.)

-- 
Jonathan




More information about the Python-list mailing list