问题背景
在写一些工具类的时候,需要将实例化的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
网友评论