[PYTHON] Test Driven Development with Django Part 2

Test Driven Development with Django Part 2

This is a learning note to help you understand Test Driven Development (TDD) in Django.

References are [** Test-Driven Development with Python: Obey the Testing Goat: Using Django, Selenium, and JavaScript (English Edition) 2nd Edition **](https://www.amazon.co.jp/dp/B074HXXXLS We will proceed with learning based on / ref = dp-kindle-redirect? _ Encoding = UTF8 & btkr = 1).

In this book, we are conducting functional tests using Django 1.1 series and FireFox, but this time we will carry out functional tests on Djagno 3 series and Google Chrome. I've also made some personal modifications (such as changing the Project name to Config), but there are no major changes.

⇒⇒ Click here for Part 1

Part1. The Basics of TDD and Django

Chapter2 Extending Our Functional Test Usinng the unittest Module

In Chapter 1, you can write the first functional test from Django's environment construction and check whether Django's Default page is working through the functional test. It's done. This time I would like to apply this to the actual front page while creating a ToDo application.

Testing with Chrome's web driver and Selenium is called ** functional testing ** because it allows you to see ** how your application works ** from the user's perspective. It traces the * user story * when a user uses an application, and determines how the user uses the application and how the application responds to it.

Functional Test == Acceptance Test == End-To-End Test

** Test-Driven Development with Python: Obey the Testing Goat: Using Django, Selenium, and JavaScript (English Edition) 2nd Edition ** In / B074HXXXLS / ref = dp-kindle-redirect? _ Encoding = UTF8 & btkr = 1), testing the function (* function *) of an application is called * functional tests *, so in this article it is called a functional test. I will. This is also called * acceptance tests *, * End-To-End tests (E2E tests, integration tests) *. The purpose of this test is to see how the entire application works from the outside.

Let's write it as a comment in the functional test while assuming the actual user story.

# django-tdd/functional_tests.py

from selenium import webdriver

browser = webdriver.Chrome()

#Nobita is a new to-I heard that there is a do app and accessed the homepage.
browser.get('http://localhost:8000')

#Nobita has the page title and header to-I confirmed that it suggests that it is a do app.
assert 'To-Do' in browser.title

#Nobita is to-Prompted to fill in the do item,


#Nobita wrote in the text box "Buy Dorayaki"(His best friend loves dorayaki)


#When Nobita presses enter, the page is refreshed
# "1:Buying dorayaki"Is to-Found to be added as an item to the do list


#The text box allows you to continue to fill in items, so
#Filled in "Billing Dorayaki Money"(He is tight when it comes to money)


#The page was refreshed again and I was able to see that new items were added


#Nobita is this to-I was wondering if the do app was recording my items properly,
#When I checked the URL, I found that the URL seems to be a specific URL for Nobita


#When Nobita tried to access a specific URL that he had confirmed once,


#The item was saved so I was happy to fall asleep.


browser.quit()

Changed the title assertion from "Django" to "To-Do". It is expected that the functional test will fail as it is. So let's run a functional test.

#Start local server
$ python manage.py runserver

#Launch another command line
#Run functional test
$ python functional_tests.py

Traceback (most recent call last):
  File "functional_tests.py", line 11, in <module>
    assert 'To-Do' in browser.title
AssertionError

The test failed as expected. Therefore, we know that we should proceed with development so that this test can be successful.

Use unittest Module

In the functional test we just ran

--AssertioError is unfriendly (I hope you know what the browser title really was)

--The browser started by Selenium is not erased and remains

There was annoyance. These can be solved using the unittest module, which is a standard Python module.

Let's rewrite the functional test as follows.

# django-tdd/functional_tests.py

from selenium import webdriver
import unittest


class NewVisitorTest(unittest.TestCase):

    def setUp(self):
        self.browser = webdriver.Chrome()

    def tearDown(self):
        self.browser.quit()

    def test_can_start_a_list_and_retrieve_it_later(self):
        #Nobita is a new to-I heard that there is a do app and accessed the homepage.
        self.browser.get('http://localhost:8000')

        #Nobita has the page title and header to-I confirmed that it suggests that it is a do app.
        self.assertIn('To-Do', self.browser.title)
        self.fail('Finish the test!')

        #Nobita is to-Prompted to fill in the do item,

        #Nobita wrote in the text box "Buy Dorayaki"(His best friend loves dorayaki)

        #When Nobita presses enter, the page is refreshed
        # "1:Buying dorayaki"Is to-Found to be added as an item to the do list

        #The text box allows you to continue to fill in items, so
        #Filled in "Billing Dorayaki Money"(He is tight on money)

        #The page was refreshed again and I was able to see that new items were added

        #Nobita is this to-I was wondering if the do app was recording my items properly,
        #When I checked the URL, I found that the URL seems to be a specific URL for Nobita

        #When Nobita tried to access a specific URL that he had confirmed once,

        #The item was saved so I was happy to fall asleep.


if __name__ == '__main__':
    unittest.main(warnings='ignore')

Functional tests can be written by inheriting unittest.TestCase. Let's sort out the points this time.

--The test function you want to execute starts with * test_ , and the test runner automatically runs the test. - setUp * and * tearDown * are special functions that are executed before and after the test runs. -* tearDown * is also executed with a test error. --Self.fail () will fail the test and spit out an error. --Unittest.main () runs the test and automatically runs the test case and its methods. --Warnings = You can ignore excessive ResoureWarning etc. by adding the option of'ignore'.

Let's run it.

$ python functional_tests.py
======================================================================
FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "functional_tests.py", line 20, in test_can_start_a_list_and_retrieve_it_later
    self.assertIn('To-Do', self.browser.title)
