2009年11月6日金曜日

Grails + easyb でイミフなエラー(MultipleCompilationErrorsException)が出る件

Grailsのバージョンは1.2-M3
EasyB + Grails Testingプラグイン(grails-easyb)のバージョンは1.1

ちょっと前、GrailsでRSpec的なBDDができたらいいなぁ、的なこと言ってたんですが、どうやら"easyb" というBDDフレームワークがあって、Grailsでも使用できる模様。([Java][Groovy][BDD] Grails におけるドメインクラスのユニットテスト - Grails標準テストと Easyb プラグイン使用)

人によるかもですが、私の場合xUnit系のテストケースよりはBDDのスペックの方が断然書きやすいので、早速飛びついてみました。
easyb公式ページなどを参考に、簡単なシナリオを書いてみる…

で、タイトル通り怒られました。このメッセージがよく分からない…
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, Script1.groovy: 7: unexpected token: } @ line 7, column 5.
グーグル先生とかに相談してみたんですがさっぱり。
適当に試行錯誤してみました。まずコレ。
scenario "TestScenario", {
    given "TestGiven", {
    }
    when "TestWhen", {
    }
    then "TestThen", {
        "test".shouldBe("test")
    }
}
このコードなら通してくれました。
だから何?って感じの超テストコードなんですが、ここから段々デコレーションしてみます。

といいますか、どうやら日本語が含まれてるとだめっぽい。コメントすら無理
でもシナリオ名に日本語使ったとき、たまに通ることもある…

あーもうだめだ、再現性ないとかお試しで頑張るには手強すぎる。
シナリオの書き方が違ってるのか?コメントはどこどこに入れてはいけないとか…そんなバ
サービスのインジェクションとかどうするのかなー、とか他にもいろいろ調べたかったんですけど、とりあえず様子見ということで。

しばらく標準のテストで進めるか…

2009年11月3日火曜日

[Grails] Integration Test のテストケースは、GrailsUnitTestCaseでなくGroovyTestCase を継承するらしい

Grailsのバージョンは1.2-M3

情報元はここ
http://agileice.blogspot.com/2009/09/grails-integration-testing.html

なんか、GrailsのIntegrationTestで、Config.groovyに設定した定義情報が使えないなあ、って思ってネットサーフィンしてたら、上記のページを発見。

テストケースの継承元を間違うと、テストケースのtearDownでConfig.groovyの設定情報がnullになってしまうらしいです。
  • GrailsUnitTestCaseとか、それ継承してるControllerUnitTestCaseとか
    Unitテストのみに使用
  • GroovyTestCase
    Integration Test で使用
ポイントは、Integration Testのテストケース全部にGroovyTestCase を使うことですかね。
一個でもGrailsUnitTestCaseのが混じってると、その後のテストケースで設定情報が消えます。

最近のGrailsだと、コントローラーやサービス作成時にUnit Testを生成するから、そのファイルをIntegration Testの方に移動したりしているうちに段々ごっちゃになってそう。

2009年10月29日木曜日

Grails+Acegi プログラム上でログイン・ログアウトさせる

Grailsのバージョンは1.2-M3
Acegi Security は 0.5.2

忘れないうちにメモ

import org.springframework.security.providers.UsernamePasswordAuthenticationToken as AuthToken
import org.springframework.security.context.SecurityContextHolder as SCH

class NantokaService {
    def daoAuthenticationProvider

    // ログイン処理
    void systemLogin(String username, String password) {
        def auth = new AuthToken(username, password)
        def authtoken = daoAuthenticationProvider.authenticate(auth)
        SCH.context.authentication = authtoken
    }
    // ログアウト処理
    void systemLogout() {
        SCH.context.authentication = null
    }
}

こんな感じ

2009年10月28日水曜日

7 〜モールモースの騎兵隊〜

をいまさらプレイしてます。

いまさらすぎるタイトルですが、ヴィーナス&ブレイブス買いに行ったら500円で売っていたので。
事前にプレイしとくとちょっぴり嬉しい、とどこかで聞いたような気が…

戦闘システムにランダム要素ほとんどないんで、考えがいあって楽しいです。
一問一問出題されるクイズみたいな戦闘だし、飽きないで遊べてます。
これでランダムエンカウント、とかだったら途中で投げそう。

しかし、この騎士団の連中、プライドだけ高い無能集団みたいな描かれ方してますけど、
構成メンバー全員、職種「騎士」なんだよなぁ。
それ最強集団じゃないスか?
適当にローテーションしてるだけで大抵殲滅できそう。

2009年10月27日火曜日

GrailsのUrlMappingsから直接viewに飛ばすと、localeの読み込みがおかしくなる

Grailsのバージョンは1.2-M3

ここで四時間くらい詰まった…

開発中アプリのトップページ「localhost/sampleapp/」に、"messages_ja.properties"から読み込んだメッセージを表示させていたんです。
で、URLの末尾に「?lang=de」とかつけるとそのメッセージがドイツ語(messages_de.properties)に変わるはずじゃないですか。

でも、変わらなかったんですよね。ブラウザの設定から日本語を消しても、クッキーを消しても、ずっと日本語表示のまま。

こういうときはGoogleいったあと、JIRAでしょうか。
http://jira.codehaus.org/browse/GRAILS-3871
に原因が書いてました。

Grailsのデフォルトだと、UrlMappingsに
"/"(view:"/index")

って書いてて、トップーページをviewに直接遷移させてるんですけど、
この場合、そのviewでlocaleの変更ができなくなるみたい。

いちど
"/"(controller:"foo")
でコントローラーを呼び出して、その中でindex.gspをrenderするように修正することで直りました。


だいぶ有名な事象みたいだけど、これ、直るのかな…
JIRAみると、必殺技「仕様です」みたいにも読めるけど。

GrailsのTagLibテストケースの記述

Grailsのバージョンは1.2-M3

最近のフレームワークは、開発者がテストにハマるようにいろいろ趣向こらしていて助かりますよね。
RSpec on RailsとZenTestはもうすごいよかったなぁ…
Groovyでも似たようなのないですかね、RSpec on Grails みたいなヤツ。あとZenTestみたいなヤツ。

さて、Grailsも最近のフレームワークなので、テストは結構楽しくできます。
ですが、Grailsの1.2(1.1も?)だと、ドメインモデルだのコントローラーだのは、テストケースの中でnewしてもうまくいかないらしいです。(ダイナミックメソッドが注入されずエラーになるみたい 参考:Grails1.1.xのUnitテスト)

TagLibのテストでも、同じようにnewして実行すると、メソッドやプロパティが見つからないと言われて落ちることがあります。
TagLibのユニットテストを記述するTagLibUnitTestCaseには、tagLibプロパティがあって、対象となるTagLibがセット済みなのでそれを使えばいいみたいです。

Grails をマスターするのカスタムタグを例にすると、

×
class DateTagLibTests extends GroovyTestCase {
  def dateTagLib

  void setUp(){
    dateTagLib = new DateTagLib()
  }

  void testThisYear() {
    String expected = Calendar.getInstance().get(Calendar.YEAR)
    assertEquals("the years don't match", expected, dateTagLib.thisYear())
  }
}

class DateTagLibTests extends GroovyTestCase {
  void testThisYear() {
    String expected = Calendar.getInstance().get(Calendar.YEAR)
    assertEquals("the years don't match",expected, tagLib.thisYear())
  }
}

上だと、
groovy.lang.MissingPropertyException:No such property: out for class
とか言われて落ちました。

あ、でも各テストケースの中(setUpじゃなくて)でTagLibクラスをnewすると普通にテスト通りましたね。
よくわからんです。

WebFlowってRESTfulじゃないよね…

すくなくとも、Grails(てかSpring?)の実装だと。
まったく同じ画面なのに、リロードするとどんどんURLが変化していく…
あれ、複数のURLが同じリソースを指すのはいいんだっけ。でもWebFlowのURLって特に記述的な意味とかないし。
POSTのリクエストボディに制御パラメータ入れられないかな。

Grailsが最近取り入れてるRESTfulなURLマッピングと組み合わせようとすると、訳分からんことに。
なにかうまい方法ないでしょうか。よくわからない…
とりあえず、WebFlowについてよく理解できるまでは使わないようにします。