I am currently developing a Django Rest Framework API with TDD. I have 15 tests and counting for two views, which doesn't seem right to me. It takes me a lot of time to write the tests and a lot of the testing logic seems redundant to me, especially because I have to check permissions for each test request. Furthermore I am unsure how to test permissions. If every view has about 3 permissions, it takes an enormous amount of tests to cover it. My questions are:
- Should my tests be so much?
- Am I testing in an efficient way?
Please comment on my way of testing and give me any advice regarding how I can improve it.
Here are my Views:
class UserListView(APIView):
permission_classes = [IsAuthenticated, IsAdminUser]
def get(self, request, format=None):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data) #if you only return the data, it is automatically HTTP_200_OK
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserDetailView(APIView):
permission_classes = [IsAuthenticated, IsAdminUser]
def get_object(self, pk):
try:
return User.objects.get(pk=pk)
except User.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
user = self.get_object(pk)
serializer = UserSerializer(user)
return Response(serializer.data)
def put(self, request, pk, format=None):
user = self.get_object(pk)
serializer = UserSerializer(user, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
And here is my tests:
class TestUserBase(APITestCase):
def setUp(self):
self.client = APIClient()
self.regular_user = User.objects.create_user(email="[email protected]", password="1234")
self.super_user = User.objects.create_superuser(email="[email protected]", password="1234")
def _super_auth(self):
self.client.force_authenticate(user=self.super_user)
def _regular_auth(self):
self.client.force_authenticate(user=self.regular_user)
class TestUserListView(TestUserBase):
url = reverse('user-list')
valid_user = {
"email": "[email protected]",
"password": "validvalid",
"first_name": "test",
"last_name": "user"
}
invalid_user = {
"email": "",
"password": "validvalid",
"first_name": "test",
"last_name": "user"
}
def test_unauthorized_users_view(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_authorized_but_forbidden_users_view(self):
self._regular_auth()
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_authorized_and_permitted_users_view(self):
self._super_auth()
response = self.client.get(self.url)
expected_data = UserSerializer(User.objects.all(), many=True).data
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected_data)
self.assertEqual(User.objects.count(), 2)
def test_unauthorized_user_create(self):
response = self.client.post(self.url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_authorized_but_forbidden_user_create(self):
self._regular_auth()
response = self.client.post(self.url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_authorized_and_permitted_invalid_user_create(self):
self._super_auth()
response = self.client.post(self.url, self.invalid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_authorized_and_permitted_valid_user_create(self):
self._super_auth()
response = self.client.post(self.url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, self.valid_user)
self.assertEqual(User.objects.count(), 3)
class TestUserDetailView(TestUserBase):
valid_url = reverse('user-detail', kwargs={"pk": 1})
invalid_url = reverse('user-detail', kwargs={"pk": 5})
valid_user = {
"email": "[email protected]",
"first_name": "bob",
"last_name": "von peer"
}
invalid_user = {
"email": "[email protected]"
}
def test_unauthorized_user_view(self):
response = self.client.get(self.valid_url)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_authorized_but_forbidden_user_view(self):
self._regular_auth()
response = self.client.get(self.valid_url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_authorized_and_permitted_valid_user_view(self):
self._super_auth()
response = self.client.get(self.valid_url)
expected_data = UserSerializer(User.objects.get(pk=1)).data
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected_data)
def test_authorized_and_permitted_invalid_user_view(self):
self._super_auth()
response = self.client.get(self.invalid_url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_unauthorized_user_update(self):
response = self.client.post(self.valid_url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_authorized_but_forbidden_user_update(self):
self._regular_auth()
response = self.client.post(self.valid_url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_authorized_and_permitted_valid_user_update(self):
self._super_auth()
response = self.client.put(self.valid_url, self.valid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.valid_user)
def test_authorized_and_permitted_invalid_user_update(self):
self._super_auth()
response = self.client.put(self.valid_url, self.invalid_user, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)