2020-12-03 pytest在django中使用的几个案例

问题背景

在写一些工具类的时候,需要将实例化的django Model(大致上可以理解为表格中的数据行)作为参数传入,原生的unittest在VSCode上的支持上感觉不是很好,就尝试了一下pytest。挺好用的,同时还发现了它还支持一个更便捷的方式,编写大量检验逻辑相同的单元测试案例,让最近被单元测试困扰的我顿时醍醐灌顶般惊醒。代码范例如下(案例一二与django相关,二更加通用,三为批量写单元测试的案例):
注:以下的一些描述仅方便个人理解,如有错误欢迎评论区指正。

案例一: django混入真实的数据记录

fixture大致可以理解为在某一个作用域/阶段[scope]预执行的一些函数,一般的fixture只要写好function定义就会在恰当的时机被调用
其中作用于function yield类的fixture似乎需要将定义好的function传入test_function的参数才会被启用,同时可以将yield的object传给test_function,
而且可以做到类似unittest的setUp/tearDown的作用——在yield之前的命令将会预先执行(setUp),yield之后的命令则在test_function结束后执行(tearDown)

import pytest

from .models import MyModel
@pytest.fixture(scope="class")
def django_db_setup(): # The name must be django_db_setup
    pass
@pytest.fixture(scope="function")
def real_record():
    # Start setting up for a test function
    # similar-to setUp for scope="function" when real_record is passed as a parameter to a test function
    record = MyModel.objects.get(id=1)
    # end setting up for function
    yield record
    # Start tearing down for a test function
    # similar-to tearDown
    pass # do something afterwards

class TestRealRecord:
    @pytest.mark.django_db
    def test_real_record(self, real_record):
        assert real_record.id == 1

案例二: django混入虚拟的数据记录(实际上就是混入一个实例化的class)

如果不想连接数据库,只是写一些虚拟的参数,但同时还想要保留Model的其他方法可以在测试时被调用,可以直接使用function yield fixture将实例化的Model传入test function

import pytest

from .models import MyModel

@pytest.fixture(scope="function")
def simulated_record():
    record = MyModel(id=9527)
    yield record
class TestSimulatedRecord:
    def test_simulated_record(self, simulated_record):
        assert simulated_record.id == 9527

案例三、批量生成测试

利用pytest.mark.parametrize可以对同一类检验逻辑的测试案例快速编写单元测试,可以被VSCode识别为折叠后的一组测试,展开折叠后还可以对批量生成的单个测试案例进行调试。解锁快速生成单元测试的技能,让TDD(Test Driven Development)更加便捷。
以下每一个tuple()内的一组变量将被传入test function作为一个测试案例,所有的几个测试案例将会被分为一组折叠到VSCode的Test界面里。

import pytest  

class TestBatchRecord:
    @pytest.mark.parametrize(
        'expression, answer, correct',
        [
            ("1+1", 2, True),
            ("2+2", 3, False),
        ]
    )
    def test_parametrize(self, expression, answer, correct):
        if correct:
            assert eval(expression) == answer
        else:
            assert eval(expression) != answer

案例四、数据库只读测试

直接在开发机器的数据库中进行测试,可以结合已有的真实数据进行相对准确的读取相关的测试

import pytest

@pytest.fixture
def django_db_setup(django_db_blocker):
    from django.conf import settings
    settings.DATABASES['default']['NAME'] = 'db-name-in-develop-machine'

def TestTasksCollection:
    @pytest.mark.django_db
    def test_task_1(self):
        pass

你可能感兴趣的:(2020-12-03 pytest在django中使用的几个案例)