unittest weirdness

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Mar 13 00:38:56 CET 2014

On Tue, 11 Mar 2014 13:58:17 -0700, Ethan Furman wrote:

> class Test_wfbrp_20140225(TestCase):
>      @classmethod
>      def setUpClass(cls):
>          cls.pp = wfbrp.PaymentProcessor(
>              '.../lockbox_file',
>              '.../aging_file',
>              [
>                  Path('month_end_1'),
>                  Path('month_end_2'),
>                  Path('month_end_3'),
>                  ],
>              )

This has nothing to do with your actual problem, which appears to be the 
Linux(?) OOM killer reaping your applications, just some general 
observations on your test.

>      def test_xxx_1(self):

Having trouble thinking up descriptive names for the test? That's a sign 
that the test might be doing too much. Each test should check one self-
contained thing. That may or may not be a single call to a unittest 
assert* method, but it should be something you can describe in a few 

"it's a regression test for bug 23"
"test that the database isn't on fire"
"invoices should have a valid debtor"
"the foo report ought to report all the foos"
"...and nothing but the foos."

This hints -- its just a hint, mind you, since I lack all specific 
knowledge of your application -- that the following "affirm" tests should 
be pulled out into separate tests.

>          p = self.pp.lockbox_payments[0]
>          # affirm we have what we're expecting 
>          self.assertEqual(
>                  (p.payer, p.ck_num, p.credit),
>                  ('a customer', '010101', 10000),
>                  )
>          self.assertEqual(p.invoices.keys(), ['XXXXXXXXXXX'])
>          self.assertEqual(p.invoices.values()[0].amount, 10000)

which would then leave this to be the Actual Thing Being Tested for this 
test, which then becomes test_no_missing_invoices rather than test_xxx_1.

>          # now make sure we get back what we're expecting 
>          np, b = self.pp._match_invoices(p)
>          missing = []
>          for inv_num in ('123456', '789012', '345678'):
>              if inv_num not in b:
>                  missing.append(inv_num)
>          if missing:
>              raise ValueError('invoices %r missing from batch' %
>              missing)

Raising an exception directly inside the test function should only occur 
if the test function is buggy. As Terry has already suggested, this 
probably communicates your intention much better:

    self.assertEqual(missing, [])

Steven D'Aprano

More information about the Python-list mailing list