テストが通るたびにレッドライト!グリーンライト!ってさけんでるんだけど RSpec でわからないことがある。

テストが通るたびにレッドライト!グリーンライト!ってさけんでるんだけど RSpec でわからないことがある。

Ruby を全面に押し出してる会社に転職してはや半年ほど、Ruby というか Rails 力が足りないので他の職務をこなしておりますが、そればっかりやってもいられないということで最近は空き時間をみて Rails をさわっています。

いちおう慣れてきた感じはするので RubyRails といえばテストだろつうことで「Everyday Rails - RSpecによるRailsテスト入門」読みながらテストをもりもり書いています(書き方が正しいかわからないのでテストファーストとはいかない)がわからないことがある。

validates :fullname,
        presence: {message: 'お名前を入力してください'},
        length:   {minimum: 2, too_short: 'お名前が短すぎます'}

でこういう validates で二重に条件を設定した場合のエラーをみるときに

user = User.new(fullname: '')
expect(user).to have(1).errors_on(:fullname)

user = User.new(fullname: '姓名')
expect(user).to have(0).errors_on(:fullname)

これはいいんですが

user = User.new
expect(user).to have(2).errors_on(:fullname)

have(2) になっちゃうじゃないですか。この数値、手計算してかえるの……。

have_at_least つかやあいいじゃねぇかという話もあるんですけど、have(1) もそうなんですけど、エラーの内容を特定して指し示してるわけではないのでどうもきもちがわるい。

message 比較以外で特定する方法があったら知りたいけど検索力が足りないので見つけられなかった。仕方がないので

validates :fullname,
        presence: {message: TaggedString.new(:presence, 'お名前を入力してください')},
        length:   {minimum: 2, too_short: TaggedString.new(:length, 'お名前が短すぎます')}

タグをもった TaggedString という文字列クラスをでっちあげて presence エラーと length エラーを区別できるようにしてとりあえず難を逃れたわけですが、もっとなんか普通にスマートな方法がどこかにあると思う。

「Everyday Rails - RSpecによるRailsテスト入門」まだ全部読めてないのでどこかに出てくるかな。

なお付与したタグがI18n.translateにぶちころされたので予期せぬモンキーパッチ童貞喪失にてタグ消えないように対処した。(そういえば最初は message に連想配列をいれて対処していたところ、手動で errors.add する場合はいいんだが、ビルトインの validator 使うと自動でI18n.translate通すのでそこで死んだ。)

これも TaggedString 側でなんとかできそうなので要勉強。

そういえば参考にしようと会社の Rails 業務ソースを読んだ

ずらっとならぶ *_spec.rb を前にしてわくわくしながらひらいたら、scaffold かなにかで自動生成したものらしくて、特になにも書きくわえられていなかった。

横にずらっと並んでいる 1KB がまぶしい。