[TIP] mock object not being used?

Ben Finney ben+python at benfinney.id.au
Wed Sep 18 20:34:51 PDT 2013


Christine Jones <cjjones at pixar.com> writes:

>

I have some comments on your style that will hopefully make your code
more maintainable.

> # READ - GET signups - 200 (assumes > 0 signups)
>     def test_signups_get(self):

Each test case (that is, each function in a unit test) should be named
for the single assertion it is making about the code. That way, the name
of the failed test says exactly what expected behaviour was not
satisfied.

Yes, this entails that *separate assertions need to be in separate test
cases* (i.e. in separate ‘test_foo’ functions), to ensure that they can
pass or fail independently. You may already be doing this; if not, early
is better to learn than later.

In this case, you're asserting that the result contains “cjjones” in the
data. To name the test case, we need to describe what the semantic
meaning of this behaviour is. Perhaps “The data should contain the first
player's username”::

    def test_data_contains_username_of_first_player(self):
        """ The data should contain the first player's username. """

(I like to write the docstring as an admonition; that way, it makes
sense when it appears in the test report, regardless of whether the test
passes or fails.)

>       today = datetime.datetime.now()
>       from lunchlottoweb import models

Don't import like this inside a function. Instead, import the necessary
modules at the top of your unit test module.

>       with patch.object(models, "LottoPlayer") as MockLottoPlayer:
>          players = [NonCallableMock(employeelogin='cjjones', employeedept='systems', signupdate=today, lottowinner=False),
>                     NonCallableMock(employeelogin='dlovrn', employeedept='systems', signupdate=today, lottowinner=False)]

If you want to make use of these instances for numerous test cases –
which I advise – then use the ‘setUp’ method of the TestCase classes to
set a test data attribute on each test case.

>          MockLottoPlayer.all = players
>          request = MagicMock(name='signups_multiple_exist')
>          r = self.app.get('/signups')
>          assert 'cjjones' in r.data
>
> My function:
> ======================
> # admin page: today's signups
> @app.route('/signups', methods=['GET'])
> def signups():
>   today = date.today()
>   players = LottoPlayer.query.filter(cast(LottoPlayer.signupdate, Date) == today).distinct(LottoPlayer.employeelogin).all()
>   player_count = players.__len__()
>   if player_count > 1:

There's no need to call this magic method directly. Instead, use the
built-in ‘len’ function::

    if len(players) > 1:

>       return render_template("signups_today.html", signups=players)
>   else:
>       return render_template("signups_today.html")

-- 
 \           “People are very open-minded about new things, as long as |
  `\         they're exactly like the old ones.” —Charles F. Kettering |
_o__)                                                                  |
Ben Finney




More information about the testing-in-python mailing list