Django 自动化测试 && 静态文件的引入

2022-01-17 19:33:54 浏览数 (1)

个人学习笔记,参考 django 官方文档:https://docs.djangoproject.com/zh-hans/3.2/

一、自动化测试

  测试代码,就是检查你的代码能否正常运行(废话)

  实话说,就目前为止,我写程序都是运行——>报错——>然后看报错信息——>print输入输出这样去测试的。但是项目毕竟是一个整体的项目,这样测试未免太不专业了。

  自动化测试具有以下优点:

  • 测试将节约你的时间
  • 测试不仅能发现错误,而且能预防错误
  • 测试是你的代码更有吸引力
  • 测试有利于团队协作

听起来不错,那就试试吧!

1、首先得有个 BUG

  按照我们之前写的这个应用逻辑,当我们访问index这个页面时,我们应该会得到最近发布的五条投票,如果有五条的话。

  但是现在有一个小 bug 就是,如果我们的投票是定时到明天发布的,我们的想法是用户明天才能看到这条投票,index页面不应该显示这条数据,但按照目前的逻辑,index会立马显示这条数据。

注意:上面描述的确实是一个 BUG,但是还有一个重要的 BUG,就是之前我们再写数据模型时,我们根本没定义任何方法来显示一天内的数据。原谅我没有看到这个要求:Question 是在一天之内发布的。

下面是 model 层现在的状态。

代码语言:javascript复制
# django框架的接口模块,默认已经引入
from django.db import models

import datetime
from django.utils import timezone


# Create your models here.

# 创建了一个“问题”类(表),表里有两个字段。
class Question(models.Model):
    # 问题描述字段
    question_text = models.CharField(max_length=200)
    # 创建日期字段
    pub_date = models.DateTimeField('date published')

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

    # python魔法方法,显示调用该对象的时候的返回内容
    def __str__(self):
        return self.question_text


# 创建了一个选项类(表),表中包含三个字段。
class Choice(models.Model):
    # 这个表里定义了一个外键字段,因为一个问题可以有多个选项,每个问题对应每个问题的选项。
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    # 选项描述字段
    choice_text = models.CharField(max_length=200)
    # 是否选取字段
    votes = models.IntegerField(default=0)

    # python魔法方法,显示调用该对象的时候的返回内容
    def __str__(self):
        return self.choice_text

2、暴露这个 BUG

  文字描述这个 BUG 确实有点苍白无力,下面我们用 python manage.py shell 命令来暴露这个 BUG。

  在项目根目录下打开终端,输入python manage.py shell 进入交互式编译环境。

代码语言:javascript复制
>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>> # 创建了一个实例对象,他的时间是未来的。
>>> future_question = Question(pub_date=timezone.now()   datetime.timedelta(days=30))
>>> # 会公开近期投票吗?
>>> future_question.was_published_recently()
True

  很显然现在应用会公开未来的投票,所以我们要修复这个 BUG,哦对了,这不是一个自动化测试,我们只是在交互式环境下测试的,我们应该把他写成一个文件,当项目运行时,执行自动化测试。

3、自动化测试

  按照惯例,Django 应用的测试应该写在应用的 tests.py 文件里。测试系统会自动的在所有以 tests 开头的文件里寻找并执行测试代码。

polls/tests.py

代码语言:javascript复制
# Django自带的测试接口,默认已经引入
from django.test import TestCase
# Create your tests here.
# 引入datatime模块
import datetime
from django.utils import timezone
# 引入我们的数据表
from .models import Question


class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):
        """
        未来的一个时间他的返回值应该是False
        """
        time = timezone.now()   datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)

4、运行测试

  在终端执行测试命令python manage.py test polls

代码语言:javascript复制
PS J:study_djangomysite> python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests)
未来的一个时间他的返回值应该是False
----------------------------------------------------------------------
Traceback (most recent call last):
  File "J:study_djangomysitepollstests.py", line 19, in test_was_published_recently_with_future_question
    self.assertIs(future_question.was_published_recently(), False)
AttributeError: 'Question' object has no attribute 'was_published_recently'

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (errors=1)
Destroying test database for alias 'default'...
PS J:study_djangomysite>

  以下是自动化测试的运行过程:

  • python manage.py test polls 将会寻找 polls 应用里的测试代码
  • 它找到了 django.test.TestCase 的一个子类
  • 它创建一个特殊的数据库供测试使用
  • 它在类中寻找测试方法——以 test 开头的方法。
  • test_was_published_recently_with_future_question 方法中,它创建了一个 pub_date 值为 30 天后的 Question 实例。
  • 接着使用 assertls() 方法,发现 was_published_recently() 返回了 True,而我们期望它返回 False

5、修复这个 BUG

  当 pub_date 为未来某天时, Question.was_published_recently() 应该返回 False。修改 models.py 里的方法,让它只在日期是过去式的时候才返回 True

polls/models.py

代码语言:javascript复制
...
def was_published_recently(self):
    now = timezone.now()
    return now - datetime.timedelta(days=1) <= self.pub_date <= now
...

6、更全面的测试

  最好对过去、最近、将来都进行测试。于是把测试代码修改如下。

代码语言:javascript复制
# Django自带的测试接口,默认已经引入
from django.test import TestCase
# Create your tests here.
# 引入datatime模块
import datetime
from django.utils import timezone
# 引入我们的数据表
from .models import Question


class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):
        """
        未来的一个时间他的返回值应该是False
        """
        time = timezone.now()   datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)

    def test_was_published_recently_with_old_question(self):
        """
        最近一天的
        """
        time = timezone.now() - datetime.timedelta(days=1, seconds=1)
        old_question = Question(pub_date=time)
        self.assertIs(old_question.was_published_recently(), False)

    def test_was_published_recently_with_recent_question(self):
        """
        过去的
        """
        time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
        recent_question = Question(pub_date=time)
        self.assertIs(recent_question.was_published_recently(), True)

7、其他方案

  还有一个解决思路就是,我们不应该显示未来的投票,那么我们在视图显示时,就应该过滤掉过去未来这个我没有继续研究。

二、静态文件的引入

  首先,在 polls 目录下创建一个名为 static 的目录。Django 将在该目录下查找静态文件,这种方式和 Diango 在 polls/templates/ 目录下查找 template 的方式类似。

1、新建 css 样式

在静态文件目录下新建样式。

static/style.css

代码语言:javascript复制
li a {
  color: green;
}

2、引入静态文件

在模板中引入静态文件。

index.html

代码语言:javascript复制
{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}" />

3、运行项目

0 人点赞