AssertionError: 'To-Do' not found in 'Django:A web framework for perfectionists who never miss a deadline'

----------------------------------------------------------------------
Ran 1 test in 7.956s

FAILED (failures=1)

The unittest module makes it easier to understand the contents of * AssertionError *.

If you change * self.assertIn ('To-Do', self.brower.title) * to * self.assertIn ('Django', self.brower.title) *, you should be able to clear the test. Let's check this.

# django-tdd/functional_tests.py
# ~~abridgement~~
    def test_can_start_a_list_and_retrieve_it_later(self):
        #Nobita is a new to-I heard that there is a do app and accessed the homepage.
        self.browser.get('http://localhost:8000')

        #Nobita has the page title and header to-I confirmed that it suggests that it is a do app.
        self.assertIn('Django', self.browser.title)  #Change
        self.fail('Finish the test!')
# ~~abridgement~~
$ python functinal_tests.py
======================================================================
FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "functional_tests.py", line 21, in test_can_start_a_list_and_retrieve_it_later
    self.fail('Finish the test!')
AssertionError: Finish the test!

----------------------------------------------------------------------
Ran 1 test in 6.081s

FAILED (failures=1)

As a result of running, the test should succeed, but the test is FAIL. When I checked * AssertionError *, the message set by * self.fail ('Finish the test') * was reflected. This is because * self.fail ('message') * has a function to always spit out the set error message even if there is no error. Here it is set as a reminder to let you know that the test is over.

So this time, comment out * self.fail ('Finish the test!') * And run it.

# django-tdd/functional_tests.py
# ~~abridgement~~
    def test_can_start_a_list_and_retrieve_it_later(self):
        #Nobita is a new to-I heard that there is a do app and accessed the homepage.
        self.browser.get('http://localhost:8000')

        #Nobita has the page title and header to-I confirmed that it suggests that it is a do app.
        self.assertIn('Django', self.browser.title)
        # self.fail('Finish the test!')  #Comment out
# ~~abridgement~~
$ python functinal_tests.py

.
----------------------------------------------------------------------
Ran 1 test in 7.698s

OK

It was confirmed that there were no errors and the test was successful. The final functional test output should look like this. Let's undo the changes in * functional_tests.py *.

# django-tdd/functional_tests.py
# ~~abridgement~~
    def test_can_start_a_list_and_retrieve_it_later(self):
        #Nobita is a new to-I heard that there is a do app and accessed the homepage.
        self.browser.get('http://localhost:8000')

        #Nobita has the page title and header to-I confirmed that it suggests that it is a do app.
        self.assertIn('To-do', self.browser.title)
        self.fail('Finish the test!')
# ~~abridgement~~

Commit

By creating a user story while adding comments, I was able to create and run a functional test of my to-do application. Let's commit here. I was able to confirm the changed file by doing ** git status **.

You can check the difference from the last commit by doing ** git diff **. When you do this, you can see that functional_tests.py has changed significantly.

Let's commit.

$ git add .
$ git commit -m "First FT specced out in comments, and now users unittest"

Chapter 2 Summary

I was able to change the functional tests from a level that confirms the launch of a Django project to one that is based on a user story that uses a To-Do application. We also found that using unittest can make better use of error messages.

Recommended Posts

Test Driven Development with Django Part 3
Test Driven Development with Django Part 4
Test Driven Development with Django Part 6
Test Driven Development with Django Part 2
Test Driven Development with Django Part 1
Test Driven Development with Django Part 5
Test Driven Development Startup with PySide & Pytest
Development digest with Django
[Test Driven Development (TDD)] Chapter 21 Summary
How to authenticate with Django Part 2
How to authenticate with Django Part 3
Application development using SQLite with Django (PTVS)
Experience Part I "Multinational Currencies" in the book "Test Driven Development" in Python
Internationalization with django
Django begins part 4
CRUD with Django
First Django development
Create test data like that with Python (Part 1)
Build Django + NGINX + PostgreSQL development environment with Docker
Build the fastest Django development environment with docker-compose
[Python] Build a Django development environment with Docker
Django Getting Started Part 2 with eclipse Plugin (PyDev)
Build a Django development environment with Doker Toolbox
Authenticate Google with Django
Django 1.11 started with Python3.6
Primality test with Python
Upload files with Django
Output PDF with Django
Strengthen with code test ⑨
Strengthen with code test ③
Markdown output with Django
Use Gentelella with django
Strengthen with code test ⑤
Strengthen with code test ④
Getting Started with Django 1
Primality test with python
Send email with Django
sandbox with neo4j part 10
Web application made with Python3.4 + Django (Part.1 Environment construction)
File upload with django
Strengthen with code test ②
Use LESS with Django
Pooling mechanize with Django
Use MySQL with Django
Strengthen with code test ①
Build a development environment with Poetry Django Docker Pycharm
[Memo] Django development environment
Articles that enable system development with Django (Python) _Introduction
Start today with Django
Getting Started with Django 2
Strengthen with code test ⑧
Strengthen with code test ⑨
Tutorial for doing Test Driven Development (TDD) in Flask-2 Decorators
Build a Django development environment with Docker! (Docker-compose / Django / postgreSQL / nginx)
[Django] Build a Django container (Docker) development environment quickly with PyCharm
Build a bulletin board app from scratch with Django. (Part 2)
Build a bulletin board app from scratch with Django. (Part 3)
Tutorial for doing Test Driven Development (TDD) in Flask ―― 1 Test Client
Image processing with Python (Part 2)
Studying Python with freeCodeCamp part1
Do Django with CodeStar (Python3.6.8, Django2.2.9)