Yesterday my father told me that two or three days ago my aunt had died suddenly in cancer. She had finished fourty to fifty years life that is shorter than Japanese average.
Few years she had been bothered by such a severe hyperesthesia that she couldn't have spend an ordinary life which every middle age ladies can enjoy.
When she and my father were child, she lived in more healthy than my father.
Because she had been seeing my father's weakness, she decided to get a jobs in nurse.
She had wide knowlege about health. She would have been a skillful nurse, if she had not has a severe hyperesthesia.
More excelent her career became, she lost her healthiness.
Finally her health had got lost severely. She had decided to live alone without jobs.
Today her funeral is going to be held.
I cannot take part in it, but I pray for her soul.
2012年1月22日日曜日
2012年1月17日火曜日
TDDと勉強法
昨晩の帰り際にふと思い立ったので、覚書程度に。
オレが高校3年生の時、11月、突如思い立って、物理の勉強に没頭した。
単純な
その時に役に立った本が『坂間の物理』という本で、えっと、某台予備校に通っていたかつて学生だった人の何人かは知っている物理教師の本だった。
まあ、その教師の物理の授業を受けたことがある人は知っていると思うけど、あんなのは受験生が期待する授業ではない。
ただ、あの人のやっていることはTDDという観点で見ると、非常に理にかなっている。
彼の教育プロセスをもう一度思い出してみた。
なんか、TDDっぽい教育だと思った。
一般的なTDDスタイルの開発
なんか似ている。
オレは思い立った1ヶ月間『坂間の物理』に掲載されている108問の問題をすべて、この三段階の方法で演習した。
結果、予備校生になっても物理は超得点源になって、某大学模試で物理の偏差値78とかありえない値を取得した。
ペアプロの学習効果はよく言われているが、実際にはTDDもプログラマーの成長に欠かせない要素があるのではないかと思う。
テストを書くということは、実装を書くのに加えて、テストコードも書かなければならないから、一見無駄に思える。
だが、それは上記に上げたプロセスのまだ第一段階なのではなかろうか?
本当にTDDが力を発揮してくるのは第二段階、第三段階を超えた時で、エレガントな実装を出来るようになった時には、オレが物理を超得意となった状態と同じく、プログラマーはプログラムの実装を超得意と思って自信をもって取り組むことが出来るようになるのではないかと思う。
まあ、脳足りんの考えたことなので、実証もされてないことだし、単なる妄想かもしれない。
ちなみに坂間先生というのは、自分の授業について、後で答えを書いてきてごらん、添削してあげるからと言っていたので、毎週授業でやった範囲の部分の真似を持っていていたら、ちゃんとレビューしてくれた。この部分はこう書くともっとエレガントになるとか、ここは読みづらいからもっと大きく書けとか。
テストも同様で、それをレビューしてエレガントなコードはどういうものなのかを考えていけば、プログラマーは大いに成長するのではないだろうか。
…
ちなみに、坂間先生はオレが通っていた○進スーパーコースでは人気なかったです。
おわり。
オレが高校3年生の時、11月、突如思い立って、物理の勉強に没頭した。
単純な
ma = Fとかいう公式に載っていることではなくて、もっと運動方程式とは何なのかと根源的に追い詰めた。その時に役に立った本が『坂間の物理』という本で、えっと、某台予備校に通っていたかつて学生だった人の何人かは知っている物理教師の本だった。
まあ、その教師の物理の授業を受けたことがある人は知っていると思うけど、あんなのは受験生が期待する授業ではない。
ただ、あの人のやっていることはTDDという観点で見ると、非常に理にかなっている。
彼の教育プロセスをもう一度思い出してみた。
- 真似をさせる→答えは教えてやる。間違えてもいいから、こうなるように計算してみろというのである。
- 徹底的に真似をさせる→教えてやった答えを、問題文を見ないようにして解けというのである。
- 高速化させる→もっとエレガントに解答を書けというのである。
なんか、TDDっぽい教育だと思った。
一般的なTDDスタイルの開発
- 答えはわかっている。テストは落ちる。
- 答えが合うように、実装を作る。
- もっとエレガントになるように実装を洗練させる。
なんか似ている。
オレは思い立った1ヶ月間『坂間の物理』に掲載されている108問の問題をすべて、この三段階の方法で演習した。
結果、予備校生になっても物理は超得点源になって、某大学模試で物理の偏差値78とかありえない値を取得した。
ペアプロの学習効果はよく言われているが、実際にはTDDもプログラマーの成長に欠かせない要素があるのではないかと思う。
テストを書くということは、実装を書くのに加えて、テストコードも書かなければならないから、一見無駄に思える。
だが、それは上記に上げたプロセスのまだ第一段階なのではなかろうか?
本当にTDDが力を発揮してくるのは第二段階、第三段階を超えた時で、エレガントな実装を出来るようになった時には、オレが物理を超得意となった状態と同じく、プログラマーはプログラムの実装を超得意と思って自信をもって取り組むことが出来るようになるのではないかと思う。
まあ、脳足りんの考えたことなので、実証もされてないことだし、単なる妄想かもしれない。
ちなみに坂間先生というのは、自分の授業について、後で答えを書いてきてごらん、添削してあげるからと言っていたので、毎週授業でやった範囲の部分の真似を持っていていたら、ちゃんとレビューしてくれた。この部分はこう書くともっとエレガントになるとか、ここは読みづらいからもっと大きく書けとか。
テストも同様で、それをレビューしてエレガントなコードはどういうものなのかを考えていけば、プログラマーは大いに成長するのではないだろうか。
…
ちなみに、坂間先生はオレが通っていた○進スーパーコースでは人気なかったです。
おわり。
2012年1月14日土曜日
Grails2.0のDomainをTDDしてみる。
出展はいつもどおりの『Grails徹底入門』
の96ページにあるモデル図から。
ここから、今回の対象部分のモデルを抜き出したのが以下の図。
で、今回はこのうち、Shipmentの部分をTDDしていきます。
ドメインの作成はいたって簡単です。
これだけで、
なお、テストクラスはデフォルトでは
それをテストに書きます。
なお、Grails2.0はJUnit4対応しているので、アノテーションを用いることでテストメソッドであることを示せます。
ここではテストメソッド名も変更しています。
また、
実行結果は次のようになります。
まあ、
暗黙の
そこで、実装に行きます。
とりあえず、
この状態でテストを実行してみます。
というわけで、とくに
Grailsのドメインクラスにあるフィールドはデフォルトで
(出荷予定であれば話は別ですが…)
それをテストに書きます。
翌日の日付であった場合は、エラーとなるというテストを記述しています。
で、テストの結果は次のとおりになります。
まず、
落ちた原因を探りたいので、一度テストを修正します。
テスト結果
内容からわかるようにエラーがないということです。
ここで、正しく
制約を加えたらテストを実行します。
ちゃんとパスします。
念のため、今日も大丈夫か確認します。
ポイントとしては、
理由は、これから他にも
テストの実行結果は次のようになります。
次にリレーションに関するフィールドの追加とテストです。
先に掲載したモデルから、
こういうのを一般的には一対一の片方向の関連とかなんとかいうらしいです。
Grailsのドメインにおいて、これを実現するのが
では、おもむろにテストを書きます。
ここでは、暗黙の
まずは
テストを実行します。
なんか、関係のない
このあたりはGrailsの改善に期待するしかなさそうです…
テストが通るように実装をします。
実装したら、テストを実行します。
今回はすんなり通りました。何だったんでしょう?あの落ちっぷりは…
さて、
うむ、ほんとうは
の96ページにあるモデル図から。
ここから、今回の対象部分のモデルを抜き出したのが以下の図。
で、今回はこのうち、Shipmentの部分をTDDしていきます。
ドメインの作成
ドメインの作成はいたって簡単です。
$ grails create-domain-class Shipment
これだけで、
Shipmentドメインクラスと、ShipmentTestsテストクラスが生成されます。Shipment.groovy
package grailsshop
class Shipment {
static constraints = {
}
}
Shipment.groovy
package grailsshop
import grails.test.mixin.*
import org.junit.*
@TestFor(Shipment)
class ShipmentTests {
void testSomething() {
fail()
}
}
なお、テストクラスはデフォルトでは
failになるようになっています。最初のテスト
Shipment(出荷)はイベントなので、必ず日付をもちます。したがって、nullは禁止です。それをテストに書きます。
なお、Grails2.0はJUnit4対応しているので、アノテーションを用いることでテストメソッドであることを示せます。
ここではテストメソッド名も変更しています。
また、
validateのテストになりますので、前回の結論に書いておいたようにmockForConstraintsTestsメソッドを最初に用いておきます。Shipment.groovy
package grailsshop
import grails.test.mixin.*
import org.junit.*
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
実行結果は次のようになります。
grails> test-app grailsshop.Shipment
| Running 1 unit test... 1 of 1
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.validate() == false
| | |
| true false
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:20)
| Completed 1 unit test, 1 failed in 1930ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
まあ、
Shipmentにはdateというフィールドをまだ実装していないので、落ちるのもやむなしです。暗黙のnullable : false
そこで、実装に行きます。
とりあえず、
ShipmentクラスにDate型のdateを持たせてみます。Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static constraints = {
}
}
この状態でテストを実行してみます。
grails> test-app grailsshop.Shipment
| Completed 1 unit test, 0 failed in 152ms
| Tests PASSED - view reports in target/test-reports
grails>
というわけで、とくに
nullチェックの実装を入れていませんが、テストが通りました。Grailsのドメインクラスにあるフィールドはデフォルトで
nullableがfalseのようです。適当に制約をいれていく
Shipment(出荷)、捉え方によるけど、未来の日付は入れられないことにしておきましょう。(出荷予定であれば話は別ですが…)
それをテストに書きます。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
assert shipment.validate() == false
assert shipment.errors[object] == 'max'
}
}
dayFromToday(int)は今日からの日付を取るユーティリティーメソッドです。0を指定すると今日の日付、1を指定すると明日の日付が取得できます。翌日の日付であった場合は、エラーとなるというテストを記述しています。
で、テストの結果は次のとおりになります。
grails> test-app grailsshop.Shipment
| Running 2 unit tests... 1 of 2
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.validate() == false
| | |
| true false
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:24)
| Completed 2 unit tests, 1 failed in 96ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
まず、
validate()でAssertが落ちます。落ちた原因を探りたいので、一度テストを修正します。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
shipment.validate()
assert shipment.errors[object] == 'max'
}
}
テスト結果
grails> test-app grailsshop.Shipment
| Running 2 unit tests... 1 of 2
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.errors[object] == 'max'
| | || |
| | |date false
| | null
| org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 0 errors
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:25)
| Completed 2 unit tests, 1 failed in 81ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
内容からわかるようにエラーがないということです。
ここで、正しく
validate()でエラーとなるようにドメインクラスを修正します。Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static constraints = {
date(max: new Date())
}
}
制約を加えたらテストを実行します。
grails> test-app grailsshop.Shipment
| Completed 2 unit tests, 0 failed in 124ms
| Tests PASSED - view reports in target/test-reports
grails>
ちゃんとパスします。
念のため、今日も大丈夫か確認します。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
assert shipment.validate()
assert shipment.errors[object] == 'max'
shipment = new Shipment(date: dayFromToday(0))
shipment.validate()
assert shipment.errors[object] == null
}
}
ポイントとしては、
validate()が通るケースでは、assert shipment.validate() == trueのテストを行わない方が良いです。理由は、これから他にも
validateするものが増えるので、後々にテストが通らなくなるからです。テストの実行結果は次のようになります。
grails> test-app grailsshop.Shipment
| Completed 2 unit tests, 0 failed in 81ms
| Tests PASSED - view reports in target/test-reports
grails>
リレーションに関するフィールドの追加とテスト
次にリレーションに関するフィールドの追加とテストです。
先に掲載したモデルから、
ShipmentとWarehouse、Orderの関係は、次のようになります。Shipment-WarehouseShipmentからみてWarehouseは唯一つ存在し、かつその参照先を保持する必要がある。WarehouseからみてShipmentは0または1つ存在し、その参照先は保持しなくて良い。Shipment-OrderShipmentからみてOrderは唯一つ存在し、かつその参照先を保持する必要がある。OrderからみてShipmentは0または1つ存在し、その参照先は保持しなくて良い。
こういうのを一般的には一対一の片方向の関連とかなんとかいうらしいです。
Grailsのドメインにおいて、これを実現するのが
belongsToです。では、おもむろにテストを書きます。
ここでは、暗黙の
nullable : falseを利用します。まずは
Orderから…ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateOrder() {
mockForConstraintsTests(Shipment)
def object = 'order'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
テストを実行します。
grails> test-app grailsshop.Shipment
| Running 3 unit tests... 1 of 3
| Failure: validateDate(grailsshop.ShipmentTests)
| java.lang.NoSuchMethodError: grailsshop.Shipment.getBelongsTo()Ljava/lang/Object;
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher$GetterPropertyFetcher.get(ClassPropertyFetcher.java:326)
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getPropertyValueWithFetcher(ClassPropertyFetcher.java:218)
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getStaticPropertyValue(ClassPropertyFetcher.java:233)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.establishRelationshipOwners(GormMappingConfigurationStrategy.java:271)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getOwningEntities(GormMappingConfigurationStrategy.java:716)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.initialize(AbstractPersistentEntity.java:79)
at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntityInternal(AbstractMappingContext.java:150)
at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:135)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:124)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:120)
| Failure: validateDate(grailsshop.ShipmentTests)
| java.lang.NullPointerException
at org.grails.datastore.mapping.core.DatastoreUtils.unbindSession(DatastoreUtils.java:362)
at grails.test.mixin.domain.DomainClassUnitTestMixin.shutdownDatastoreImplementation(DomainClassUnitTestMixin.groovy:109)
| Running 3 unit tests... 2 of 3
| Failure: validateOrder(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.errors[object] == 'nullable'
| | || |
| | |order false
| | null
| org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 1 errors
| Field error in object 'grailsshop.Shipment' on field 'date': rejected value [null]; codes [grailsshop.Shipment.date.nullable.error.grailsshop.Shipment.date,grailsshop.Shipment.date.nullable.error.date,grailsshop.Shipment.date.nullable.error.java.util.Date,grailsshop.Shipment.date.nullable.error,shipment.date.nullable.error.grailsshop.Shipment.date,shipment.date.nullable.error.date,shipment.date.nullable.error.java.util.Date,shipment.date.nullable.error,grailsshop.Shipment.date.nullable.grailsshop.Shipment.date,grailsshop.Shipment.date.nullable.date,grailsshop.Shipment.date.nullable.java.util.Date,grailsshop.Shipment.date.nullable,shipment.date.nullable.grailsshop.Shipment.date,shipment.date.nullable.date,shipment.date.nullable.java.util.Date,shipment.date.nullable,nullable.grailsshop.Shipment.date,nullable.date,nullable.java.util.Date,nullable]; arguments [date,class grailsshop.Shipment]; default message [Property [{0}] of class [{1}] cannot be null]
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateOrder(ShipmentTests.groovy:39)
| Completed 3 unit tests, 3 failed in 75ms
| Packaging Grails application.....
| Compiling 1 source files.
grails>
なんか、関係のない
validateDateまで落ちてしまいました(´・ω・`)このあたりはGrailsの改善に期待するしかなさそうです…
テストが通るように実装をします。
Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static belongsTo = [
/**
* 発注.
*/
order : Order
]
static constraints = {
date(max: new Date())
}
}
実装したら、テストを実行します。
grails> test-app grailsshop.Shipment
| Completed 3 unit tests, 0 failed in 168ms
| Tests PASSED - view reports in target/test-reports
grails>
今回はすんなり通りました。何だったんでしょう?あの落ちっぷりは…
さて、
Warehouseの方も同様にテスト、実装します。ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateWarehouse() {
mockForConstraintsTests(Shipment)
def object = 'warehouse'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static belongsTo = [
/**
* 発注.
*/
order : Order,
/**
* 倉庫.
*/
warehouse : Warehouse
]
static constraints = {
date(max: new Date())
}
}
結論
うむ、ほんとうは
@Mockをやりたかったのだが、書いている量が半端なくなってきたので、次回に…2012年1月10日火曜日
Objective-CのUnit Testを書いてみた
ツイッター上で、Objective-Cの本について、
とつぶやいたお陰で、なんかUnit Testを書くことになったような雰囲気…
とありあえず、簡単なテストを書いてみた。
ここに、画面の操作(Controller)と画面表示(View)に関係のない部分 = 日付のフォーマット(Model)があったので、Modelの部分についてはテストを書けるだろうということで、書いたテストが上の2つのテストです。
NSString系の文字列の扱いがよくわかっていないので、時間が妙にかかった。
このあたりは本で知識を補強していく必要があるっぽい。
テストを書こう
とつぶやいたお陰で、なんかUnit Testを書くことになったような雰囲気…
とありあえず、簡単なテストを書いてみた。
FirstViewController.mは、まあ、名前から想像できる通り、画面の操作系のオブジェクトです。ここに、画面の操作(Controller)と画面表示(View)に関係のない部分 = 日付のフォーマット(Model)があったので、Modelの部分についてはテストを書けるだろうということで、書いたテストが上の2つのテストです。
やってみてちょっと判ったこと
NSString系の文字列の扱いがよくわかっていないので、時間が妙にかかった。
このあたりは本で知識を補強していく必要があるっぽい。
2012年1月9日月曜日
#日本鼻メガネの会 に参加してみた的な
参加までの経緯
なんのことやらわからず参加しました。
多分、参加することになった理由は謎のハッシュタグ
#日本鼻メガネの会
ですね。
なんですかこの怪しげな響きは…と調べていくと、
日本鼻メガネの会 新年会
十分に怪しい…
謳い文句もなんだか怪しい…
IT系勉強会でひそかなブームになりつつある鼻メガネを愛でる会です
え、ブーム、そんなのブームなのか?!
だが、もっと怪しいのが参加者の面々。
Twitterでよく見かける人ばっかり…
定員15人で、参加者14人、キャンセル1人だったので、参加できるっぽかったので、とりあえず趣旨はよくわからんが参加ポチった。
当日
とりあえず、鼻メガネは必要そうだったので、歌舞伎町のドンキホーテで鼻だけ購入。
会場は新宿角海老の裏。参考:新宿角海老(R-20限定)
とりあえず、店の名前よく覚えていなかったので(今でも思い出せない…)新宿角海老のあたりをウロウロしていたら、風俗関連のお兄さんに「お兄さん、どのお店探しているの?」と声をかけられました。
いや、おっ◯いパブとか興味ないから…
とりあえず、@shinyaa31さんのおかげで会場にたどり着きましたが、
ツイッターアイコンしか知らんので顔が誰が誰かようわからん…
いつもどおり、コーラをがぶ飲みしておきました。
当日の様子などは以下のエントリーなどが詳しいのでそちらを参照下さい。
- 2012/01/07 日本鼻メガネの会 新年会 #日本鼻メガネの会
- [勉強会]日本鼻メガネの会 新年会に参加してきた #日本鼻メガネの会
- 2012-01-09 #日本鼻メガネの会 新年会に参加しました
- #日本鼻メガネの会 新年会に参加してきた
他にも多数あるけど、まあ、ようまとめきれんです。
結論
勉強会で知り合ったクラスタとか、Twitterで知り合ったクラスタとの、gdgdなオフ会意見交換会も面白いですね。
2012年1月7日土曜日
Grails2.0のDomainのUnit Testハマリどころ
今日はGrailsのDomainテストのハマリどころについてのメモです。
と言っても、ひとつしか書いていませんが…
前回の記事では
このテストで分かるのはこのままでは登録できないということです。
ただ、残念なことに何が悪くて
この際に役立つのがPOGOに自動的に付与される
この
上記のコードの例では、
したがって、
では、本当に
このテストは
おもむろに実行します。
実行結果(一部略)
実際はもっと長ったらしいエラーメッセージが出ますが、Field errorの部分の内容を見るかぎりではこのテストは通ってもよさそうなものなのですが、ダメなんですね。
書き方間違えたのかと思って、公式サイトを確認しましたが、合っているようです。
そんなこんなで、混乱していたところ、Grailsの第一人者であられる@tyamaさんからアドバイスをいただきました。
ふむ、
というわけで、おもむろに入れてテストを通してみる。
そして、テスト実行。
おお、通った。
とりあえず、
と言っても、ひとつしか書いていませんが…
ConstraintsのValidationテスト
前回の記事では
Validationのテストについて少し取り扱っています。Book.groovy
class Book {
String name
String author
int price
static constraints = {
name (blank: false)
author (blank: false)
price (min: 0)
}
}
BookTests.groovy
@Test
void validation() {
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
}
このテストで分かるのはこのままでは登録できないということです。
ただ、残念なことに何が悪くて
Validationで引っかかったのかがわかりません。この際に役立つのがPOGOに自動的に付与される
errorsというメンバーです。くせもののerrors
この
errorsにはvalidate()でチェックされたエラーのスナップショットが格納されています。上記のコードの例では、
Bookクラスには著者の情報が未設定であり、不適切な価格情報が設定されているという状態です。したがって、
errorsにはauthorとpriceというメンバーが存在します、いや、するはずです。では、本当に
priceで引っかかっているのか確認するテストを書きます。
@Test
void validation() {
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
assert book.errors['price'] == 'min'
}
このテストは
validate()でチェックされたエラーのうち、priceに対するエラーはminであることをテストします。おもむろに実行します。
実行結果(一部略)
| Failure: validateQuantity(grailsshop.Book)
| Assertion failed:
assert book.errors['price'] == 'min'
| | | |
| | | false
| | Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
| Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
grailsshop.Book: null
実際はもっと長ったらしいエラーメッセージが出ますが、Field errorの部分の内容を見るかぎりではこのテストは通ってもよさそうなものなのですが、ダメなんですね。
書き方間違えたのかと思って、公式サイトを確認しましたが、合っているようです。
mockForConstraints
そんなこんなで、混乱していたところ、Grailsの第一人者であられる@tyamaさんからアドバイスをいただきました。
ふむ、
mockForConstraints(Class<T>)を使えばよいとな。というわけで、おもむろに入れてテストを通してみる。
@Test
void validation() {
mockForConstraintsTests(Book)
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
assert book.errors['price'] == 'min'
}
そして、テスト実行。
grails> test-app grailsshop.Book
| Completed 1 unit tests, 0 failed in 361ms
| Tests PASSED - view reports in target/test-reports
おお、通った。
結論
とりあえず、
Grails2.0でconstraintsのValidationテストをする場合は、黙ってmockForConstraintsTestsを使っとけという話ですな。2012年1月6日金曜日
イケてないGitの覚書き
イケてないGit覚書き
基本
コミットする
# 作業後
# コミットする
$ git commit -a -m '出版社の資本金は1円以上'
[publisher-test e93607c] 出版社の資本金は1円以上
1 files changed, 5 insertions(+), 1 deletions(-)
$
変更したけどイケてないのでもとに戻す
# やらかしたので状態を取り戻す
$ git checkout filename
いや、そもそもコミットを取り消す
# やらかす
$ git commit -a -m '完璧っす'
[publisher-test f08613e3] 完璧っす
1 files changed, 10 insertions(+), 1 deletions(-)
# あああっ!
$ git reset HEAD^
GitHubにpush
$ git push -u origin master
たくさんすることがあるとき
ブランチを作成する
$ git checkout -b publishers-attr
ブランチを移動する
$ git checkout publishers-attr
ブランチの作業結果をmasterにマージする
# 現在のブランチを確認
$ git branch
master
* publishers-attr
# masterに戻る
$ git checkout master
# マージ
$ git merge publishers-attr
イケてないとき
ブランチで途中まで作業をしていてテストこけているのでコミットはしたくないけどこのまま作業を続けたくもない。だからMasterに戻って別の作業をしたい。
# 今のブランチ
$ git branch
master
* publishers-attr
$ git stash
$ git checkout master
# 作業する
Masterで作業していたら閃いたので、さっきのブランチに移動してあのイケテナイ変更から再開する
$ git commit -a -m 'masterでコミット'
# 閃いた
$ git checkout publishers-attr
$ git stash pop
登録:
投稿 (Atom)


