在 DRF 测试中使用 pytest 参数化

N.C*_*.C. 4 django django-testing pytest django-rest-framework pytest-django

现在我有这样的代码:

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
Run Code Online (Sandbox Code Playgroud)

每次因该错误而失败时:

======================================================================
ERROR: test_ordering (my_module.tests.MyTestClass)
----------------------------------------------------------------------
TypeError: test_ordering() missing 2 required positional arguments: 'field' and 'reverse_ordering'
Run Code Online (Sandbox Code Playgroud)

如何@pytest.mark.parametrizeAPITestCaseDRF 测试类中使用装饰器进行测试?
也许有另一种方法来参数化测试(但不是循环)?

hoe*_*ing 8

也许有另一种方法来参数化测试(但不是循环)?

从 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
Run Code Online (Sandbox Code Playgroud)

但是,如果您想从使用中获得真正的好处pytest,请考虑从unittest- 样式类测试转移到测试函数。pytestpytest-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
Run Code Online (Sandbox Code Playgroud)

编辑

您还可以查看parameterized库,它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
Run Code Online (Sandbox Code Playgroud)


小智 6

ApiTestCase是其子类,如pytest 文档unittest.TestCase中所述,不支持参数化:

以下 pytest 功能在 unittest.TestCase 子类中工作:

  • 标记:skip、skipif、xfail;
  • 汽车用固定装置;

以下 pytest 功能不起作用,并且由于设计理念不同,可能永远不会起作用:

  • 固定装置(自动使用固定装置除外,见下文);
  • 参数化;
  • 定制挂钩;

第三方插件可能会或可能不会正常工作,具体取决于插件和测试套件。