15211


`rspec 3.3` を使いテストを書いていたのですが、シンプルなテストだったので

[code]

    it "condition1" do
      expect{foo[:hoge}.eq 1
    end
    it "condition2" do
      expect{foo[:moge}.eq 2
    end
    
[/code]

をそれぞれ一行で

[code]

    it "condition1"{ expect{foo[:hoge}.eq 1 }
    it "condition2"{ expect{foo[:moge}.eq 2 }
    
[/code]

と書いた所

[code]

    syntax error, unexpected '{', expecting keyword_end (SyntaxError)
    
[/code]

のエラーになってしまいました。`do ~ end` と `{ ~ }` は等価だと思っていたのですがRSpecでは違うのでしょうか？

何かRSpecのオプションなどによって一行での記述を行えるようにすることはできますか？


CC BY-SA 3.0
2015-09-03T12:07:36.697
15201
2015-09-03T23:35:07.340
3271
question
ruby rspec
RSpec3.3 で it を 一行で記述する方法


RSpec 固有の話ではなく、Ruby の文法の問題です。  
次のように書けばよいです。

[code]

    it("condition1"){ expect(foo[:hoge]).to eq 1 }
    
[/code]

Ruby のリファレンスマニュアル <http://docs.ruby-
lang.org/ja/2.2.0/doc/spec=2fcall.html#block> に記述があります。

> { ... } の方が do ... end ブロックよりも強く結合します


CC BY-SA 3.0
2015-09-03T14:28:46.167
15205
2015-09-03T23:35:07.340
2015-09-03T23:35:07.340
3249
3249
15201
answer


Rubyの仕様で、メソッドに引数と中括弧のブロックを同時に渡す場合はメソッドを丸括弧で囲む必要があります。  
他にも同じようなパターンを下にまとめてみました。

[code]

    # 引数あり、丸括弧なし、中括弧ブロックあり => NG
    irb(main):001:0> puts 'x' { 'y' }
    SyntaxError: (irb):1: syntax error, unexpected '{', expecting end-of-input
    puts 'x' { 'y' }
              ^
    
    # 引数あり、丸括弧あり、中括弧ブロックあり => OK
    irb(main):002:0> puts('x') { 'y' }
    x
    => nil
    irb(main):003:0> puts { 'y' }
    
    # 引数なし、丸括弧あり、中括弧ブロックあり => OK
    => nil
    irb(main):004:0> puts() { 'y' }
    
    => nil
    
    # ハッシュが引数（中括弧あり）、丸括弧なし => NG
    irb(main):005:0> puts { a: 1 }
    SyntaxError: (irb):5: syntax error, unexpected ':', expecting '}'
    puts { a: 1 }
             ^
    
    # ハッシュが引数（中括弧あり）、丸括弧あり => OK
    irb(main):006:0> puts({ a: 1 })
    {:a=>1}
    => nil
    
    # ハッシュが引数（中括弧あり）、丸括弧あり => OK
    irb(main):006:0> puts({ a: 1 })
    {:a=>1}
    => nil
    
    # ハッシュが引数（中括弧なし）、丸括弧あり => OK
    irb(main):007:0> puts(a: 1)
    {:a=>1}
    => nil
    
    # ハッシュが引数（中括弧なし）、丸括弧なし => OK
    irb(main):008:0> puts a: 1
    {:a=>1}
    => nil
    
[/code]

ただ、いずれにしても元のRSpecの構文が少しおかしいです。正しくはこうなります。

[code]

    it("condition1"){ expect(foo[:hoge]).to eq 1 }
    it("condition2"){ expect(foo[:moge]).to eq 2 }
    
[/code]

また、上のコードでもかまいませんが、itを一行で書きたいときはsubjectを使うこともよくあります。

[code]

    describe 'foo' do
      subject { foo[key] }
      context 'with hoge' do
        let(:key) { :hoge }
        it { is_expected.to eq 1 }
      end
      context 'with moge' do
        let(:key) { :moge }
        it { is_expected.to eq 2 }
      end
    end
    
[/code]

テストコードが大きくなってくると、このようにしてテストコードのDRYさを求めた方が保守性が上がることもあります。

詳しくは以前書いたこちらのQiita記事を参照してください。

[subject
を使ってテスト対象のオブジェクトを1箇所にまとめる](http://qiita.com/jnchito/items/42193d066bd61c740612#subject-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%86%E3%82%B9%E3%83%88%E5%AF%BE%E8%B1%A1%E3%81%AE%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%921%E7%AE%87%E6%89%80%E3%81%AB%E3%81%BE%E3%81%A8%E3%82%81%E3%82%8B)


CC BY-SA 3.0
2015-09-03T18:41:00.477
15211
2015-09-03T22:04:08.800
2015-09-03T22:04:08.800
85
85
15201
answer