RSpecを実際に書いて体験してみる

## この記事の目的
RSpecの取っ掛かりとして、簡単なRSpecを書いて実際に実行してみます。流れの中で説明も多少入っていますが、事細かく何を意味しているかなどの説明はあまりしません。あくまでまずRSpecを実行してみる、体験してみるところに重点をおきます。

##今回使用するメソッドの説明

文字列数字を足し算するメソッドを作ってみましょう。メソッドはint Add(string numbers)。

- メソッドは文字列の数字を引数(例："1")に取る、カンマ区切りで複数の文字列の数字が取れる(例："1,2,3")。
- 空の場合は0を返す

##RSpecを準備する
Gemfileにrspecを追加。**bundle install**を実行。

```ruby:Gemfile    
source "https://rubygems.org"
...
...
gem "rspec"
```

そして、specディレクトリ(なければmkdir specで作成)の直下に**string_calculator_spec.rb**を作成します。これが今回使用するRSpecのファイルです。
    
```ruby:spec/string_calculator_spec.rb
describe StringCalculator do
end
```
RSpecでは、describeでclass、module、メソッドを記述します。describeブロックはrspecの処理の流れを記述するため、必ず最初に書かれます。

**bundle exec rspec**でrspecを実行してみます。すると下記のようなエラーが出てくるはずです。

実行結果
![スクリーンショット 2017-12-17 3.57.20.png](https://qiita-image-store.s3.amazonaws.com/0/133800/fae00b2e-a1e1-9ee3-fbd2-e364f99cbe26.png)

これはまだ**StringCalculator**というクラスを作成していないからです。では、StringCalculatorクラスをlibの配下に作成します。

```ruby:lib/string_calculator.rb
class StringCalculator
end
```
ここで、rspecのファイルにrequireを追加します。

```ruby:spec/string_calculator_spec.rb 
require "string_calculator"

describe StringCalculator do
end
```
**bundle exec rspec**を実行します。

実行結果
![スクリーンショット 2017-12-17 4.11.09.png](https://qiita-image-store.s3.amazonaws.com/0/133800/d31721d7-2322-8f9d-2bf2-e816a650ec9c.png)

先ほどのエラーがなくなりました。これでコードを書く準備ができました。

##実際にRSpecを書いてみる

StringCalculatorのaddメソッドは空(empty)を受け入れてます。空を受け取ったら0を返す仕様です。まずはdescribeにaddを追加してみましょう。

```ruby:spec/string_calculator_spec.rb
require "string_calculator"

describe StringCalculator do

  describe ".add" do
    context "given an empty string" do
      it "returns zero" do
        expect(StringCalculator.add("")).to eql(0)
      end
    end
  end

end
```
- クラスメソッドのaddを記述するために、また別のdescribeを使います。そして慣例で、クラスメソッドはドット(.)のprefixを付けて(".add")、インスタンスメソッドにはdash(#)を付けます("#add")。

- コンテキストブロックではaddメソッドが空だったら0を返すことを記述しています。contextはdescribeと意味的には同じなのですが、コードの可読性を向上させるために使われたりします。

- itブロックはテストケースを記述するために使います。上記は、addメソッドに空を与えると0を返しますよという例です。

- 「expect(...).to」や「expect(...).not_to」は期待する(しない)結果を定義します。eqlはイコールの意味です(matcherと呼ぶらしい)。matcherはいろいろな書き方があるようです。参考：https://relishapp.com/rspec/rspec-expectations/v/3-1/docs/built-in-matchers

RSpecを書き終わったら、クラスにaddメソッドを追記しましょう。

```ruby:lib/string_calculator.rb
class StringCalculator

  def self.add(input)
    0
  end

end
```

追記後**bundle exec rspec**を実行します。

実行結果
![スクリーンショット 2017-12-17 5.01.03.png](https://qiita-image-store.s3.amazonaws.com/0/133800/a4679677-822c-955d-e7cd-09ea8550ae8b.png)

RSpecが通りました。

##1つの数字でaddメソッドをRSpecに通してみる
string_calculator_spec.rbを下記のように書き換えてみましょう。

```ruby:spec/string_calculator_spec.rb

require "string_calculator"

describe StringCalculator do

  describe ".add" do
    context "given '4'" do
      it "returns 4" do
        expect(StringCalculator.add("4")).to eql(4)
      end
    end

    context "given '10'" do
      it "returns 10" do
        expect(StringCalculator.add("10")).to eql(10)
      end
    end
  end

end
```

実行してみましょう。

実行結果
![スクリーンショット 2017-12-17 12.55.23.png](https://qiita-image-store.s3.amazonaws.com/0/133800/e516e3c2-29df-b91c-1b11-404965482f7a.png)

1つ目のRSpecで期待する値(expected)は4に対して、受け取った結果の値(got)は0だよ、2つ目のRSpecでは期待する値(expected)は10に対して、受け取った結果の値(got)は0だよって書かれています。ゴールはRSpecを通すことなので、RSpecの対象となっているクラス(ここではStringCalculatorクラス)を修正します。

```ruby:lib/string_calculator.rb

class StringCalculator

  def self.add(input)
    if input.empty?
      0
    else
      input.to_i
    end
  end

end
```

RSpecを実行してみてください。下記のようになると無事RSpecが通りました。
![スクリーンショット 2017-12-17 13.00.59.png](https://qiita-image-store.s3.amazonaws.com/0/133800/59b09099-b1ea-c360-0dbe-6f905d516bf9.png)

## 複数の数字でメソッドを試してみる
最後に複数の文字列数字をカンマ区切りで渡した場合(本来のメソッド処理)のケースを試します。

```ruby:spec/string_calculator_spec.rb

require "string_calculator"

describe StringCalculator do 

  describe ".add" do
    context "two numbers" do
      context "given '3,5'" do
        it "returns 8" do
          expect(StringCalculator.add("3,5")).to eql(8)
        end
      end

      context "given '1000,200'" do
        it "returns 1200" do
          expect(StringCalculator.add("1000,200")).to eql(1200)
        end
      end
    end
  end

end
```

RSpecを実行しましょう。失敗するはずです。
![スクリーンショット 2017-12-17 17.57.41.png](https://qiita-image-store.s3.amazonaws.com/0/133800/6edb42f0-246c-ab3f-a27e-4291d5717ee2.png)

ここで再度StringCalculatorをクラスを修正します。

```ruby:lib/string_calculator.rb

class StringCalculator

  def self.add(input)
    if input.empty?
      0
    else
      numbers = input.split(",").map { |num| num.to_i }
      numbers.inject(0) { |sum, number| sum + number }
    end
  end

end
```

RSpecを実行します。

実行結果
![スクリーンショット 2017-12-17 18.00.29.png](https://qiita-image-store.s3.amazonaws.com/0/133800/355eef97-8702-e5f3-e039-0fc1d9fa6add.png)

##おまけ
RSpecはアウトプットの表示方法がいくつかあって、そのうちのひとつにdocumentationフォーマットがあります。やり方は簡単で、

**bundle exec rspec --format documentation**

とするだけです。

実行結果
![スクリーンショット 2017-12-17 18.50.12.png](https://qiita-image-store.s3.amazonaws.com/0/133800/0138ee4f-34e1-eaa8-1679-d0b97671ed69.png)