81 lines
2.8 KiB
Markdown
81 lines
2.8 KiB
Markdown
# Chapter 3. Testing a Simple Home Page with Unit Tests
|
|
|
|
Chap2 introduced writing a functional test using unittest module (expected failure), now create a working To-Do list app
|
|
|
|
## 3.1 Our First Django App, and Our First Unit Test
|
|
|
|
* Django encourage structure the code into apps. We can reuse app developed by us or others
|
|
|
|
Create an app `lists` (sub-directory) via `python manage.py startapp lists` along other `functional_tests.py` & `manage.py`, this subdir should include `tests.py` be default
|
|
|
|
## 3.2 Unit Tests, and How They Differ from Functional Tests
|
|
|
|
Unit Tests vs Functional Tests:
|
|
|
|
* **Unit Tests (UT)**: tests app from inside as programmer
|
|
* **Functional Tests (FT)**: test app from outside as user
|
|
|
|
TDD approach will cover both, with following workflow:
|
|
|
|
1. Writing FT that describing new functionality
|
|
2. After expected failure of FT, design app that can get it pass FT. And write UTs that define how code behave. Benchmark, each production code we write should be tested by at least 1 of our unit tests.
|
|
3. After having a failure UT, write the smallest amount of app code to pass the UT.
|
|
4. Iterate step 2 & 3 to the point that we can test with FT
|
|
5. Rerun FT and it should pass.
|
|
6. Keep writing new UT & FT
|
|
|
|
Summary:
|
|
|
|
* FT evaluate app on high level
|
|
* UT drive development on low level
|
|
|
|
## 3.3 Unit Testing in Django
|
|
|
|
1. `lists/tests.py` provide place to write UT/FT. Adding following to import Django's `TestCase` which is inherited from `unittest`
|
|
|
|
```python
|
|
from django.test import TestCase
|
|
|
|
# Create tests from here
|
|
```
|
|
|
|
2. Before writing any new FT/UT, make sure UT can be run by automated test runner, as `lists/tests.py` is created by unittest. while previously we directly call `python functional_tests.py`. Running Django's test framework via:
|
|
|
|
```python
|
|
python manage.py test
|
|
```
|
|
|
|
## 3.4 Django's MVC, URLs, and View Functions
|
|
|
|
Django is structured along a classic [**Model-View-Controller (MVC)** pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
|
|
|
|
Django's main job is to decide what to do when a user asks for a particular URL on our site.
|
|
|
|
Django's workflow is like:
|
|
|
|
1. An HTTP `request` comes in for a particular URL
|
|
2. *Resolving the URL*: Django uses some rules to decide which `view` function should deal with the request.
|
|
3. The view function processes the request and returns an HTTP `response`
|
|
|
|
Let's design a tests:
|
|
|
|
1. Verify we can resolve the URL for the root of site ("/") to a particular view function we've made?
|
|
2. Verify view function return some HTML which will get the functional test to pass?
|
|
|
|
## 3.5 At Last! We Actually Write Some Application Code!
|
|
|
|
Add content in `lists/views.py`, to pass the test
|
|
|
|
```python
|
|
from django.shortcuts import render
|
|
|
|
home_page = None
|
|
```
|
|
|
|
## 3.6 urls.py
|
|
|
|
|
|
|
|
## 3.7 Unit Testing a View
|
|
|
|
### 3.7.1 The Unit-Test/Code Cycle |