Django向けの単体テストの設計方法を理解するのに問題があります。
私の理解では、ビュー全体を一度にテストすることは不可能に思えます。リクエストの前後の状態を区別する必要があります。しかし、私はこれを設計する方法がわかりません。実生活の例はありますか?
ドキュメントを見ると、例は単純すぎてモデルにのみ焦点が当てられています。
@login_required
def call_view(request, contact_id):
profile = request.user.get_profile()
if request.POST:
form = CallsForm(profile.company, request.POST)
if form.is_valid()
return HttpResponseRedirect('/contact/' + contact_id + '/calls/')
else:
form = CallsForm(profile.company, instance=call)
variables = RequestContext(request, {'form':form}
return render_to_response('conversation.html', variables)
更新:
成功テストを動作させようとしましたが、それでも失敗します:
def test_contact_view_success(self):
# same again, but with valid data, then
self.client.login(username='username1', password='password1')
response = self.client.post('/contact/add/', {u'last_name': [u'Johnson'], })
self.assertRedirects(response, '/')
エラーメッセージ:
AssertionError: Response didn't redirect as expected: Response code was 200 (expected 302)
これは、form.is_valid()が失敗し、リダイレクトしないためだと思いますか?
NB NB!以下で説明するのは、厳密には「単体テスト」ではありません。 Djangoコードを表示するための独立した単体テストを記述することはほとんど不可能です。これは統合テストの詳細です...
あなたの見解にはいくつかの経路があることは正しいです。
GET
またはPOST
匿名ユーザー(ログインページにリダイレクトする必要があります)GET
またはPOST
は、プロファイルのないログインユーザーによって(UserProfile.DoesNotExist
_例外を発生させる必要があります)GET
ログインユーザーによる(フォームを表示する必要があります)POST
ログインユーザーによる空白データ(フォームエラーが表示されます)POST
(フォームエラーが表示されます)POST
有効なデータを持つログインユーザーによる(リダイレクトする必要があります)テスト1は実際には_@login_required
_をテストしているだけなので、スキップできます。とにかくそれをテストする傾向があります(念のため、デコレーターを使用するのを忘れた場合に備えて)。
2の失敗ケース(500エラーページ)が本当に必要なものかわかりません。私はあなたが代わりに何をしたいのかを解決します(おそらく get_or_create()
を使用するか、DoesNotExist
例外をキャッチして新しいプロファイルをそのように作成します)。
カスタム検証の量によっては、4を実際にテストする必要がない場合があります。
いずれにしても、上記のすべてを考えると、私は次のようなことをします:
_from Django.test import TestCase
class TestCalls(TestCase):
def test_call_view_denies_anonymous(self):
response = self.client.get('/url/to/view', follow=True)
self.assertRedirects(response, '/login/')
response = self.client.post('/url/to/view', follow=True)
self.assertRedirects(response, '/login/')
def test_call_view_loads(self):
self.client.login(username='user', password='test') # defined in fixture or with factory in setUp()
response = self.client.get('/url/to/view')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'conversation.html')
def test_call_view_fails_blank(self):
self.client.login(username='user', password='test')
response = self.client.post('/url/to/view', {}) # blank data dictionary
self.assertFormError(response, 'form', 'some_field', 'This field is required.')
# etc. ...
def test_call_view_fails_invalid(self):
# as above, but with invalid rather than blank data in dictionary
def test_call_view_fails_invalid(self):
# same again, but with valid data, then
self.assertRedirects(response, '/contact/1/calls/')
_
明らかに、ここでの欠点はハードコードされたURLです。テストで se reverse()
を使用するか、 RequestFactory
を使用してリクエストを作成します を使用して、ビューをメソッドとして(URLではなく)呼び出すことができます。ただし、後者の方法では、リダイレクト対象をテストするためにハードコードされた値またはreverse()
を使用する必要があります。
お役に立てれば。
Djangoには、完全な要求/応答サイクルをテストするために使用できるテストクライアントが付属しています: docs には、特定のurlおよびステータスコードとテンプレートコンテキストのアサート。また、POSTを実行し、期待どおりに成功したリダイレクトをアサートするテストも必要です。