Django 单元测试框架介绍

Django 提供了一个测试框架,其中包含继承自 Python 标准unittest库的几个基类,以及 Django Test Client。Django Test Client 允许您模拟请求,插入测试数据以及检查应用程序的输出。

Django 还提供了一个API(LiveServerTestCase)来测试用户与浏览器的交互过程。

测试用例基类层次

测试用例基类层次

SimpleTestCase: 可以发起 HTTP 请求,跟页面,模板,URL 交互,禁止了数据库的访问;不使用数据库时,用这个基类;

TransactionTestCase: 在测试用例运行之后,会清理所有表来重置数据库; 可以运行 commit, rollback 来观察中间的状态;(需要测试事务时,使用 这个基类)

TestCase: 测试用例执行完后不清理表数据; 相反把会把每个测试用例的代码放在一个事务中执行,并且在最后自动回滚事务。(需要使用到事务做测试的时候,应使用 TransactionTestCase )

LiveServerTestCase: 在后台自动启动一个 django 服务,并且在测试结束时自动停止服务。这样可以使用 Selenium 之类的客户端来测试应用。

TestCase 在不支持事务的数据库上,行为跟 TransactionTestCase 是一样的,在测试运行完后,会清理所有的数据。

编写测试,您可以继承任何测试基类(SimpleTestCase, TransactionTestCase, TestCase, LiveServerTestCase)来定义自己的Test Case. 然后运行 “assert” 方法 检测测试结果。

from django.test import TestCase

class MyTestCase(TestCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        ...

    @classmethod
    def tearDownClass(cls):
        ...
        super().tearDownClass()
        
    def setUp(self):
        #Setup run before every test method.
        pass

    def tearDown(self):
        #Clean up run after every test method.
        pass

    def test_something_that_will_pass(self):
        self.assertFalse(False)

哪些逻辑需要测试?

Django 自带的代码(框架中实现的)逻辑不需要测试。 自己写的代码需要测试,比如自定义的页面的访问,自定义的功能菜单

测试用例目录组织

Django 使用 unittest 模块的内置测试查找机制,它将在当前工作目录下,查找任何匹配模式test*.py 命名的文件作为 Test Case。

我们为测试代码创建一个模块,为视图,表单,和其它主要的功能,分别创建文件。例如:

job/
  /testcase/
    __init__.py
    test_forms.py
    test_views.py

添加测试用例 (test_views.py)

from django.test import TestCase
from django.test import Client
from jobs.models import Job, JobTypes, Cities

class JobTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.job = Job.objects.create(job_name="Java开发工程师", job_type=JobTypes[0][0], job_city=Cities[1][0], job_requirement="精通Java开发")

    def test1(self):
        # Some test using self.job
        pass

    def test_index(self):
        client = Client()
        response = client.get('/joblist/')
        self.assertEqual(response.status_code, 200)

    def test_detail(self):
        # 使用 TestCase.self.client 作为 HTTP Client:
        response = self.client.get('/job/1/')
        self.assertEqual(response.status_code, 200)

        job = response.context['job']
        self.assertEqual(job.job_name, JobTests.job.job_name)

执行测试用例

python manage.py test

将查找当前目录下,文件名匹配 test*.py 的所有文件,并运行测试。 注意Django 的 App 自动会在应用目录下面创建一个 tests.py 的空测试用例。 如果你的测试用例所在的包名/目录名,恰好也叫 tests。 记得把 tests.py 删除。 否则 Python 将找不到 tests 包下面的测试用例。

如果您收到类似于以下的错误:

ValueError: Missing staticfiles manifest entry ...

这可能是因为默认情况下,没有运行 collectstatic,需要在运行测试之前,简单地运行collectstatic:

python manage.py collectstatic

运行特定测试用例

# 测试指定模块
python manage.py test jobs.testcase   

# 测试单个模块中的文件
python manage.py test jobs.testcase.test_views  

# 指定类
python manage.py test jobs.testcase.test_views.JobTests 

# 测试指定方法
python manage.py test jobs.testcase.test_views.JobTests.test_detail