Тесты Django Rest Framework не проходят и проходят, в зависимости от количества функций - PullRequest
1 голос
/ 23 октября 2019

У меня есть тестовый класс в Django Rest Framework, который содержит функцию, которая проходит тест, если это единственная функция в классе, или не выполняется, если это одна из двух или более функций.

Если я запускаю приведенный ниже код как есть, то есть функция def test_audio_list(self) остается закомментированной, тест проходит в соответствии с двумя утверждениями assert.

Если я раскомментирую функцию def test_audio_list(self) и запускаютесты, функция def test_audio_retrieve(self) завершится с ошибкой 404, а def test_audio_list(self) пройдет.

Вот мой полный тестовый пример (с def test_audio_list(self): закомментированным).

class AudioTests(APITestCase):
    # setup a test user and a factory
    # factory = APIRequestFactory()
    test_user = None

    def setUp(self):
        importer()
        self.test_user = User(username='jim', password='monkey123', email='jim@jim.com')
        self.test_user.save()

    # def test_audio_list(self):
    #     """
    #         Check that audo returns a 200 OK
    #     """
    #     factory = APIRequestFactory()
    #     view = AudioViewSet.as_view(actions={'get': 'list'})
    #
    #     # Make an authenticated request to the view...
    #     request = factory.get('/api/v1/audio/')
    #     force_authenticate(request, user=self.test_user)
    #     response = view(request, pk="1")
    #
    #     self.assertContains(response, 'audio/c1ha')
    #     self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_audio_retrieve(self):
        """
            Check that audo returns a 200 OK
        """
        factory = APIRequestFactory()
        view = AudioViewSet.as_view(actions={'get': 'retrieve'})

        # Make an authenticated request to the view...
        request = factory.get('/api/v1/audio/')
        force_authenticate(request, user=self.test_user)
        response = view(request, pk="1")

        self.assertContains(response, 'audio/c1ha')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

Выполнениеpython manage.py test на вышеприведенном не даст ошибок. Но если я раскомментирую функцию def test_audio_list(self), def test_audio_retrieve(self) завершится с ошибкой со следующим:

======================================================================
FAIL: test_audio_retrieve (api.tests.AudioTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/code/api/tests.py", line 96, in test_audio_retrieve
    self.assertContains(response, 'audio/c1ha')
  File "/usr/local/lib/python3.7/site-packages/django/test/testcases.py", line 446, in assertContains
    response, text, status_code, msg_prefix, html)
  File "/usr/local/lib/python3.7/site-packages/django/test/testcases.py", line 418, in _assert_contains
    " (expected %d)" % (response.status_code, status_code)
AssertionError: 404 != 200 : Couldn't retrieve content: Response code was 404 (expected 200)

Примечание . Если я изменю порядок функций в классе, то есть поместим def test_audio_retrieve(self) перед def test_audio_list(self), результат останется прежним.

Я предполагаю, что, должно быть, я что-то здесь не так делаю, но я простоне могу положить на это свой палец.

Любая помощь очень ценится.

Ура,

C

Ответы [ 2 ]

2 голосов
/ 24 октября 2019

вы использовали 'force_authenticate' более одного раза, может быть, вы можете аутентифицировать пользователя в setUp или использовать refresh_from_db

, проверьте это: Примечание: force_authenticate напрямую устанавливает request.user для пользователя в памятиэкземпляр. Если вы повторно используете один и тот же пользовательский экземпляр в нескольких тестах, которые обновляют сохраненное пользовательское состояние, вам может потребоваться вызвать refresh_from_db () между тестами.

https://www.django -rest-framework.org / api-guide / testing /

...

вы можете попробовать функции слияния, что-то вроде этого,

def test_audio(self):
    """
        Check that audio returns a 200 OK
    """
    factory = APIRequestFactory()
    view_retrieve = AudioViewSet.as_view(actions={'get': 'retrieve'})
    view_list = AudioViewSet.as_view(actions={'get': ‘list’})


    # Make an authenticated request to the view...
    request = factory.get('/api/v1/audio/')
    force_authenticate(request, user=self.test_user)

    # Retrieve
    response = view_retrieve(request, pk="1")
    self.assertContains(response, 'audio/c1ha')
    self.assertEqual(response.status_code, status.HTTP_200_OK)

    # List
    response = view_list(request, pk="1")
    self.assertContains(response, 'audio/c1ha')
    self.assertEqual(response.status_code, status.HTTP_200_OK)
1 голос
/ 26 октября 2019

Проблема, как я уже объяснил мне очень полезному пользователю на форумах Django, довольно проста.

https://forum.djangoproject.com/t/apitestcase-with-apirequestfactory/420

Я использую поле автоинкремента наидентификатор моих объектов, и, поскольку Django выполняет каждый тест, он сначала импортирует данные с вызовом importer() в def setUp(). After the each test function is run, Django then deletes the data and will again run setUp () which in turn run importer () `` `.

Это приводит к изменению идентификатора моих объектов при каждой тестовой функции в классе, который запускается.

Я статически определял идентификаторы в моем тестовом примере, полагая, что идентификатор объектов останетсяТо же самое на протяжении всего теста.

Так что вместо

# hardcoded PK
response = self.detail_view(request, pk="1")

у меня теперь есть

# dynamically assigned PK
pk = Audio.objects.first().id
response = self.detail_view(request, pk=pk)

Короче говоря, мне нужно будет динамически получить идентификатор объекта, который я хочу проверитьили, что еще лучше, создайте контрольный пример, который не зависит от импорта данных. Мне было рекомендовано использовать что-то вроде Factory Boy для генерации собственных тестовых данных в тестовых примерах.

...