[TIP] unittest/mock question

Marius Gedminas marius at gedmin.as
Mon Sep 16 03:58:03 PDT 2013


On Fri, Sep 13, 2013 at 04:26:25PM -0700, Christine Jones wrote:
> I've just started using Python unittest and mock. I've gone through
> the three Michael Foord tutorials, and read the docs, however, I
> cannot figure my way around this issue.
> 
> I am using Python 2.6 and mock 1.0.1.
> 
> I have the following function and tests. In brief, I am not able to
> test both branches of my if/else statement unless I comment out one or
> the other tests. Specifically, if I run both tests below only the last
> one passes. However, if I comment out the last one, the first one runs
> and passes. 
> 
> I was under the impression that patch automatically unmonkey patches
> when the context or function is left but it seems like maybe this is
> not happening. Or I am missing some other key concept. Any help would
> be greatly appreciated. Thank you in advance!
> 
> Christine
> 
> 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()

What ORM is this?  It may matter.

>    player_count = players.__len__()

That's an unusual spelling of

     player_count = len(players)

>    if player_count > 1:
>        return render_template("signups_today.html", signups=players)
>    else:
>        return render_template("signups_today.html")
> 
> Test for if branch:
> ======================
> # READ - GET signups - 200 (assumes > 0 signups)       
>    def test_signups_get(self):
>        today = datetime.datetime.now()
>        from lunchlottoweb import models
>        with patch.object(models, "LottoPlayer"):

I think you're supposed to do

         with patch.object(models, "LottoPlayer") as LottoPlayer:

here.  Not 100% sure.

>           players = [NonCallableMock(employeelogin='cjjones', employeedept='systems', signupdate=today, lottowinner=False),
>                      NonCallableMock(employeelogin='dlovirin', employeedept='systems', signupdate=today, lottowinner=False)]
>           LottoPlayer.all = players

Because if you don't, then you're modifying some global object, but I
don't see where it came from.

>           request = MagicMock(name='signups_multiple_exist')
>           r = self.app.get('/signups')
>           assert 'cjjones' in r.data
> 
> Test for else branch:
> ======================
>    # READ - GET signups when there are 0 signups
>    def test_signups_get_when_none(self):
>        now = datetime.datetime.now()
>        yesterday = now - datetime.timedelta(days = 1)
>        from lunchlottoweb import models
>        with patch.object(models, 'LottoPlayer'):

Same here

>            players = [NonCallableMock(employeelogin='jshmo', employeedept='systems', signupdate=yesterday, lottowinner=False), 
>                      NonCallableMock(employeelogin='foo', employeedept='systems', signupdate=yesterday, lottowinner=False)]
>            LottoPlayer.all = players

But then again at the moment you're modifying the same global object
from both tests, so I don't quite understand what is happening...

Perhaps the ORM layer caches something?

>            request = MagicMock(name='signupsrequest')
>            r = self.app.get('/signups')
>            assert 'No one has signed up yet' in r.data

Marius Gedminas
-- 
11. Are you at least tracking the number of users of retchmail?

As far as I know, retchmail has exactly three users.
	-- http://alumnit.ca/wiki/index.php?page=RetchMail
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: Digital signature
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20130916/56e2c2f8/attachment.pgp>


More information about the testing-in-python mailing list