testing is easier in python

John Ochiltree jo at johnochiltree.uklinux.net
Sat Feb 1 09:45:22 CET 2003

Geoff Gerrietts wrote:
> Quoting Michael Hudson (mwh at python.net):
>>Subject: Re: Python Success Stories or Nightmares
> [...]
>>Geoff Gerrietts <geoff at gerrietts.net> writes:
>>>Good stuff:
>>>- Unit tests are amazingly easy to write, since you can "stub in"
>>>  dependencies in lots of different ways.
>>I recently got smacked in the face (in a good way) by this one, so I
>>thought I'd quote it in isolation to make sure everyone read it.
> I think it's worth explaining, too, but I'm not sure this is the
> thread to do it in, so I'm changing the subject line. It's worth
> explaining because I've seen the topic of unit tests come up in other
> threads, and I saw someone make the claim that testing is
> a language-neutral solution. I don't believe that. Here's why.
> I've written unit tests for Java, C, and C++ programs before. Perhaps
> ironically, the C and C++ versions are probably easier to write than
> the Java versions. None of the three are particularly easy to write,
> though. Python makes writing unit tests easy.
> When you sit down to write a unit test, you hafta look at what the
> software you're trying to test, does. Sometimes, it's a pretty simple
> transformation. That is, arguments go in, and outputs come out. The
> only other impacting factor might be state that is internal to your
> object, which you can presumably control.
>   arguments --> [ big black box of code ] --> output
> In the more interesting case, though, your code has additional
> external dependencies. An easy example is a reliance on time.time().
>   arguments --> [ big black box of code ] --> output
>                    |              ^
>                    v              |
>                 [ external lump of code ]
> Now, in a testing situation, you must manage the inputs and outputs of
> the external code as well as the arguments. You may be able to
> envision several ways of doing this in Java or C++; the most typical
> method I have seen is to create a facade object that can detect
> whether you are in "test mode" or "deployment mode". In "test mode",
> the facade returns a constant. In "deployment mode" it returns the
> result of the actual system call.
> This solution leaves a few things to be desired: it doesn't allow for
> different tests wanting different constants, it adds logic to the
> app-as-built, etcetera.
> In Python, you can also do this, if you're the sort who likes that
> kind of bondage. But Python's more flexible than that: you can also
> just "replace" time.time with a stub that does the right thing.
>   import my_module_to_be_tested
>   my_module_to_be_tested.time.time = my_stub
> Now, this does have some consequence, since it's changing time.time
> for everyone. But if that's going to pickle your gizzard, you can opt
> instead to write a local testing_time module, with stubs you can swap
> at your leisure, and re-assign my_module_to_be_tested.time instead:
> safer, with only incrementally more trouble.
> In the C and C++ worlds, you can accomplish something like this by
> choosing how you link your applications. It's not as elegant, not as
> easy, and not as powerful, but it can be done. I am not aware of how
> you can do this in Java without sacrificing the practicality of the
> test environment.
> Once this idiom has been mastered, applications spring up everywhere.
> Now, you're not likely to want to (or /need/ to) do this in your
> production code (though the timeoutsocket library uses a similar
> trick), but when you're building tests or other meta-applications,
> it's remarkably powerful.
> Thanks,
> --G.

As an aside, the real power of the unittest module (or junit, or cppunit 
depending on your language) comes when you adopt Kent Beck's development 
  technique. Write the test first. This will fail. Write enough code for 
the test to pass. Refactor the code. Move onto the next bit of 
functionality. (This is only a small part of XP BTW)


More information about the Python-list mailing list