I have a test class in Django Rest Framework which contains a function which passes the test if it is the only function in the class, or fails if it is one of two or more functions.
If I run the below code as is, i.e. def test_audio_list(self)
function remains commented out, the test passes as per the two assert statements.
If I uncomment def test_audio_list(self)
function and run the tests, the def test_audio_retrieve(self)
function will fail with a 404 whilst def test_audio_list(self)
will pass.
Here is my full test case (with def test_audio_list(self):
commented out).
class AudioTests(APITestCase):
def setUp(self):
importer() # imports data into the database
self.test_user = User(username='jim', password='monkey123', email='jim@jim.com')
self.test_user.save()
self.factory = APIRequestFactory()
self.list_view = AudioViewSet.as_view(actions={'get': 'list'})
self.detail_view = AudioViewSet.as_view(actions={'get': 'retrieve'})
# def test_audio_list(self):
# """
# Check that audo returns a 200 OK
# """
# # Make an authenticated request to the view...
# request = self.factory.get('/api/v1/audio/')
#
# self.test_user.refresh_from_db()
# force_authenticate(request, user=self.test_user)
# response = self.list_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 audio returns a 200 OK
"""
# Make an authenticated request to the view...
request = self.factory.get('/api/v1/audio/')
# force refresh of user
self.test_user.refresh_from_db()
force_authenticate(request, user=self.test_user)
response = self.detail_view(request, pk="1")
self.assertContains(response, 'audio')
self.assertEqual(response.status_code, status.HTTP_200_OK)
Running python manage.py test
on the above will produce no errors. But if I uncomment def test_audio_list(self)
function, def test_audio_retrieve(self)
will fail with the following:
======================================================================
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)
A user on Stackoverflow suggested I try running both tests within the same function as below. I can confirm that works, but from all the examples of Django tests I have seen, it appears best practice is to write individual tests in their own method. This also seems to make more sense to me as each method essentially represents a test.
def test_audio(self):
"""
All tests pass in this function
"""
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)
Iâm assuming I must be doing something wrong here, but I just cannot put my finger on it, but Iâm guessing it has something to do with the way Django treats the test database before and after objects have been accessed.
Any help is much appreciated.
Cheers,
C