Finished Chapter 3.1 ~ 3.3

master
Jason Zhu 2020-08-19 15:50:58 +10:00
parent 8363e83957
commit fe1bc3a548
13 changed files with 258 additions and 0 deletions

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ListsConfig(AppConfig):
name = 'lists'

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,8 @@
from django.test import TestCase
# Create your tests here.
class SmokeTest(TestCase):
def test_bad_maths(self):
self.assertEqual(1+1,3)

View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "superlists.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv)

View File

@ -0,0 +1,120 @@
"""
Django settings for superlists project.
Generated by 'django-admin startproject' using Django 1.11.29.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '5ty+3qgs$cadiv2l4)a)#ikp1=bfd$41^d^@07#!q(t4_$6igh'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# 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 = 'superlists.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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 = 'superlists.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/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/1.11/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/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'

View File

@ -0,0 +1,21 @@
"""superlists URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]

View File

@ -0,0 +1,16 @@
"""
WSGI config for superlists project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "superlists.settings")
application = get_wsgi_application()

57
textbook/chap3.md 100644
View File

@ -0,0 +1,57 @@
# 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
## At Last! We Actually Write Some Application Code!
## urls.py
## Unit Testing a View
### The Unit-Test/Code Cycle