[PYTHON] Test Driven Development with Django Part 1

Test Driven Development with Django 1

Why do you do it

I've been studying Django on my own, using the resources of my predecessors, including the Django Girls Tutorial, but I couldn't find any Japanese resources to learn test-driven development in Django. I would like to post it as a reference for people like me who are self-taught in programming.

This is a record for understanding Test Driven Development (TDD) in Django. I am still lacking in study, so I would appreciate it if you could point out any mistakes. ..

This time [** 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 reference, 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.

Let's do it.

Building a virtual environment

#Create project directory
$ mkdir django-TDD
$ cd djagno-TDD

#Creating a virtual environment
$ python -m venv venv-tdd

#Enable virtual environment
$ venv-tdd/Script/activate

#Upgrade pip and setuptools
$ python -m pip install --upgrade pip setuptools

#Install Django and Selenium
$ pip install django selenium
    installing collected packages: sqlparse, pytz, asgiref, django, urllib3, selenium
    Successfully installed asgiref-3.2.3 django-3.0.2 pytz-2019.3 selenium-3.141.0 sqlparse-0.3.0 urllib3-1.25.7

We will use Google Chrome to perform functional tests, so download the Google Chrome web driver.

The current environment is Google Chrome version: 79.0.3945.130 (Official Build) (64-bit), so Google Chrome Driver has downloaded Chrome Driver 79.0.3945.16.

Part1. The Basics of TDD and Django

Chapter1. Getting Django Set Up Using a Functional Test

When you decide to create a website, the usual first step is to install the web-framework, rewrite the settings, and so on, but in TDD you always write the test first.

The TDD development cycle is to ensure that:

--Write a test --Run a test to make sure it fails. --Write the code so that the test succeeds.

The first thing we want to confirm is ...

To do this, use Selenium to automatically operate the browser.

Write a functional test

Create functional_tests.py.

# django-tdd/functional_tests.py

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('http://localhost:8000')

assert 'Django' in browser.title

This is the first functional test. Do this.

$ python functional_tests.py

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

You can see that the browser is started automatically by selenium, but an error page is displayed. You can see that the Assertion Error is also displayed on the shell. I want to solve this.

Start Django

Start the Djagno project and start the development server to pass this functional test.

$ django-admin startproject config .

$ python manage.py runserver

    Watching for file changes with StatReloader
    Performing system checks...

    System check identified no issues (0 silenced).

    You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
    Run 'python manage.py migrate' to apply them.
    January 19, 2020 - 15:36:31
    Django version 3.0.2, using settings 'config.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.

You can see that Django (3.0.2) started the development server http://127.0.0.1:8000/ using config.settings.

Now launch another shell to enable the virtual environment and then run the functional test.

$ python manage.py functional_tests.py

    DevTools listening on ws://127.0.0.1:54716/devtools/browser/6ddf9ee8-7b35-41f5-8700-d740ef24c8dc

As a result, the AssertionError was not displayed, and the browser did not display the error.

We ran functional tests and confirmed that Djagno was working! !! !! !!

Register with Git repository

TDD works with the Version Control System.

$ git init .

$ type nul > .gitignore

Manage things you don't want to manage with git with .gitignore.

#.gitignore
db.sqlite3
debug.log
/venv-tdd

Now that you've created a .gitignore, add your changes.

$ git add .
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .gitignore
        new file:   .vscode/settings.json
        new file:   README.md
        new file:   README_Part1.md
        new file:   chromedriver.exe
        new file:   config/__init__.py
        new file:   config/__pycache__/__init__.cpython-37.pyc
        new file:   config/__pycache__/settings.cpython-37.pyc
        new file:   config/__pycache__/urls.cpython-37.pyc
        new file:   config/__pycache__/wsgi.cpython-37.pyc
        new file:   config/asgi.py
        new file:   config/settings.py
        new file:   config/urls.py
        new file:   config/wsgi.py
        new file:   functional_tests.py
        new file:   manage.py

Here, * hoge.pyc * and * __ pycache __ * folders that I don't want to make changes have been added to the changes. I want to exclude this.

$ git rm -r --cached config/__pycache__ .vscode

Edit .gitignore

# .gitignore
db.sqlite3
debug.log
/venv-tdd
.vscode
__pycache__
*.pyc
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .gitignore
        new file:   README.md
        new file:   README_Part1.md
        new file:   chromedriver.exe
        new file:   config/__init__.py
        new file:   config/asgi.py
        new file:   config/settings.py
        new file:   config/urls.py
        new file:   config/wsgi.py
        new file:   functional_tests.py
        new file:   manage.py

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   .gitignore
        modified:   README_Part1.md

The git status has been fixed as intended. Commit with this.

$ git add .

Here, I don't want to commit SECRET_KEY etc. in Djagno's config / settings.py before committing.

$ git rm -r --cached config/settings.py
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .gitignore
        new file:   README.md
        new file:   README_Part1.md
        new file:   chromedriver.exe
        new file:   config/__init__.py
        new file:   config/asgi.py
        new file:   config/urls.py
        new file:   config/wsgi.py
        new file:   functional_tests.py
        new file:   manage.py

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   README_Part1.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        config/settings.py

Use python-dotenv to avoid committing system variables together in an .env file.

$ pip install python-dotenv

Modify config / settings.py

# config/settings.py
"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 3.0.2.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os
from dotenv import load_dotenv  #add to

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_NAME = os.path.basename(BASE_DIR)  #add to

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# .Load env
load_dotenv(os.path.join(BASE_DIR, '.env'))  #add to

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY')  #Change

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']  #Change


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  #Change
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'config.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'ja'  #Change

TIME_ZONE = 'Asia/Tokyo'  #Change

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

Make changes in this state and commit.

$ type nul > .env

Added SECRET_KEY to .env.

# .env
SECRET_KEY = 'your_secret_key'

Add .env to .gitignore.

db.sqlite3
debug.log
/venv-tdd
.vscode
__pycache__
*.pyc
.env  #add to

Record changes.

$ git add .
$ git status
$ git commit -m "first commit!"

Chapter1 Summary

I started my Django project by writing functional tests. I will continue reading in this condition.

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
Django test
[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)
Django begins part 1
Experience Part I "Multinational Currencies" in the book "Test Driven Development" in Python
Internationalization with django
Django begins part 4
First Django development
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
Strengthen with code test ⑦
Output PDF with Django
Strengthen with code test ③
Markdown output with Django
Use Gentelella with django
Twitter OAuth with Django
Strengthen with code test ⑤
Strengthen with code test ④
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
Use LESS 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)
[Memo] Build a development environment for Django + Nuxt.js with Docker
[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
Django starting from scratch (part: 2)
Bordering images with python Part 1