【发布时间】:2011-07-26 14:40:13
【问题描述】:
对于我的一些 Django 视图,我创建了一个装饰器来执行基本 HTTP 访问身份验证。然而,在 Django 中编写测试用例时,我花了一段时间才弄清楚如何对视图进行身份验证。这就是我的做法。我希望有人觉得这很有用。
【问题讨论】:
标签: python django unit-testing http-authentication django-testing
对于我的一些 Django 视图,我创建了一个装饰器来执行基本 HTTP 访问身份验证。然而,在 Django 中编写测试用例时,我花了一段时间才弄清楚如何对视图进行身份验证。这就是我的做法。我希望有人觉得这很有用。
【问题讨论】:
标签: python django unit-testing http-authentication django-testing
对于 python3,您可以对 username:password 字符串进行 base64 编码:
base64.b64encode(b'username:password')
这会返回字节,因此您需要将其转换为带有.decode('ascii') 的ASCII 字符串:
完整示例:
import base64
from django.test import TestCase
class TestClass(TestCase):
def test_authorized(self):
headers = {
'HTTP_AUTHORIZATION': 'Basic ' +
base64.b64encode(b'username:password').decode("ascii")
}
response = self.client.get('/', **headers)
self.assertEqual(response.status_code, 200)
【讨论】:
(python3) 我在测试中使用这个:
credentials_string = '%s:%s' % ('invalid', 'invalid')
credentials = base64.b64encode(credentials_string.encode())
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials.decode()
以及以下视图:
import base64
[...]
type, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
auth = base64.b64decode(auth.strip()).decode()
【讨论】:
另一种方法是绕过 Django Client() 并改用 Requests。
class MyTest(TestCase):
def setUp(self):
AUTH = requests.auth.HTTPBasicAuth("username", "password")
def some_test(self):
resp = requests.get(BASE_URL + 'endpoint/', auth=AUTH)
self.assertEqual(resp.status_code, 200)
【讨论】:
requests 的响应类不能保证与 django 使用的类 100% 兼容。例如,您将没有可用的response.context。
在您的 Django TestCase 中,您可以更新客户端默认值以包含您的 HTTP 基本身份验证凭据。
import base64
from django.test import TestCase
class TestMyStuff(TestCase):
def setUp(self):
credentials = base64.b64encode('username:password')
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
【讨论】:
Client 对象的credentials() 方法更简洁地完成:self.client.credentials(HTTP_AUTHORIZATION='Basic ' + credentials)(参见django-rest-framework.org/api-guide/testing/#credentialskwargs)。
我是这样做的:
from django.test import Client
import base64
auth_headers = {
'HTTP_AUTHORIZATION': 'Basic ' + base64.b64encode('username:password'),
}
c = Client()
response = c.get('/my-protected-url/', **auth_headers)
注意:您还需要创建一个用户。
【讨论】:
base64.b64encode('username:password'.encode()).decode() 的操作,因为 base64 模块不处理 unicode 字符串。
base64.b64encode(bytes('username:password', 'utf8')).decode('utf8'),
c.get('/my-protected-url/', HTTP_AUTHORIZATION='Basic username:password'),如django docs和CGI docs所示。
假设我有一个登录表单,我使用以下技术通过测试框架登录:
client = Client()
client.post('/login/', {'username': 'john.smith', 'password': 'secret'})
然后我在其他测试中携带client,因为它已经过身份验证。你对这篇文章有什么问题?
【讨论】: