0

我正在对其余的 API 进行单元测试。我正在使用 django 休息框架。APIs 正在将数据保存到数据库中并从数据库中获取数据。这两个操作都不起作用,或者如果它起作用,我无法在数据库中看到它。APIs 也使用 django-fsm,因此我需要来自 db 的相同数据用于其他测试。由于 django-fsm,测试依赖于之前的测试。api总是会改变状态。但是现在我在测试运行期间无法看到数据库中的任何数据。不知道它在哪里保存数据或在哪个数据库中。

以下是我的测试设置:-

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': join(PROJECT_ROOT, 'run', 'db_for_testing.sqlite3'),
    'TEST': {
        'NAME': 'test_db_for_testing',
    },
 },
}

下面是我的api:-

class DummyView(CreateAPIView):
    def post(self, request, *args, **kwargs):
        data = request.data.copy()
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        order = self.model(book=serializer.data.get('book'))
        order.save()
        data = {
        'status_code': 200,
        'message': 'successfully.'
        }
        return Response(data, status=status.HTTP_200_OK)

由于我的测试依赖于之前将数据保存到数据库的测试,因此其他测试也失败了。我正在使用 rest_framework 的 APITestCase。帮助伙计们。提前致谢。

4

4 回答 4

1

如果我正确理解了您的问题,则每次测试后 Django “清除”数据库(回滚或截断。)因此您需要相应地编写测试。

请参阅:https ://docs.djangoproject.com/en/1.10/topics/testing/tools/#transactiontestcase

于 2016-10-05T06:50:28.287 回答
1

TL;DR - 解决方案:使用 SimpleTestCase - 请参见下面的示例


解释

问题是 Django 为涉及数据库查询的测试提供的推荐测试类 TransactionTestCase 和子类 TestCase 将每个测试包装在事务中,以加快每次测试后重置数据库的过程。来源:Django TransactionTestCase 文档

可以通过使用作为 TransactionTestCase 的父类的 SimpleTestCase 来避免这种行为。然后,您必须通过将 allow_database_queries 设置为 True 来明确指定您希望允许数据库查询 -

另请注意,您将负责测试后需要进行的任何清洁工作。您可以通过重写 tearDownClass 类方法来做到这一点。同样,在运行测试之前,任何初始化都有一个 setUpClass 类方法。记得调用超级方法。查看文档中的完整详细信息


例子

from django.test import SimpleTestCase

class MyTestCase(SimpleTestCase):
    allow_database_queries = True

    @classmethod
    def setUpClass(cls):
        # Do your pre test initialization here.
        super(MyTestCase, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        # Do your post test clean uphere.
        super(MyTestCase, cls).tearDownClass()

    def test_add_data_through_api(self):
        # Add 'dat data
        ...

    def test_work_with_data_from_previous_test(self):
        # Work 'dat data
        ...
于 2017-12-06T20:59:28.797 回答
0

这里我的三个测试依赖于前一个。如果我将它们作为单独的测试运行,则先前的测试数据被删除,而后来的测试数据因丢失该数据而失败。

所以我让它们在两个不同的功能中都不是测试功能。最后从一个测试函数调用依赖函数。

class test_profile(APITestCase):
    def setUp(self):
        super_user = default_service.create_super_user()
        self.application = default_service.create_oath2_application(super_user.id)
        self.content_type = "application/x-www-form-urlencoded"
        self.username = "user@domain.com"
        self.password = "pass123"

    def create_profile(self):
        url = reverse('EmailSignUp')
        body = {
            "email": self.username,
            "password": self.password,
            "fullname": "Mamun Hasan"
        }
        response = self.client.post(url, body, CONTENT_TYPE=self.content_type)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        data = (json.loads(response.content))['data']
        # print("Profile", data)
        self.assertEqual(data['username'], self.username)
        self.assertEqual(data['fullname'], data['fullname'])

    def get_access_token(self):
        url = reverse('oauth2_provider:token')
        body = {
            "username": self.username,
            "password": self.password,
            "grant_type": self.application.authorization_grant_type,
            "client_id": self.application.client_id,
            "client_secret": self.application.client_secret,
        }
        response = self.client.post(url, body, CONTENT_TYPE=self.content_type)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        data = (json.loads(response.content))
        # print("AccessToken", data)
        self.assertEqual(data['token_type'], 'Bearer')
        return data

    def get_profile(self, oath2_token):
        url = reverse('GetProfile')
        authorization = oath2_token["token_type"] + ' ' + oath2_token["access_token"]
        response = self.client.get(url, CONTENT_TYPE=self.content_type, HTTP_AUTHORIZATION=authorization)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        data = (json.loads(response.content))['data']
        # print("Profile", data)
        self.assertEqual(data['username'], self.username)

    def test_dependent(self):
        self.create_profile()
        oath2_token = self.get_access_token()
        self.get_profile(oath2_token)

我没有找到任何解决方案来提交以前的 API 数据。如果有人知道请发表评论。所以我这样做了。我不知道这是最好的解决方案,但它可以工作并经过测试。

于 2019-02-21T14:38:10.707 回答
0

调用 manage.py 测试时使用 --keepdb 选项:

https://docs.djangoproject.com/en/2.1/ref/django-admin/#cmdoption-test-keepdb

它从 django 1.8 开始可用。希望这可以帮助。

于 2019-01-02T15:29:22.827 回答