Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing applications Django with py.test (Django Stockholm meetup)

Testing applications Django with py.test (Django Stockholm meetup)

Slides for a talk that was given at the Django Stockholm meetup 2013-04-29.

Andreas Pelme

April 29, 2013
Tweet

More Decks by Andreas Pelme

Other Decks in Programming

Transcript

  1. QZUFTU w (FOFSBMQVSQPTF1ZUIPOUFTUJOHUPPM w 6TFECZ1Z1Z .P[JMMB TJY 4FOUSZ  w

    *OOPWBUJWFGFBUVSFT pYUVSFT QPXFSGVMQMVHJO TZTUFN w -PUTPGFYJTUJOHQMVHJOT w $PWFSBHF EJTUSJCVUFEUFTUJOH 1&1DIFDLJOH w %KBOHPQMVHJOQZUFTUEKBOHP w 8SJUFUFTUTJOBQZUIPOJDTUZMF
  2. QZUFTUUFTUTUZMF def  greeter(name):        return  'Hello  %s!'  %

     name def  test_greeter():        assert  greeter('Andreas')  ==  'Hello  Andreas'
  3. QZUFTUEKBOHP w *OUFHSBUFTQZUFTUBOE%KBOHP w .BOBHFTUIFUFTUEBUBCBTF w "MMPXTEBUBCBTFSFVTF w 1SPWJEFT%KBOHPUFTUIFMQFSTJOBQZUFTUXBZ w

    $IBOHJOHPGTFUUJOHT w -JWF4FSWFS w VSMDPOGPWFSSJEFT w *OWPLFEWJBpy.testOPUmanage.py  test
  4. QZUFTUEKBOHPTFUVQ w pip  install  pytest-­‐django   w 3FRVJSFTZPVSDPEFUPCFPO1ZUIPOQBUI w add2virtualenv

     your/project/directory w $POpHVSFTFUUJOHT w 4FUDJANGO_SETTINGS_MODULEJOZPVSTIFMM w 03DSFBUFQZUFTUJOJBOETFU DJANGO_SETTINGS_MODULE=mysettings w #POVT3VO1ZUIPOTIFMMEJSFDUMZXJUIpython
  5. 8IFSFUPQVUUFTUT w #ZEFGBVMUBOZpMFUIBUNBUDIFTtest_*.py w 5FTUEJTDPWFSZJTDPOpHVSBCMF w 4FUpython_files  =  *.pyJOQZUFTUJOJ w

    5FTUTJOBQQEJSFDUPSZ w BQQUFTUTWJFXTQZ w 5FTUTJOTFQBSBUFEJSFDUPSZ w VOJU@UFTUTBQQWJFXTQZ w JOUFHSBUJPO@UFTUTUFTU@TPNFUIJOHQZ w %FQFOETPOZPVSQSPKFDU
  6. )PXUPSVOUFTUT #  run  all  tests $  py.test #  run  a

     specific  file $  py.test  tests/app/test_views.py #  run  test  which  matches  tests  named  *test_foo* $  py.test  tests/app/test_views.py  -­‐k  test_foo #  run  all  non  database  tests  (more  on  this  later) $  py.test  tests/app  -­‐m  'not  django_db'
  7. 5FTUBCMF%KBOHPDPEF w %BUBCBTFBDDFTTNBLFTUFTUTTMPX w %KBOHP`T03.BOENPEFMTJTHSFBU w 5IFEJTUJODUJPOCFUXFFORVFSZDPEFBOE BQQMJDBUJPODPEFDBOCFCMVSSZ w 1VURVFSZDPEFJONBOBHFSNFUIPET

    w 5FTUUIPTFXJUIUIFSFBMEBUBCBTF w 1VUBQQMJDBUJPOMPHJDJONFUIPETXIJDIEPFTOPU UIFRVFSZUIFEBUBCBTF w 4UVCCJOHNPDLJOHDBOIFMQXJUIJTPMBUJPO
  8. %BUBCBTFVTBHF import  pytest def  test_without_db_access():        #  any

     db  accesses  will  raise  an  error        pass @pytest.mark.django_db def  test_with_db_access():        #  test  db  is  available        pass
  9. %BUBCBTFVTBHF import  pytest #  Allow  all  tests  in  this  module

     database  access pytestmark  =  pytest.mark.django_db def  test_with_db_access_1():        pass def  test_with_db_access_2():        pass def  test_with_db_access_3():        pass
  10. 5FTUEBUBCBTFSFVTF w 5FTUTTIPVMESVOBHBJOTUUIFSFBMEBUBCBTF w 5BCMFDSFBUJPOUBLFTUJNF w QZUFTUEKBOHPQSPWJEFTUIF-­‐-­‐reuse-­‐dbPQUJPO w 1VUaddopts  =

     -­‐-­‐reuse-­‐dbJOQZUFTUJOJ w 1FSTJTUUIFUFTUEBUBCBTFCFUXFFOSVOT w 8IFOVTJOH-­‐-­‐reuse-­‐db QBTT-­‐-­‐create-­‐dbUP GPSDFSFDSFBUJPOPGUIFEBUBCBTF
  11. %KBOHPUFTUpYUVSFT [ { "model": "myapp.person", "pk": 1, "fields": { "first_name":

    "John", "last_name": "Lennon" } }, { "model": "myapp.person", "pk": 2, "fields": { "first_name": "Paul", "last_name": "McCartney" } } ]
  12. GBDUPSZ@CPZFYBNQMF #  models.py from  django.db  import  models class  Group(models.Model):  

         name  =  models.TextField() class  Person(models.Model):        first_name  =  models.TextField()        last_name  =  models.TextField()        group  =  models.ForeignKey(Group)        def  group_letter(self):                return  self.group.name[0].upper()        def  full_name(self):                return  '%s  %s'  %  (self.first_name,                                                    self.last_name) #  factories.py import  factory from  app.models  import  Person,  Group class  GroupFactory(factory.Factory):        FACTORY_FOR  =  Group        name  =  'Developers' class  PersonFactory(factory.Factory):        FACTORY_FOR  =  Person        first_name  =  'John'        last_name  =  'Doe'        group  =  factory.SubFactory(GroupFactory)
  13. GBDUPSZ@CPZFYBNQMF from  factories  import  PersonFactory def  test_full_name():      

     person  =  PersonFactory.build(first_name='Andreas',                                                                  last_name='Pelme')        assert  person.full_name()  ==  'Andreas  Pelme' def  test_group_letter():        person  =  PersonFactory.build(group__name='admins')        assert  person.group_letter()  ==  'A'
  14. QZUFTUpYUVSFT import  pytest from  my_module  import  MyClass @pytest.fixture def  my_object():

           return  MyClass() def  test_foo(my_object):        assert  my_object.foo()  ==  'foo' def  test_bar(my_object):        assert  my_object.bar()  ==  'bar'
  15. QZUFTUEKBOHPpYUVSFT def  test_changing_settings(settings):        settings.DATE_FORMAT  =  'Y-­‐m-­‐d'  

         #  call  code  that  uses  settings.DATE_FORMAT  ...          #  the  settings  will  be  automatically  reset  after  this  test def  test_with_testclient(client):        #  client  is  an  instance  of  Django's  TestClient,  just  like        #  self.client  in  a  Django  TestCase        response  =  client.get('/foo/bar')        assert  response.status_code  ==  200
  16. 'BDUPSZ pYUVSFT import  pytest from  factories  import  PersonFactory @pytest.fixture def

     person():        return  PersonFactory.build() def  test_with_person(person):        #  Test  something  on  the  Person  object        pass
  17. 'BDUPSZ pYUVSFT import  pytest from  factories  import  UserFactory @pytest.fixture def

     user_in_db(db):        #  The  db  argument  makes  database  access  allowed        return  UserFactory.create() @pytest.mark.django_db def  test_with_saved_user(user_in_db):        #  user_in_db  is  a  saved  user        pass
  18. (SFBUSFTPVSDFT w )PMHFS,SFLFM QZUFTU 1Z$PO w *OUSPEVDUJPOUPQZUFTU TIPXTQZUFTUGFBUVSFTJOEFQUI w IUUQXXXZPVUVCFDPNXBUDI

    W-7R#2D'NZX w $BSM.FZFS 5FTUJOHBOE%KBOHP 1Z$PO w "MPUPG%KBOHPUFTUJOHCFTUQSBDUJDFT w IUUQXXXZPVUVCFDPNXBUDI WJDL/2D/9J4 w QZUFTUEPDVNFOUBUJPO w IUUQQZUFTUPSH w QZUFTUEKBOHPEPDVNFOUBUJPO w IUUQQZUFTUEKBOHPSFBEUIFEPDTPSH