Testing Django applications with py.test (EuroPython 2013)

Testing Django applications with py.test (EuroPython 2013)

0aa514c079b74c6655e6a8bf1073c878?s=128

Andreas Pelme

July 05, 2013
Tweet

Transcript

  1. 5FTUJOH%KBOHPBQQMJDBUJPOT XJUI QZUFTU "OESFBT1FMNF BOESFBT!QFMNFTF !BOESFBTQFMNF personalkollen fredag 5 juli

    13
  2. 5PQJDT w5FTUJOHJO%KBOHP wQZUFTU w%KBOHPBOEQZUFTU w%KBOHPUFTUJOHUJQTUSJDLT fredag 5 juli 13

  3. 5FTUJOHJO%KBOHP fredag 5 juli 13

  4. %KBOHP`TUFTUJOH EPDVNFOUBUJPO fredag 5 juli 13

  5. %KBOHPEPDVNFOUBUJPO l*GZPV`WFCFFOVTJOH1ZUIPO GPSBXIJMF EPDUFTUXJMM QSPCBCMZGFFMNPSF lQZUIPOJDzz fredag 5 juli 13

  6. %KBOHP`TUFTUJOH EPDVNFOUBUJPO fredag 5 juli 13

  7. fredag 5 juli 13

  8. %KBOHP`TUFTUSVOOFS fredag 5 juli 13

  9. *UJTHFUUJOHCFUUFS Photo: http://www.flickr.com/photos/bee/3290452839/ fredag 5 juli 13

  10. 0UIFSUFTUJOHUPPMT OPTF UPY 5XJTUFE5SJBM [PQFUFTUSVOOFS fredag 5 juli 13

  11. BGVMMGFBUVSFE1ZUIPOUFTUJOHUPPM QZUFTU fredag 5 juli 13

  12. TJY .PJO.PJO fredag 5 juli 13

  13. 1MVHJOT w%JTUSJCVUFEQBSBMMFMJ[FE QZUFTUYEJTU w%KBOHP QZUFTUEKBOHP w-PHDBQUVSF QZUFTUDBQUVSFMPH w$PWFSBHFSFQPSUJOH QZUFTUDPW wBOENBOZNPSF

    fredag 5 juli 13
  14. XJUIPVUCPJMFSQMBUF 1ZUIPOJDUFTUT fredag 5 juli 13

  15. from  django.test  import  TestCase class  TestHelloWorld(TestCase):        def

     test_hello_world(self):                response  =  self.client.get('/hi/')                self.assertEqual(response.status_code,                                                  200)                self.assertEqual(response.content,                                                  'Hello  World!') fredag 5 juli 13
  16. def  test_hello_world(client):        response  =  client.get('/hi/')    

     assert  response.status_code  ==  200      assert  response.content  ==  'Hello  World!' fredag 5 juli 13
  17. def  test_hello_world(client):        response  =  client.get('/hi/')    

     assert  response.status_code  ==  200      assert  response.content  ==  'Hello  World!' fredag 5 juli 13
  18. $  py.test F ===================  FAILURES  ==================== _______________  test_hello_world  ________________ client

     =  <django.test.client.Client  object  at   0x1065f58d0>    def  test_hello_world(client):          response  =  client.get('/hi/')          assert  response.status_code  ==  200 >        assert  response.content  ==  'Hello  World!' E        assert  'Hello  EuroPython!'  ==  'Hello  World!' E            -­‐  Hello  EuroPython! E            +  Hello  World! test_hello_world.py:5:  AssertionError fredag 5 juli 13
  19. assertAlmostEqual assertAlmostEquals assertDictContainsSubset assertDictEqual assertEqual assertEquals assertFalse assertGreater assertGreaterEqual assertIn

    assertIs assertIsInstance assertIsNone assertIsNot assertIsNotNone assertItemsEqual assertLess assertLessEqual assertListEqual assertMultiLineEqual assertNotAlmostEqual assertNotAlmostEquals assertNotEqual assertNotEquals assertNotIn assertNotIsInstance assertNotRegexpMatches assertRaises assertRaisesRegexp assertRegexpMatches assertSequenceEqual assertSetEqual assertTrue assertTupleEqual fredag 5 juli 13
  20. *OUFHSBUJPOCFUXFFOQZUFTUBOE%KBOHP QZUFTUEKBOHP fredag 5 juli 13

  21. *OTUBMMTQZUFTUEKBOHPBOEQZUFTU pip  install  pytest-­‐django fredag 5 juli 13

  22. "EETZPVSQSPKFDUUP1ZUIPOQBUI SFRVJSFTBTFUVQQZUPCFQSFTFOU pip  install  -­‐e  . fredag 5 juli 13

  23. %FpOF%KBOHPTFUUJOHTJOZPVSTIFMM FOWJSPONFOU export  DJANGO_SETTINGS_MODULE=settings fredag 5 juli 13

  24. #POVT -BVODIB1ZUIPOTIFMM XJUIPVUNBOBHFQZ Photo: http://www.flickr.com/photos/mark_i_geo/3498456758 fredag 5 juli 13

  25. $BOBMTPCFDPOpHVSFEJOQZUFTUJOJ [pytest] DJANGO_SETTINGS_MODULE=settings fredag 5 juli 13

  26. )PXUPSVOUIFUFTUT fredag 5 juli 13

  27. 3VOBMMUIFUFTUT $  py.test fredag 5 juli 13

  28. 3VOBMMUFTUTJOBTQFDJpDpMF $  py.test  test_views.py fredag 5 juli 13

  29. 3VOBMMUFTUDBTFTUIBUBSFOBNFE UFTU@GPP $  py.test  -­‐k  test_foo fredag 5 juli 13

  30. 8IFSFUPQVUUIFUFTUT fredag 5 juli 13

  31. #ZEFGBVMU UFTUTBSFGPVOEJO test_*.py fredag 5 juli 13

  32. $POpHVSBCMFJOQZUFTUJOJ [pytest] python_files  =  *.py fredag 5 juli 13

  33. 5FTUTDBOMJWFVOEFS%KBOHPBQQT polls/tests/views.py blog/tests/views.py fredag 5 juli 13

  34. 5FTUTDBOMJWFJOUIFJSPXOSPPUEJSFDUPSZ tests/polls/views.py tests/blog/models.py fredag 5 juli 13

  35. 5FTUTCFTQMJUVQJOUPEJGGFSFOUSPPU EJSFDUPSJFT unit_tests/blog/models.py functional_tests/test_foo.py fredag 5 juli 13

  36. %KBOHP5FTU$BTFT KVTUXPSLT fredag 5 juli 13

  37. 3FVTFEBUBCBTFGSPNMBTUSVO py.test  -­‐-­‐reuse-­‐db fredag 5 juli 13

  38. 1VUUIJTJOQZUFTUJOJUPBMXBZTSFVTFUIF EBUBCBTF 1BTTDSFBUFECUPGPSDFSFDSFBUJPO [pytest] addopts  =  -­‐-­‐reuse-­‐db fredag 5 juli

    13
  39. 5FTUBCMF%KBOHPDPEF fredag 5 juli 13

  40. .JãLP)FWFSZ l5IFSFJTOPTFDSFUUPXSJUJOH UFTUTUIFSFBSFPOMZTFDSFUT UPXSJUJOHUFTUBCMFDPEFz fredag 5 juli 13

  41. NPEFMTQZ WJFXTQZ fredag 5 juli 13

  42. NPEFMTQZ WJFXTQZ BENJOQZ GPSNTQZ fredag 5 juli 13

  43. NPEFMTQZ WJFXTQZ BENJOQZ GPSNTQZ FHH@NBLFSQZ TQBN@IFMQFSTQZ DPPLJF@FBUFSQZ fredag 5 juli

    13
  44. ,FFQUIFNTNBMM GFXCSBODIFT 5FTUJOHWJFXT fredag 5 juli 13

  45. from  datetime  import  datetime,  time from  django.http  import  HttpResponse def

     greet(request):        now  =  datetime.now().time()        if  time(5)  <  now  <  time(12):                greeting  =  'morning'        elif  time(18)  <  now  <  time(21):                greeting  =  'evening'        else:                greeting  =  'day'        return  HttpResponse('Good  %s!'  %  greeting) fredag 5 juli 13
  46. from  datetime  import  datetime,  time from  django.http  import  HttpResponse def

     greet(request):        now  =  datetime.now().time()        if  time(5)  <  now  <  time(12):                greeting  =  'morning'        elif  time(18)  <  now  <  time(21):                greeting  =  'evening'        else:                greeting  =  'day'        return  HttpResponse('Good  %s!'  %  greeting) fredag 5 juli 13
  47. #  greeter.py from  datetime  import  time def  greeting_at(time_of_day):    

       if  time(5)  <  time_of_day  <  time(12):                return  'morning'        elif  time(18)  <  time_of_day  <  time(21):                return  'evening'        else:                return  'day' fredag 5 juli 13
  48. #  views.py from  datetime  import  time from  django.http  import  HttpResponse

    from  .greeter  import  greeting_at def  greet(request):        now  =  datetime.now().time()        greeting  =  greeting_at(now)        return  HttpResponse('Good  %s!'  %                                                greeting) fredag 5 juli 13
  49. NBLFTZPVSUFTUTTMPX %BUBCBTFBDDFTT fredag 5 juli 13

  50. fredag 5 juli 13

  51. UFTUJOH UFTUJOH fredag 5 juli 13

  52. 5IF03.CMVSTUIFMJOFCFUXFFO BQQMJDBUJPODPEFBOERVFSZDPEF 4FQBSBUFUIFRVFSZDPEFJOUPJUTPXO NFUIPET .JOEZPVSRVFSJFT fredag 5 juli 13

  53. fredag 5 juli 13

  54. ! 6 '" fredag 5 juli 13

  55. fredag 5 juli 13

  56. QZUFTUEKBOHPBOEEBUBCBTFT fredag 5 juli 13

  57. 5IJTXJMMBMMPXEBUBCBTFBDDFTT import  pytest @pytest.mark.django_db def  test_user_count():        assert

     User.objects.count()  ==  0 fredag 5 juli 13
  58. 5IJTXJMMGBJM EBUBCBTFBDDFTTJTOPU BMMPXFE def  test_user_count():        assert  User.objects.count()

     ==  0 fredag 5 juli 13
  59. ___________  test_user_count  ____________ test_db_access.py:4:  in  test_user_count >      assert

     User.objects.count()  ==  0 ...  snip  ... E      Failed:  Database  access  not  allowed,        use  the  "django_db"  mark  to  enable fredag 5 juli 13
  60. .BSLBOFOUJSFNPEVMFGPSEBUBCBTF VTBHF import  pytest pytestmark  =  pytest.mark.django_db def  test_foo():  pass

    def  test_bar():  pass fredag 5 juli 13
  61. 3VOBMMUFTUTXIJDIEPFTOPUUPVDIUIF EBUBCBTF $  py.test  -­‐m  'not  django_db' fredag 5 juli

    13
  62. .PEFMUFTUEBUB w$SFBUFPCKFDUTNBOVBMMZ w%KBOHPpYUVSFT w'BDUPSJFT fredag 5 juli 13

  63. %KBOHPpYUVSFT [{"model": "myapp.person", "pk": 1, "fields": {"first_name": "John", "last_name": "Lennon"}},

    {"model": "myapp.person", "pk": 2, "fields": {"first_name": "Paul", "last_name": "McCartney"}} ] Slow & hard to maintain.. avoid them! fredag 5 juli 13
  64. GBDUPSZ@CPZJTBOFYDFMMFOUMJCSBSZ 5IFTPMVUJPOGBDUPSJFT fredag 5 juli 13

  65. 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() fredag 5 juli 13
  66. import  factory from  yourapp.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) fredag 5 juli 13
  67. from  yourfactories  import  PersonFactory def  test_group_letter():        person

     =  PersonFactory.build(                group__name='admins')        assert  person.group_letter()  ==  'A' fredag 5 juli 13
  68. import  pytest @pytest.mark.django_db def  test_group_letter():        person  =

     PersonFactory.create(                group__name='admins')        assert  person.group_letter()  ==  'A' fredag 5 juli 13
  69. 3FQMBDFNFOUGPSVOJUUFTUTFU6QUFBS%PXO QZUFTUpYUVSFT fredag 5 juli 13

  70. (FUBOJOTUBODFPGUIFUFTUDMJFOU def  test_with_client(client):        response  =  client.get('/foo/')  

         assert  response.status_code  ==  200 fredag 5 juli 13
  71. 5IFTFUUJOHTXJMMCFBVUPNBUJDBMMZSFTFU BGUFSUIFUFTU def  test_foo(settings):        settings.DATE_FORMAT  =  'Y-­‐m-­‐d'

    fredag 5 juli 13
  72. $SFBUFZPVSPXOpYUVSFTXJUI QZUFTUpYUVSF import  pytest @pytest.fixture def  person():      

     return  PersonFactory.build() fredag 5 juli 13
  73. 3FRVFTU%KBOHPEBUBCBTFBDDFTT JOBpYUVSF import  pytest from  your_factories  import  UserFactory @pytest.fixture def

     person_in_db(db):        return  PersonFactory.create() fredag 5 juli 13
  74. (SFBUSFTPVSDFT w $BSM.FZFS 5FTUJOHBOE%KBOHP 1Z$PO w %KBOHPUFTUJOHCFTUQSBDUJDFTBOEJOTQJSBUJPOGPSUIJTUBML w IUUQXXXZPVUVCFDPNXBUDI WJDL/2D/9J4

    w )PMHFS,SFLFM QZUFTUSBQJEBOETJNQMFUFTUJOHXJUI1ZUIPO  &VSP1ZUIPO w IUUQXXXZPVUVCFDPNXBUDI WL;+)6N;9. w QZUFTUEPDVNFOUBUJPO w IUUQQZUFTUPSH w QZUFTUEKBOHPEPDVNFOUBUJPO w IUUQQZUFTUEKBOHPSFBEUIFEPDTPSH fredag 5 juli 13
  75. QZUFTUTQSJOU fredag 5 juli 13

  76. 8PSLTXJUICPUI XPSMET fredag 5 juli 13

  77. 4MJEFTIUUQTQFBLFSEFDLDPNQFMNF BOESFBT!QFMNFTF !BOESFBTQFMNF 5IBOL:PV fredag 5 juli 13