[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