[Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"
boB Stepp
robertvstepp at gmail.com
Sun Apr 16 23:16:15 EDT 2017
Thank you very much Martin; you filled in a lot of details. I had an
overall understanding of what unittest does, but you have now enhanced
that understanding substantially. I'm still iffy on how the mixin
class gets its test method called when this class does not subclass
from unittest.TestCase, but I think I may have an idea now on how it
is happening. Let's get to that part of your response.
On Sun, Apr 16, 2017 at 3:59 PM, Martin A. Brown <martin at linux-ip.net> wrote:
[snip]
> Your next question is why do the mixins work? And how do they work?
>
> I'll make a few observations:
>
> - [on unittest] the unit testing tools use classes because it's a
> natural way to accommodate the goal of reproducibly setting up
> arguments and/or an environment for each test (note that each
> TestCase can have its own setUp() and tearDown() methods; this
> allows isolation)
>
> - [on unittest] each test collected by the TestLoader can be any
> Python class (as long as it is also derived from
> unittest.TestCase)
>
> - [on your classes] your classes use a multiple inheritance
> model, deriving from TestFuncAcceptsSequencesMixin; when
> instantiated, they'll have all of the expected TestCase methods
> and the method called 'test_func'
It is here that I am struggling. If the mixin class does not inherit
from unittest.TestCase, then how is test_func ever seen?
> In more detail, you have created three different classes, each of
> which is derived from unittest.TestCase (I'm showing just the
> signatures):
>
> class AcceptLists(TestFuncAcceptsSequencesMixin, unittest.TestCase):
> class AcceptStrings(TestFuncAcceptsSequencesMixin, unittest.TestCase):
> class AcceptTuples(TestFuncAcceptsSequencesMixin, unittest.TestCase):
>
> Here's what's happening:
>
> - TestLoader finds the files that contains the above classes (probably
> named 'test_something.py')
>
> - Testloader imports the file 'test_something.py'; this defines your
> classes: AcceptLists, AcceptStrings and AcceptTuples (or will
> produce a traceback if the code does not import; try breaking
> your code and you should see that the import of your test code
> fails during the TestLoader phase)
>
> - TestLoader appends the now-defined classes: AcceptLists,
> AcceptStrings and AcceptTuples to the list of tests
>
> - control passes back to main and then to TestRunner
>
> - for each unittest.TestCase in the list of tests, TestRunner will:
>
> - create an instance T from the defined class
This answers one important thing I was wondering about: How do the
classes AcceptLists, AcceptStrings, and AcceptTuples get instantiated?
Apparently the unittest machinery does this for me.
> - for each method name starting with 'test_' (you have only
> 'test_func') TestRunner will:
And here is my precise sticking point: How does the TestRunner find
test_func? The classes it has collected and instantiated
(AcceptLists, AcceptStrings and AcceptTuples) do not themselves call
and make use of the test_func method they inherit from the mixin
class.
> - execute the T.setUp() method if it exists
>
> - TestRunner will execute the method 'test_func'
The only thing that makes sense to me is that the TestRunner follows
the MRO of the inherited classes and checks for any test_xxx methods
that might exist in those superclasses. Is this correct or do I have
a conceptual misunderstanding?
> - collect the success / failure and any outputs
>
> - report on the success / failure
>
> - produce some final summary output and set the exit code
> accordingly (os.EX_OK means success, anything else is failure)
>
[snip]
> I hope my long-winded explanation amkes that a bit clearer.
More clarity has been achieved, but I am not fully there yet!
Thanks!
--
boB
More information about the Tutor
mailing list