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 <mar...@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 _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor