Create an app `lists` (sub-directory) via `python manage.py startapp lists` in the directory which contains `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:
* The resolve() function if `django.url` package can be used for resolving URL paths to the corresponding view functions. The function returns a [`ResolverMatch` object](https://docs.djangoproject.com/en/3.1/ref/urlresolvers/#django.urls.ResolverMatch) that allows you to access various metadata about the resolved URL.
* In `assertEqual(...)`, we try to test that `found.func` is `home_page` (a view function we haven't defined yet)
* This book use Django v1.11. So `path` function is not utilized, it's used in v3.x
Explain:
*`url` start with a regex, which defines which URLs it looks for, and where (function) should these request to send
*`^$` means empty string
Modifying `superlists.urls` to
```python
from django.conf.urls import url
from lists import views
urlpatterns = [
url(r'^$', views.home_page, name='home'),
]
```
Generate error as shown
```
...
File "/home/jason/HomeWorkstation/SynologyGiteaSpace/python-tdd-book-src/src/superlists/urls.py", line 20, in <module>
url(r'^$', views.home_page, name='home'),
File "/home/jason/miniconda3/envs/python-tdd-book/lib/python3.6/site-packages/django/conf/urls/__init__.py", line 85, in url
raise TypeError('view must be a callable or a list/tuple in the case of include().')
TypeError: view must be a callable or a list/tuple in the case of include().
```
Analyzing error message "TypeError: view must be a callable or a list/tuple in the case of include().": unit tests have actually made the link btw the URL "/" and `home_page = None` in `lists/views.py`, and are now complaining that `home_page` view is not callable.