SiNBLOG

140文字に入らないことを、極稀に書くBlog

Slim3 Source Code Reading No9 tester

Slim3 Source Code Reading #9 - ChugokuGTUG

に参加してきました!


今回も@ttyokoyama 殿と2人だったので、まったりと進みました。
まぁ、他の方が参加していても、まったり進むのですがw

T.Yokoyamaのブログ: Slim3 Source Code Reading #9


今日の記事はtesterです。
私がSlim3を使っている理由の1つに、UnitTestがしやすいというのがあります。
それも、このtesterのおかげ、今回は実際に中で何をやっているのかを見ていきます。
testerには、ControllerTesterとAppEngineTesterがありますが、Datastoreを扱いを行なっているであろうAppEngineTesterから読み進めることに。

Google Code Archive - Long-term storage for Google Code Project Hosting.

中を見ていると、ちょいちょい以下のような感じの分岐があります。


static {
if (!AppEngineUtil.isServer()) {
ClassLoader loader = loadLibraries();
prepareLocalServices(loader);
}
}
メソッド名から考えると、サーバーかどうか?です。
中身を見てみると、以下のようになっています。

private static final String RUNTIME = "com.google.appengine.runtime";

public static final String ENVIRONMENT_KEY = RUNTIME + ".environment";

public static final String VERSION_KEY = RUNTIME + ".version";

public static final String PRODUCTION = "Production";

public static final String DEVELOPMENT = "Development";

public static boolean isServer() {
return System.getProperty(ENVIRONMENT_KEY) != null;
}

public static boolean isDevelopment() {
return DEVELOPMENT.equals(System.getProperty(ENVIRONMENT_KEY));
}

public static boolean isProduction() {
return PRODUCTION.equals(System.getProperty(ENVIRONMENT_KEY));
}

public static String getVersion() {
return System.getProperty(VERSION_KEY);
}

isServer()だけでなく、isProduction(),isDevelopment()もあります。
設定ファイルから読み込んだ値を文字列比較しているだけですが、そんな値あるのか?と思ったら、普通に公式に書いてありました。
http://code.google.com/intl/ja/appengine/docs/java/runtime.html#The_Environment

それぞれのメソッド実行時の結果は以下の通り。

UnitTest

  • isServer():false
  • isDevelopment():false
  • isProduction():false

開発サーバでの実行

  • isServer():true
  • isDevelopment():true
  • isProduction():false

本番サーバでの実行

  • isServer():true
  • isDevelopment():false
  • isProduction():true


そして、isServer() == falseの時は環境が無いので、擬似的に作成しているようです。
その擬似的に作成されている環境というのが、TestEnvironmentのようです。
Google Code Archive - Long-term storage for Google Code Project Hosting.
AppEngineTesterはDelegateをimplementsしており、これを差し替えることができるようになっています。
DatastoreはAppIdごとにデータが登録されるため、UnitTest用にAppIdを設定して動かしているのですね。
また、authDomainやemail,adminなんかもあります。
UserServiceを利用している場合、この辺りの設定を変えることができます。


次にUnitTestごとにDatastoreがクリアされる仕組みについてです。
仕掛けが入っているのは、以下のメソッドです。

  • AppEngineTester.makeSyncCall()
  • AppEngineTester.makeAsyncCall()
  • AppEngineTester.tearDown()

上の2つのメソッドは、Datastoreを扱う時に呼び出されるメソッドです。
setUp()でApiProxy.setDelegate(this);とすることで、自分のメソッドが呼ばれるようにしています。
そして、この中でDatastoreにputされたデータのKeyを保持しています。
それらをtearDown()で一気に消しているのです。
以前、ktrwjrを利用した時に、元々登録されているデータを上書きした場合、削除されてしまっていたのは、こういう仕組みだったからですね。
ktrwjr実行時のDatastore 続編 - SinDiary
上記のエントリーで削除されなかったのも、変なエラーのせいでtearDown()が実行されなかったからですね。


今回はここまでで終わりました。
TestEnvironmentにauthDomainがあったので、Federated LoginについてもUnitTestで動かせるのかなぁという話も出たのですが、僕はFederated Loginを使ったことがないので、また今度・・・。