02.testing DRF With Requests
02.testing DRF With Requests
In the Terminal
Clone the repo. Your command should look something like this:
RequestsClient
Sometimes you might want to run automated tests against a real HTTP
server. This could be the Django Dev Server, or a production server like
Nginx or Apache.
Or, perhaps you want to test a REST API that’s not written with Django. We
can actually write automated tests for any REST API using these techniques.
In this short example, we’re creating four Tag objects and saving them to
the database, in the setUp() method. Then, we have a test method called
test_tag_list() which fetches the Tag objects from the API and checks that
they match what we created.
It’s similar to the test we’ve already written for the Post objects, but notice
that we’re using the live_server_url attribute to build the full URL that the
RequestsClient instance will request.
from django.test import LiveServerTestCase
from rest_framework.test import RequestsClient
class TagApiTestCase(LiveServerTestCase):
def setUp(self):
self.tag_values = {"tag1", "tag2", "tag3", "tag4"}
for t in self.tag_values:
Tag.objects.create(value=t)
self.client = RequestsClient()
def test_tag_list(self):
resp = self.client.get(self.live_server_url +
"/api/v1/tags/")
self.assertEqual(resp.status_code, 200)
data = resp.json()
self.assertEqual(len(data), 4)
self.assertEqual(self.tag_values, {t["value"] for t in
data})
Another important point to note is that we’re “cheating” a little bit here for
the sake of the demonstration. We have access to the database in the
TestCase, so we can create objects using the normal methods.
class TagApiTestCase(LiveServerTestCase):
# existing methods omitted
def test_tag_create_basic_auth(self):
self.client.auth = HTTPBasicAuth("[email protected]",
"password")
resp = self.client.post(
self.live_server_url + "/api/v1/tags/", {"value":
"tag5"}
)
self.assertEqual(resp.status_code, 201)
self.assertEqual(Tag.objects.all().count(), 5)
Whichever method you use to get the token, you’ll need to set the
Authorization HTTP header. The RequestsClient class has a writable
headers dictionary attribute, which can be used to define the HTTP headers
of the request.
Here’s another test that creates a Tag, this time fetching a token from the
token-auth endpoint (the test user was created in the setUp() method).
We then build the authorization header and set it to
self.headers["Authorization"].
class TagApiTestCase(LiveServerTestCase):
# existing methods omitted
def test_tag_create_token_auth(self):
token_resp = self.client.post(
self.live_server_url + "/api/v1/token-auth/",
{"username": "[email protected]", "password":
"password"},
)
self.client.headers["Authorization"] = "Token " +
token_resp.json()["token"]
resp = self.client.post(
self.live_server_url + "/api/v1/tags/", {"value":
"tag5"}
)
self.assertEqual(resp.status_code, 201)
self.assertEqual(Tag.objects.all().count(), 5)
Try It Out
Try It Out
Go ahead and create a file called test_tag_api.py inside the blog directory.
Copy and paste this code into it:
class TagApiTestCase(LiveServerTestCase):
def setUp(self):
get_user_model().objects.create_user(
email="[email protected]", password="password"
)
def test_tag_list(self):
resp = self.client.get(self.live_server_url +
"/api/v1/tags/")
self.assertEqual(resp.status_code, 200)
data = resp.json()
self.assertEqual(len(data), 4)
self.assertEqual(self.tag_values, {t["value"] for t in
data})
def test_tag_create_basic_auth(self):
self.client.auth = HTTPBasicAuth("[email protected]",
"password")
resp = self.client.post(
self.live_server_url + "/api/v1/tags/", {"value":
"tag5"}
)
self.assertEqual(resp.status_code, 201)
self.assertEqual(Tag.objects.all().count(), 5)
def test_tag_create_token_auth(self):
token_resp = self.client.post(
self.live_server_url + "/api/v1/token-auth/",
{"username": "[email protected]", "password":
"password"},
)
self.client.headers["Authorization"] = "Token " +
token_resp.json()["token"]
resp = self.client.post(
self.live_server_url + "/api/v1/tags/", {"value":
"tag5"}
)
self.assertEqual(resp.status_code, 201)
self.assertEqual(Tag.objects.all().count(), 5)
After saving the code above, you can run these tests (and the ones that you
wrote in the last section) with the manage.py test command.
OK
Destroying test database for alias 'default'...
Session Authentication
As an aside, what about session authentication with the RequestClient? It is
possible, but requires manual cookie management. Most of the time, if
you’re going to be testing or using an API you won’t be doing so with
session based authentication. Using the session for authentication is
normally only used for GUIs in browsers as a nicety for developers and not
so much for actual API usage. For this reason we won’t be covering it, but
in short, you’d need to authenticate to the Django login view, save the
cookie that’s returned, and then send it back in any future requests in the
Cookie HTTP header.
That’s all we’re for testing Django Rest Framework. In the next module,
we’re going to look at some advanced DRF concepts, starting with caching.
Pushing to GitHub
Pushing to GitHub
Before continuing, you must push your work to GitHub. In the terminal:
git add .
git commit -m "Finish testing DRF with requests"
Push to GitHub:
git push