From 971578ca345c3d3bae7fd93b87c41d43483b6f05 Mon Sep 17 00:00:00 2001 From: Andreas Pelme Date: Sun, 2 Mar 2014 12:40:30 +0100 Subject: Support for running the test suite with py.test * Get rid of runtests.py * Moved test code from rest_framework/tests and rest_framework/runtests to tests * Invoke py.test from setup.py * Invoke py.test from Travis * Invoke py.test from tox * Changed setUpClass to be just plain setUp in test_permissions.py * Updated contribution guideline to show how to invoke py.test --- tests/test_testing.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/test_testing.py (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py new file mode 100644 index 00000000..8c6086a2 --- /dev/null +++ b/tests/test_testing.py @@ -0,0 +1,154 @@ +# -- coding: utf-8 -- + +from __future__ import unicode_literals +from io import BytesIO + +from django.contrib.auth.models import User +from django.test import TestCase +from rest_framework.compat import patterns, url +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.test import APIClient, APIRequestFactory, force_authenticate + + +@api_view(['GET', 'POST']) +def view(request): + return Response({ + 'auth': request.META.get('HTTP_AUTHORIZATION', b''), + 'user': request.user.username + }) + + +@api_view(['GET', 'POST']) +def session_view(request): + active_session = request.session.get('active_session', False) + request.session['active_session'] = True + return Response({ + 'active_session': active_session + }) + + +urlpatterns = patterns('', + url(r'^view/$', view), + url(r'^session-view/$', session_view), +) + + +class TestAPITestClient(TestCase): + urls = 'tests.test_testing' + + def setUp(self): + self.client = APIClient() + + def test_credentials(self): + """ + Setting `.credentials()` adds the required headers to each request. + """ + self.client.credentials(HTTP_AUTHORIZATION='example') + for _ in range(0, 3): + response = self.client.get('/view/') + self.assertEqual(response.data['auth'], 'example') + + def test_force_authenticate(self): + """ + Setting `.force_authenticate()` forcibly authenticates each request. + """ + user = User.objects.create_user('example', 'example@example.com') + self.client.force_authenticate(user) + response = self.client.get('/view/') + self.assertEqual(response.data['user'], 'example') + + def test_force_authenticate_with_sessions(self): + """ + Setting `.force_authenticate()` forcibly authenticates each request. + """ + user = User.objects.create_user('example', 'example@example.com') + self.client.force_authenticate(user) + + # First request does not yet have an active session + response = self.client.get('/session-view/') + self.assertEqual(response.data['active_session'], False) + + # Subsequant requests have an active session + response = self.client.get('/session-view/') + self.assertEqual(response.data['active_session'], True) + + # Force authenticating as `None` should also logout the user session. + self.client.force_authenticate(None) + response = self.client.get('/session-view/') + self.assertEqual(response.data['active_session'], False) + + def test_csrf_exempt_by_default(self): + """ + By default, the test client is CSRF exempt. + """ + User.objects.create_user('example', 'example@example.com', 'password') + self.client.login(username='example', password='password') + response = self.client.post('/view/') + self.assertEqual(response.status_code, 200) + + def test_explicitly_enforce_csrf_checks(self): + """ + The test client can enforce CSRF checks. + """ + client = APIClient(enforce_csrf_checks=True) + User.objects.create_user('example', 'example@example.com', 'password') + client.login(username='example', password='password') + response = client.post('/view/') + expected = {'detail': 'CSRF Failed: CSRF cookie not set.'} + self.assertEqual(response.status_code, 403) + self.assertEqual(response.data, expected) + + +class TestAPIRequestFactory(TestCase): + def test_csrf_exempt_by_default(self): + """ + By default, the test client is CSRF exempt. + """ + user = User.objects.create_user('example', 'example@example.com', 'password') + factory = APIRequestFactory() + request = factory.post('/view/') + request.user = user + response = view(request) + self.assertEqual(response.status_code, 200) + + def test_explicitly_enforce_csrf_checks(self): + """ + The test client can enforce CSRF checks. + """ + user = User.objects.create_user('example', 'example@example.com', 'password') + factory = APIRequestFactory(enforce_csrf_checks=True) + request = factory.post('/view/') + request.user = user + response = view(request) + expected = {'detail': 'CSRF Failed: CSRF cookie not set.'} + self.assertEqual(response.status_code, 403) + self.assertEqual(response.data, expected) + + def test_invalid_format(self): + """ + Attempting to use a format that is not configured will raise an + assertion error. + """ + factory = APIRequestFactory() + self.assertRaises(AssertionError, factory.post, + path='/view/', data={'example': 1}, format='xml' + ) + + def test_force_authenticate(self): + """ + Setting `force_authenticate()` forcibly authenticates the request. + """ + user = User.objects.create_user('example', 'example@example.com') + factory = APIRequestFactory() + request = factory.get('/view') + force_authenticate(request, user=user) + response = view(request) + self.assertEqual(response.data['user'], 'example') + + def test_upload_file(self): + # This is a 1x1 black png + simple_png = BytesIO(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\rIDATx\x9cc````\x00\x00\x00\x05\x00\x01\xa5\xf6E@\x00\x00\x00\x00IEND\xaeB`\x82') + simple_png.name = 'test.png' + factory = APIRequestFactory() + factory.post('/', data={'image': simple_png}) -- cgit v1.2.3 From bf09c32de8f9d528f83e9cb7a2773d1f4c9ab563 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 19 Aug 2014 13:28:07 +0100 Subject: Code linting and added runtests.py --- tests/test_testing.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py index 1b126e00..9c472026 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -28,7 +28,8 @@ def session_view(request): }) -urlpatterns = patterns('', +urlpatterns = patterns( + '', url(r'^view/$', view), url(r'^session-view/$', session_view), ) @@ -142,7 +143,8 @@ class TestAPIRequestFactory(TestCase): assertion error. """ factory = APIRequestFactory() - self.assertRaises(AssertionError, factory.post, + self.assertRaises( + AssertionError, factory.post, path='/view/', data={'example': 1}, format='xml' ) -- cgit v1.2.3 From 2dfe75c23a041493bc83514d8e9e9268b79072d9 Mon Sep 17 00:00:00 2001 From: Jones Chi Date: Fri, 3 Oct 2014 14:42:49 +0800 Subject: Fix follow does not work on APIClient Handle follow just like Django's Client. --- tests/test_testing.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py index 9c472026..9fd5966e 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -5,6 +5,7 @@ from django.conf.urls import patterns, url from io import BytesIO from django.contrib.auth.models import User +from django.shortcuts import redirect from django.test import TestCase from rest_framework.decorators import api_view from rest_framework.response import Response @@ -28,10 +29,16 @@ def session_view(request): }) +@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) +def redirect_view(request): + return redirect('/view/') + + urlpatterns = patterns( '', url(r'^view/$', view), url(r'^session-view/$', session_view), + url(r'^redirect-view/$', redirect_view), ) @@ -111,6 +118,46 @@ class TestAPITestClient(TestCase): response = self.client.get('/view/') self.assertEqual(response.data['auth'], b'') + def test_follow_redirect(self): + """ + Follow redirect by setting follow argument. + """ + response = self.client.get('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.get('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + + response = self.client.post('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.post('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + + response = self.client.put('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.put('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + + response = self.client.patch('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.patch('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + + response = self.client.delete('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.delete('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + + response = self.client.options('/redirect-view/') + self.assertEqual(response.status_code, 302) + response = self.client.options('/redirect-view/', follow=True) + self.assertIsNotNone(response.redirect_chain) + self.assertEqual(response.status_code, 200) + class TestAPIRequestFactory(TestCase): def test_csrf_exempt_by_default(self): -- cgit v1.2.3 From 78312d44d1e1a7f43daacd1614be2008eb77a0de Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 12 Dec 2014 13:13:08 +0000 Subject: Client.logout() also clears any force_authenticate --- tests/test_testing.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py index 9fd5966e..f5d2cbcd 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -109,7 +109,7 @@ class TestAPITestClient(TestCase): def test_can_logout(self): """ - `logout()` reset stored credentials + `logout()` resets stored credentials """ self.client.credentials(HTTP_AUTHORIZATION='example') response = self.client.get('/view/') @@ -118,6 +118,18 @@ class TestAPITestClient(TestCase): response = self.client.get('/view/') self.assertEqual(response.data['auth'], b'') + def test_logout_resets_force_authenticate(self): + """ + `logout()` resets any `force_authenticate` + """ + user = User.objects.create_user('example', 'example@example.com', 'password') + self.client.force_authenticate(user) + response = self.client.get('/view/') + self.assertEqual(response.data['user'], 'example') + self.client.logout() + response = self.client.get('/view/') + self.assertEqual(response.data['user'], b'') + def test_follow_redirect(self): """ Follow redirect by setting follow argument. -- cgit v1.2.3 From e3b16c8bc631d5be599776c483ee0488cef9c288 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 12 Dec 2014 13:16:18 +0000 Subject: Python 3 test fix --- tests/test_testing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py index f5d2cbcd..6fce8464 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -128,7 +128,7 @@ class TestAPITestClient(TestCase): self.assertEqual(response.data['user'], 'example') self.client.logout() response = self.client.get('/view/') - self.assertEqual(response.data['user'], b'') + self.assertEqual(response.data['user'], '') def test_follow_redirect(self): """ -- cgit v1.2.3 From 8825b258caa0c51d6dcdb3529dc433c75a76339d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 12 Dec 2014 13:22:24 +0000 Subject: Clean up import ordering --- tests/test_testing.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'tests/test_testing.py') diff --git a/tests/test_testing.py b/tests/test_testing.py index 6fce8464..87d2b61f 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -1,15 +1,13 @@ -# -- coding: utf-8 -- - +# encoding: utf-8 from __future__ import unicode_literals from django.conf.urls import patterns, url -from io import BytesIO - from django.contrib.auth.models import User from django.shortcuts import redirect from django.test import TestCase from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.test import APIClient, APIRequestFactory, force_authenticate +from io import BytesIO @api_view(['GET', 'POST']) -- cgit v1.2.3