@patchを使ったコントローラのテスト

masayang2010-09-01

Python用Mockはいろいろあるけど、これは便利だと思った→Mock - Mocking and Testing Library

Djangoでこんなコントローラがあったとしよう。

def index(request):
	try:
		token = _get_cookie(request, 'token')
	except KeyError:
		return render_to_response('login.html')
	return render_to_response('welcome.html')

def _get_cookie(request, cookie):
	return request.COOKIES[cookie]

テストしたいのはtokenというCookieが存在しない時と、存在するとき。テスト側はこんな具合になる。

import mock
import myproject.myapp.views as views

	@mock.patch('myproject.myapp.views._get_cookie')
	def test_index_no_cookie(self, get_cookie_mock):
		get_cookie_mock.side_effect = KeyError('boom')
		app = TestApp(self.application)
		response = app.get('/stat/')
		self.assertEqual('200 OK', response.status)
		self.assertTrue('Login' in response)

	@mock.patch('myproject.myapp.views._get_cookie')
	def test_index_with_cookie(self, get_cookie_mock):
		get_by_key_name_mock.return_value = True
		app = TestApp(self.application)
		response = app.get('/stat/')
		self.assertEqual('200 OK', response.status)
		self.assertTrue('Welcome' in response)

@patchを使うことでviews.pyの中の任意のメソッドの挙動をそのテストが始まる寸前に入れ替えることができる。中身はmockなんだけど、いちいちmock挙動の定義をしなくてよいのがらくちん。Agile2010で聞いてきた「Slice」ってやつだな。→http://www.flickr.com/photos/29833755@N08/4895488007/