使用GitHub动作对Docker化的Django应用程序进行自动化测试
在这篇文章中,读者将学习如何用[Pytest]测试Django应用程序,对其进行dockerize,并配置GitHub Actions来自动化Django测试。
Pytest是一个Python库,用于运行Python代码的测试。[GitHub Actions]使你可以在你的仓库中自动完成许多重复性的任务。
Docker确保你的应用程序在所有平台上以同样的方式工作。将这些功能添加到你的应用程序中,可以使其更容易进行[持续交付]和协作。
前提条件
读者应该具备以下条件才能跟上本教程的学习。
- 对Django有良好的理解。
- 使用Git/GitHub。
- 安装了[Docker]和[Docker compose]。
构建一个基本的Django应用程序
让我们建立本教程中要使用的项目。我们将为该项目创建一个新的虚拟环境,这在试图获得所有依赖项的列表时将会很方便。
创建虚拟环境后,用终端执行以下命令安装Django。
(env)$ pip install django
运行下面的命令来创建一个新的项目。
(env)$ django-admin startproject <name_of_project>
例如,如果你的应用程序的名字是django_test_githubactions ,在命令中使用这个名字。
(env)$ django-admin startproject django_test_githubactions
cd 进入包含manage.py的目录,执行下面的命令来初始化Django应用程序。
(env)$ python manage.py startapp blog
在settings.py 文件中,将blog 应用程序添加到已安装的应用程序列表中。这一步使Django能够识别它是主程序的一个子程序。
INSTALLED_APPS = [
"blog", #new
]
我们将为这个演示建立一个博客应用程序,所以在*blog/models.py`文件中,粘贴下面的代码片段。
from django.db import models
class Article(models.Model):
author_name = models.CharField(max_length=30)
title = models.CharField(max_length=20)
content = models.CharField(max_length=200)
def __str__(self):
return self.title
接下来,我们必须编写显示内容的逻辑。要做到这一点,请浏览app/views.py 。 然后,在该文件中添加下面的代码片断。
from django.shortcuts import get_object_or_404, render
from .models import Article
def content_view(request, pk):
post = get_object_or_404(Article, pk=pk)
return render(request, "blog/article.html", {'post':post})
接下来,用下面的代码更新你的urls.py 文件,以便在浏览器中访问该路由。
from blog import views
urlpatterns = [
path('<int:pk>', views.content_view, name="content")
]
接下来,在应用程序目录中创建一个templates 文件夹,以存放显示博客内容的模板。
导航到你的应用程序文件夹,创建templates/blog/article.html ,并粘贴下面的代码。
Blog title:
{% if post.content %}
{{ post.content }}
{% endif %}
迁移models ,开始向数据库添加文章。要做到这一点,进入你的终端/命令提示符并运行。
(env)$ python manage.py makemigrations
然后运行。
(env)$ python manage.py migrate
填充数据库
我们需要填充我们的数据库,以了解我们的应用程序是否按预期工作。要填充数据库,请到你的终端,输入下面的指令,进入Django shell。
(env)$ python manage.py shell
然后一个接一个地运行下面的代码;第二行在数据库中添加一条记录并保存。你可以用同样的格式来添加更多的数据。
>>> from blog.models import Article
>>> Article.objects.create(author_name="Ali",title="First app", content="Some detail of the article").save()`
现在运行你的服务器,进入你的localhost(http://127.0.0.1:8000/),然后添加你刚刚添加的文章的id,像这样:http://127.0.0.1:8000/1,你会看到文章内容被显示出来了。

如何向Django应用程序添加测试
本节将告诉你如何为你的URL和模型添加测试。在测试应用程序之前,执行下面的命令来安装测试库。
(env)$ pip install pytest pytest-django
Pytest-django是一个插件,它的建立是为了让你更容易在Django中使用Pytest。
接下来,在你的项目根部创建一个名字为pytest.ini 的文件。在pytest.ini 文件中,你将把你的项目的settings.py 文件的路径。
在pytest.ini 文件中,粘贴下面的代码。
[pytest]
DJANGO_SETTINGS_MODULE = django_test_githubactions.settings
接下来,在应用程序目录中创建一个测试文件夹,你的该应用程序的所有测试文件都将存放在这里。你将在博客应用程序中创建一个新的目录,blog/tests/ 。
首先,我们将测试urls.py 文件,所以你将在测试文件夹中创建一个新文件blog/tests/test_urls.py 。
所有测试文件必须以
test_开始,因为这是Pytest使用的惯例。
将下面的代码粘贴到你刚刚创建的test_urls.py 文件中。
from django.urls import reverse, resolve
from django.urls import path
class TestUrls:
# here, you are checking if the path's view name is content
def test_post_content_url(self):
path = reverse('content', kwargs={'pk':1})
assert resolve(path).view_name == "content" # here you are checking if the path's view name is content
接下来,我们将对模型进行测试,为其创建一个新文件app/tests/test_models.py ,并添加下面的代码片段。
import pytest
from app.models import Article
@pytest.mark.django_db
def test_article_create():
# Create dummy data
article = Article.objects.create(
author_name="Muhammed Ali",
title="Simple article",
content="This is my content",
)
# Assert the dummy data saved as expected
assert article.author_name=="Muhammed Ali"
assert article.title=="Simple article"
assert article.content=="This is my content"
要运行测试,进入你的命令行并运行。
(env)$ python -m pytest
你应该看到一个类似下图的过程,以显示所有的测试都通过了。

设置Docker
本节帮助你学习如何使用Docker和Docker compose来运行你的应用程序。假设你已经在本地机器上安装了Docker和Docker compose,在你的项目根部创建一个Dockerfile 文件。在Dockerfile ,你将把用于构建Docker镜像的步骤说明。
你刚刚创建的Dockerfile 应该包含下面的代码。
FROM python:3.7-alpine
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
# make a directory in our Docker image in which we can use to store our source code
# Copy the project folder from our local machine to the docker image
RUN mkdir /project
WORKDIR /project
COPY . .
FROM python:3.7-alpine 是你将继承你的Dockerfile的镜像。它通常是你正在使用的语言。
ENV PYTHONUNBUFFERED 1 是必要的,这样Docker就不会对输出进行缓冲,而且你可以实时看到你的应用程序的输出(例如Django日志)。
COPY ./requirements.txt /requirements.txt 将requirements.txt文件复制到你本地机器中的Dockerfile文件旁边,作为我们的Docker镜像*requirements.*txt。
RUN pip install -r /requirements.txt 将requirements.txt文件安装在docker镜像中。
接下来,在你项目的根部创建一个requirements.txt 文件。这个文件将包含一个我们想为项目安装的所有依赖项的列表。
将下面的文字粘贴到requirements.txt 文件中。
asgiref==3.4.1
attrs==21.2.0
Django==3.2.7
pytest==6.2.5
pytest-django==4.4.0
python-dateutil==2.8.2
pytz==2021.1
six==1.16.0
sqlparse==0.4.1
设置Docker Compose
在这一节中,你将编写指令,告诉Docker如何运行你的应用程序。首先,在你项目的根部,创建一个docker-compose.yml 文件,并添加代码行。
version: "3" # Verion of docker-compose we want to use
services:
proj:
build:
# command that is used to run services
context: . # builds the current directory
# map port on local machine to port on the docker image
ports:
- "8000:8000"
volumes:
- .:/project # Updates the image with new changes in the code
command: >
sh -c "python manage.py runserver 0.0.0.0:8000"
之后,到你的终端,运行$ docker-compose build ,使用docker-compose配置构建我们的镜像。
Docker-compose运行在0.0.0.0:8000 ,而Django并不认识它,所以你需要在你的settings.py 文件中把它添加到你的ALLOWED_HOSTS ,像这样。
`ALLOWED_HOSTS = ['0.0.0.0']`
现在运行$ docker-compose up ,启动服务器,在浏览器上进入http://0.0.0.0:8000/1,你就会看到你创建的博客。

设置GitHub动作
GitHub Actions可以让你在 GitHub 仓库中实现自动化、自定义指定的开发和部署流程。
术语
- 工作:行动的分步说明。
- 工作流:工作流是一个YAML文件上配置的一个或多个工作的自动化流程的列表。
在你的项目中激活 GitHub 操作
在你的文本编辑器上,导航到你的项目根目录,并在其中创建一个名为.github/workflows 的目录,创建一个名为main.yml f 的文件。main.yml 文件将包含所有的 GitHub Actions 命令。
将下面的代码粘贴到你刚刚创建的main.yml 文件中。
name: test_project
on:
# activates the workflow when there is a push or pull request on the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test_project:
# the operating system your job will run on
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- run: pip install -r requirements.txt # install requirements to enable GitHub run our code
- run: pytest . # run the unit test
上面的代码只是在你的最新推送上运行测试。
工作中的 GitHub 行动
提交并推送你目前拥有的所有代码到 GitHub。推送完代码后,去GitHub上的项目,点击 "Actions "标签。如果你的步骤正确,你应该看到你的GitHub Actions已经完全运行,而且你的应用程序已经被测试,所有测试都通过了。

当你点击它时,你应该看到这个。

为了检查GitHub Actions的意图是否得到满足,你将更新测试,所以它失败了。
在模型的测试中,把它改成。
def test_article_create():
article = Article.objects.create(
author_name="Muhammed Ali",
title="Simple article",
content="The article's content",
)
assert article.author_name=="Muhammed Al" # this will make sure the test fails
assert article.title=="Simple article"
assert article.content=="The article's content"
提交并推送你的代码。然后,转到你的项目Actions,你应该看到测试失败了,说明我们的GitHub Actions说明是按预期工作的。

总结
本教程教你为Django应用程序的URL和模型编写单元测试。同时,你可以在你的应用程序被推送到GitHub时自动运行测试的过程。
此外,你还可以在工作流程中添加一些提示性测试,以提高应用程序的持续集成。
希望通过这篇文章,你可以为你未来的项目增加一些用GitHub行动进行持续交付的内容。