将 pytest 参数化与 DRF 测试一起使用
Using pytest parametrize with DRF test
现在我有这样的代码:
from rest_framework.test import APITestCase
class MyTestClass(ApiTestCase):
fixtures = ['some_fixtures.json', ]
@pytest.mark.parametrize('field, reverse_ordering', [
('id', False),
('id', True)])
def test_ordering(self, field, reverse_ordering):
# some test function
每次失败并出现以下错误:
======================================================================
ERROR: test_ordering (my_module.tests.MyTestClass)
----------------------------------------------------------------------
TypeError: test_ordering() missing 2 required positional arguments: 'field' and 'reverse_ordering'
如何在 DRF 测试 class 的 APITestCase
内部使用 @pytest.mark.parametrize
装饰器进行测试?
也许还有另一种方法来参数化测试(但不是循环)?
ApiTestCase
是 unittest.TestCase
的子类,不支持 pytest docs:
中提到的参数化
The following pytest features work in unittest.TestCase subclasses:
- Marks: skip, skipif, xfail;
- Auto-use fixtures;
The following pytest
features do not work, and probably never will due to different design
philosophies:
- Fixtures (except for autouse fixtures, see below);
- Parametrization;
- Custom hooks;
Third party plugins may or may not work well, depending
on the plugin and the test suite.
Maybe there is some another way to parametrize tests (but not loops)?
从 Python 3.4 开始,参数化在标准库中可用 subTest
:
class MyTest(APITestCase):
test_ordering_params = [('id', False), ('id', True)]
def test_ordering(self):
for field, reverse_ordering in self.test_ordering_params:
with self.subTest(field=field, reverse=reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = self.client.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data
但是,如果您想从使用 pytest
中获得真正的好处,请考虑从 unittest
式 class 测试转移到测试函数。使用 pytest
结合 pytest-django
插件的相同测试:
import pytest
from rest_framework.test import APIClient
@pytest.fixture
def apiclient():
return APIClient()
@pytest.mark.parametrize('field, reverse_ordering', [('id', False), ('id', True)])
def test_ordering(apiclient, db, field, reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = apiclient.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data
编辑
您还可以查看 parameterized
库,它为测试 class 方法提供了类似于 pytest
的参数化。示例:
from parameterized import parameterized
class MyTest(APITestCase):
@parameterized.expand([('id', False), ('id', True)])
def test_ordering(self, field, reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = self.client.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data
现在我有这样的代码:
from rest_framework.test import APITestCase
class MyTestClass(ApiTestCase):
fixtures = ['some_fixtures.json', ]
@pytest.mark.parametrize('field, reverse_ordering', [
('id', False),
('id', True)])
def test_ordering(self, field, reverse_ordering):
# some test function
每次失败并出现以下错误:
======================================================================
ERROR: test_ordering (my_module.tests.MyTestClass)
----------------------------------------------------------------------
TypeError: test_ordering() missing 2 required positional arguments: 'field' and 'reverse_ordering'
如何在 DRF 测试 class 的 APITestCase
内部使用 @pytest.mark.parametrize
装饰器进行测试?
也许还有另一种方法来参数化测试(但不是循环)?
ApiTestCase
是 unittest.TestCase
的子类,不支持 pytest docs:
The following pytest features work in unittest.TestCase subclasses:
- Marks: skip, skipif, xfail;
- Auto-use fixtures;
The following pytest features do not work, and probably never will due to different design philosophies:
- Fixtures (except for autouse fixtures, see below);
- Parametrization;
- Custom hooks;
Third party plugins may or may not work well, depending on the plugin and the test suite.
Maybe there is some another way to parametrize tests (but not loops)?
从 Python 3.4 开始,参数化在标准库中可用 subTest
:
class MyTest(APITestCase):
test_ordering_params = [('id', False), ('id', True)]
def test_ordering(self):
for field, reverse_ordering in self.test_ordering_params:
with self.subTest(field=field, reverse=reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = self.client.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data
但是,如果您想从使用 pytest
中获得真正的好处,请考虑从 unittest
式 class 测试转移到测试函数。使用 pytest
结合 pytest-django
插件的相同测试:
import pytest
from rest_framework.test import APIClient
@pytest.fixture
def apiclient():
return APIClient()
@pytest.mark.parametrize('field, reverse_ordering', [('id', False), ('id', True)])
def test_ordering(apiclient, db, field, reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = apiclient.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data
编辑
您还可以查看 parameterized
库,它为测试 class 方法提供了类似于 pytest
的参数化。示例:
from parameterized import parameterized
class MyTest(APITestCase):
@parameterized.expand([('id', False), ('id', True)])
def test_ordering(self, field, reverse_ordering):
query = ('-' if reverse_ordering else '') + field
resp = self.client.get(reverse('url-name'), {'ordering': query}, format='json')
assert resp.data