[Python][Django] django.test.TestCaseクラスのassertRedirectsメソッドは、ドメイン名を検査しない。
環境
この記事の内容は、Ubuntu Linux 6.10, Python 2.4.4c1, Django 0.97-pre-SVN-6097で確認しました。
問題点
以下のテストケースが、失敗します。
from django.http import HttpResponseRedirect from django.test import TestCase class TestFoo(TestCase): def test_redirect(self): response = HttpResonseRedirect("http://example.com/") self.assertRedirects(response, "http://example.com/")
原因
django.test.TestCaseクラスのassertRedirectsメソッドが、リダイレクト先のドメイン名まで検査してないことが原因です。
対策
以下のようにassertRedirectsメソッドを書き換えます。
self.failUnlessEqual("http://example.com/", response["Location"])
詳細
問題のassertRedirectsメソッドは、以下のような実装になっています。
def assertRedirects(self, response, expected_url, status_code=302, target_status_code=200): """Asserts that a response redirected to a specific URL, and that the redirect URL can be loaded. Note that assertRedirects won't work for external links since it uses TestClient to do a request. """ self.assertEqual(response.status_code, status_code, ("Response didn't redirect as expected: Response code was %d" " (expected %d)" % (response.status_code, status_code))) scheme, netloc, path, query, fragment = urlsplit(response['Location']) url = path if query: url += '?' + query if fragment: url += '#' + fragment self.assertEqual(url, expected_url, "Response redirected to '%s', expected '%s'" % (url, expected_url)) :
問題となるのは、以下のコードです。
scheme, netloc, path, query, fragment = urlsplit(response['Location']) url = path if query: url += '?' + query if fragment: url += '#' + fragment self.assertEqual(url, expected_url, "Response redirected to '%s', expected '%s'" % (url, expected_url))
リダイレクト先 (response['Location']) を、urlparse.urlsplit関数でスキーマやドメイン名などに分解していますが、検査対象になっているのはパスから先だけです。このため、リダイレクト先が"http://example.com/"だったとしても、比較されるのは"/"だけであり、"http://example.com/"と比較しても失敗します。