Google App Engineの開発ではPythonを使います。GAEを使ったWebアプリの開発でテスト駆動開発を行う際にも,Python的なユニットテストの文脈を活用できます。
ただし,GAEでユニットテストを行うためにはいくつかのツールやトリックが必要です。ここでは,そのテクニックを簡単に紹介します。
その1 : NoseGAEを使う
Pythonのテスト用ツールにNoseがあります。このツールは,複数のディレクトリを渡り歩いて,複数のテストコードを一気に実行してくれる便利なツールです。NoseのプラグインNoseGAEをインストールすることで,GAEアプリのテストを楽に行うことができます。「nose --with-gae」というようにオプション指定をすることでNoseGAEを利用できます。NoseGAEでは,テストコード上でGAEのモジュールやパッケージをインポートするために必要なパスをsys.pathに追加してくれます。
その2 : テスト用のstubを使う
GAEのパッケージには,テスト用に使うstubがたくさん登録されています。このstubを登録することで,GAEの認証やDatastoreを使ったWebアプリを手軽にテストできるようになります。
unittestクラスを継承して以下のような基底クラスを使います。setUp()メソッドに以下のようなコードを登録することによって,ダミーの認証モジュールやDatastore用の環境が自動的に構築されます。
import os
import unittest
from handlers import application
from webtest import TestApp
from google.appengine.api import apiproxy_stub_map
from google.appengine.api import datastore_file_stub
from google.appengine.api import mail_stub
from google.appengine.api import urlfetch_stub
from google.appengine.api import user_service_stub
from google.appengine.ext import db, search
from google.appengine.api import users
from models import UserData, UserImage
APP_ID = u'test'
AUTH_DOMAIN = 'gmail.com'
LOGGED_IN_USER = 'test@example.com'
class GAETestBase(unittest.TestCase):
def setUp(self):
# API Proxyを登録する
apiproxy_stub_map.apiproxy =\
apiproxy_stub_map.APIProxyStubMap()
# ダミーのDatastoreを登録する
stub = datastore_file_stub.DatastoreFileStub(APP_ID,'/dev/null',
'/dev/null')
apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)
# ダミーのユーザ認証用サービスを登録する
apiproxy_stub_map.apiproxy.RegisterStub(
'user', user_service_stub.UserServiceStub())
os.environ['AUTH_DOMAIN'] = AUTH_DOMAIN
os.environ['USER_EMAIL'] = LOGGED_IN_USER
# ダミーのurlfetchを登録
apiproxy_stub_map.apiproxy.RegisterStub(
'urlfetch', urlfetch_stub.URLFetchServiceStub())
# ダミーのメール送信サービスを登録
apiproxy_stub_map.apiproxy.RegisterStub(
'mail', mail_stub.MailServiceStub())
このクラスを継承してユニットテスト用のクラスを作ります。テスト用のメソッドが呼ばれる前にstartUp()メソッドが呼ばれ,自動的にstubを登録し,テスト用の環境を構築してくれます。
class UserTest(M6Base):
def test_some_function(self):
# テストコードを書く!
テストコードでは,usersやDatastore,GQLのクエリなどを自由に活用することができます。
その3 : WebTestを使う
GAEアプリケーションの実体はwgsiアプリケーションです。WebTest(http://pypi.python.org/pypi/WebTest/)はwsgiアプリをテストするための便利なツールです。テストの課程でダミーのリクエストを送ったりするには,このWebTestを使うと楽ちんです。
テストコードでは,まず以下のようにしてアプリケーションのインスタンスを作ります。
from webtest import TestApp
app = TestApp(application)
GETリクエストを送るには,appインスタンスを使って以下のようにします。
POSTリクエストで送るにはpost()メソッドを使います。引数に辞書を渡してデータを送ります。
app.post('/path/to/request', {'foo':'hoge', 'bar', 'hage'})
オマケ
Noseはテスト用のツールであるだけでなく,テスト用の便利関数をたくさん内蔵しています。テストが通らなかったときに,渡した値をログに表示してくれるので,assert文を書くよりずっと楽です。
# 引数(式)が偽の解きにassert
assert_true(some_condition)
# 2つの引数(式)が等しくなかったらassert
assert_equal(a, b)
ドキュメント(英文)。
Google App Engineは某社の案件(この時点でGAEを使える会社ってあんまりないけどね!)で絶賛活用中なんですが,とても面白いですね〜。正式リリースが待ち遠しいです:-)。