2010-03-10

GAE/J + Slim3 [はじめてのSlim3(3)]

前回の続き、「Creating a form」の途中から...TweetControllerクラスのrun()メソッドを修正してテストがGreen(OK)となった続きから。
  • モデルクラスのTweetクラスを生成する。build.xmlのgen-modelタスクを実行し、モデル名に"Tweet"と入力すると以下のソースが作成される。
    • src/(ルートパッケージ)/model/Tweet.java
    • test/(ルートパッケージ)/model/TweetTest.java
  • 新しくソースを生成したのでテストを実行する...はい、Green(OK)(^_^)
  • この時点で、Tweetクラスはデータストアに格納するための必要最低限の属性(key, version, schemaVersion)しか持っていない。
    このクラスは"/twitter/index.jsp"から入力された「tweet(つぶやき)」を表すクラスなので、それに必要な属性(content, createdDate)を追加する。以下のフィールドを追加してgetter,setterも追加する。
    private String content;
    private Date createdDate = new Date();
  • ソースを修正したのでテスト実行...はい、Green(OK)だね(^_^)
    ここでテストクラスの作り方について...元サイトにも書かれていることだが、教科書的にテストクラスを作るとgetter, setter一つ一つにテストメソッドを作ることになるんだが、実際の開発現場ではそんな事してられない。(-_-)
    というのは、Tweetクラスのソースを見てみるとgetter, setterは、フィールドをそのまま返す、設定するとしているだけであり、問題が起こる可能性はまずない。このようなgetter, setterのテストメソッドをイチイチ作っていたら時間がいくらあっても足らない。
    ということで、実際の開発現場ではgetter, setterのテストに関しては何らかのデータ加工を行っている場合だけ作っています。...閑話休題
  • 次はサービスクラスTwitterServiceを作成する。このクラスはモデルのTweetクラスをデータストアに格納する役目を担うことになる。
    では、build.xmlのgen-serviceタスクを実行し、サービス名に"TwitterService"と入力すると以下のソースが作成される。
    • src/(ルートパッケージ)/service/TweetService.java
    • test/(ルートパッケージ)/service/TweetServiceTest.java
  • 新しくソースを生成したのでテストを実行する...今回もGreen(OK)
    ここまで何回かテストを実行してきたけど、Red(NG)となったのは確か一回だけ。Green(OK)となるのが分かっているのに何でイチイチ実行しなければならないんだ、と思うよね。たしかにTweetServiceのソースは中身空っぽだし、TweetServiceTestではnotNullValue()[nullでない]のテストなのでGreen(OK)になるのは当たり前だよね。
    でも、ここで大事なのは「テスト作成」-「テスト実行」-「ソース修正」-「テスト実行」のサイクルを回して"リズム"に乗ること。さあ、リズムに乗って次に進もう。
  • 次はTweetService#tweet()メソッドのテストを作る。テストメソッドは下記のとおり。
    @Test
    public void tweet() throws Exception {
        Map<string, object=""> input = new HashMap<string, object="">();
        input.put("content", "Hello");
        Tweet tweeted = service.tweet(input);
        assertThat(tweeted, is(notNullValue()));
        Tweet stored = Datastore.get(Tweet.class, tweeted.getKey());
        assertThat(stored.getContent(), is("Hello"));
    }
    はい、ここで「あれ?」と気づいた人(^_^)/
    ……
    そう、TweetService#tweet()メソッドはまだ存在していない、eclipseのエディタで"tweet"のところに赤い波線がついていて「メソッド tweet(Map) は型 TwitterService で未定義です」とコンパイルエラーになっている。
    これが「テスト駆動」!
    テスト=仕様を書く→テストが通る(仕様を満足する)コードを書く、という具合にテストによって駆動される。
  • では、TweetService#tweet()メソッドを実装しよう。
    eclipseでは簡単、
    • エラーの出てる箇所("tweet")にカーソルを合わせて"Ctrl+1"を押す
      Tweet tweeted = service.tweet(input);
    • ポップアップから"型 'TwitterService'のメソッド 'tweet(Map)'を作成します"を選択する。
    • TweetService#tweet(Map)メソッドが作成される
  • これでコンパイルエラーが無くなったので、テスト実行...Red(NG)(-_-)
    tweet()メソッドはeclipseが自動生成して
    "return null"
    となっているので
    "assertThat(tweeted, is(notNullValue()));"
    でNG、ということでこの時点では正常。(テストが通らないことを確認することも大事)
  • それでは、テストを通すようにtweet()メソッドを実装する。
    public Tweet tweet(Map input) {
        Tweet tweet = new Tweet();
        BeanUtil.copy(input, tweet);
        Transaction tx = Datastore.beginTransaction();
        Datastore.put(tweet);
        tx.commit();
        return tweet;
    }
    
  • では、テスト実行...Green(OK)
あともう少しなんだが、日付が変わったしまったので今日はここまで。
m(_ _)m

※追記[2010.3.10 22:00] ソースコード部分を見やすくしました。(ソースコードHTMLコンバーターを使わせて頂きました)

0 件のコメント: