Google App EngineとPythonでの素直な開発環境の構築(TDDができるように)

31st Jan, 2011 | Google App Engine python TDD

追記: 続編的なものを書いた。

今年は色々なことに手を出してみよう、ってことで少し前からGoogle App Engine(以下GAE)で、あるモノを作っている。モノ自体は近いうちに公表できると思う。

基本的に、Pythonと標準っぽいフレームワークだけでやってみている。作っているものがそれなりにシンプルなのと(だからこそGAE!)、GAEでそれなりの規模の開発をするのが自分自身初めてということもあり、あまり色々なレイヤーを重ねて手こずりたくなかった、ってのがその理由。

ただ、GAE初心者なので、「いやいやそれは今時ないよ」「XXの方が100倍いい」とかあったら教えてくれると嬉しいので今のところの環境を書いておくことにした。今ならスイッチ可能。

今作っているものがJSONファイルを入出力するだけのものなので、HTML生成パートみたいのはない。

1. フレームワーク

上にも書いたように、今回は、わりと単純なアプリケーションの作成なので、Google App Engine (Python)で提供されている最小限のフレームワークだけを使っている。

2. Pythonのバージョンは2.5

Google App Engineは2.5が前提 らしい。

Mac (Snow Leopard) だと、2.6と2.5の両方が入っていて、デフォルト(/usr/bin/python)のバージョンは2.6。そのため普通にGoogle App Engineの開発環境をインストールすると2.6が使われてしまっていて、最初の数時間無駄にした。

defaultコマンドで /usr/bin/python の指すバージョンを変えられるようだけど、他に影響を与えたくなかったので、今回は、

  • コマンドラインから実行するpython関連のコマンドは2.5を付けて実行(例: easy_install-2.5)
  • GoogleAppEngineLauncherで、 /usr/bin/python2.5 を指定

で、なんとかなっている。

3. ディレクトリ構成

「GAE/Pythonスタンダードなディレクトリ構成」みたいのはないようなので、いろいろな公開されているプロジェクトを参考にして以下のような配置にしてみた。最初はもうちょっと深い構成にしていたのだけど、これぐらいで十分かも。今のところModelは1ファイルにまとめてるがだいぶ増えてきたので、近い将来分離する予定。

application dir/
  models.py
  handlers/foo_handler.py
  handlers/bar_handler.py
  tests/test_foo_handler.py
  tests/bar_foo_handler.py
  main.py
  app.yaml

controller的なものをhandlerと呼ぶみたいなのでそうしてる。

4. テスティング環境

もう当然TDDだよね、ということで最初に手をつけたのがテスト環境の構築。

まず、ここしばらくWeb開発でRuby on Rails + rspecメインな生活をしていることもあり、GAE/Python上でもそれっぽいのを探してみたところ、いくつかそれっぽいのはあったのだけど、「開発が活発ではない」「使いづらそう」という感じがしたのでその方向は諦めて、普通にUnitTestでいくことにした。マイナーなものを使うよりも、自分以外の人が触ることになったときのことを考えて、ふつーなものにしておいたほうがいいかな、という判断もある。

素のUnitTestだけだといろいろいまいちなので、以下の物を入れた。

sudo easy_install-2.5 nose
sudo easy_install-2.5 nosegae
sudo easy_install-2.5 gaetestbed
sudo easy_install-2.5 webtest

使い方等は、その中のgaetestbedの README 読めばなんとなく使い方はわかるので省略。

5. doctest併用

UnitTestの他に、コードの中にテストを書ける doctest も使っている。基本的にhandlerのテストはUnitTestで、modelのテストはdoctestで書いている。

併用している理由としては、長い間うっすらと「なんかdoctestいいなー、いつか使ってみたい」と思っていたのと、今回はそれほど複雑なmodelがないというのがある。

nosegaeは、UnitTestとdoctestの両方を同時に扱えるので、この二つを混ぜても素直に全体のテストの実行が1コマンドできる。オプションに—with-doctest を付けて、

> nosetests --with-gae --with-doctest 

こんな感じ。CIでもほぼこれと同じコマンドを実行している。

6. セッション管理

GAEでは、Googleアカウントと連動したセッション+アカウント管理は標準で提供されているようだけど、今回は自前でセッション/アカウント管理をしたかったので、それは使わずに、セッション管理には gae-sessions を使ってみた。他にも色々あるのだけど、単純で軽そうだったのでこれにした。

そのライブラリの作者が作った他のライブラリとの 比較表 が参考になる。完全勝利になってるのは若干あやしいが。

このライブラリで作成したセッションに、自分で作ったユーザ用のモデルを入れるという簡単実装にした(gae-sessionsのセッションの実装自体は普通にCookieを使ったものなのでデバッグ等も簡単)。

一つ躓いた点として、gae-sessionsの導入手順をREADMEに従うと、 appengine_config.py を作ってそこでmiddlewareをセットする、となっている。ただ、ローカルの開発環境でnosegaeを使いunit testを流すと、 appengine_config.py は読んでくれないので、main.py の中で直接読み込んでごまかしてる。こんな感じ。

application = SessionMiddleware(
    webapp.WSGIApplication([....],
                           debug=True),
    cookie_key="hogehogehogehogehogehogehogehogehogehogehogehogehogehoge")

7. 本: Code in the Cloud

とりあえずGoogle App Engineを始めるにあたって何冊か読んだ本の中でそれなりに良かった奴。JavaとPython両方が書いてあるのが微妙に読みづらいが、最初に読む本、としてはそこそこいい本だと思う。テスト関係のことはほとんど載ってないけど。

8. まとめ

以上の環境で、ぼちぼちコードを書いているけど、気持ち良くTDDができている。GAE自体は思ってたよりも(話に聞いていたよりは)複雑でも難しくもなく素直だなーって印象。ドキュメントもわかりやすい。まあ、後発組は楽だなあ、と。

とは言え、もうちょっとやると壁にあたりそうなので、そのときまた何か書きたいと思う。

9. 参考にしたもの

http://www.cuberick.com/2008/11/unit-test-your-google-app-engine-models.html
https://github.com/jgeewax/gaetestbed/
http://www.slideshare.net/adeoshineye/test-driven-development-on-google-app-engine