RSpec

具体的な実装の記載はこちら

# rspec
- 公式サイト　https://relishapp.com/rspec
TDD(test-driven development)手法を取り入れたテストフレームワークです。

## TDD(テスト駆動開発)とはなにか
[wikipediaより](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA)
> プログラム開発手法の一種で、プログラムに必要な各機能について、最初にテストを書き（これをテストファーストと言う）、そのテストが動作する必要最低限な実装をとりあえず行った後、コードを洗練させる、という短い工程を繰り返すスタイルである。

## ざっくりと、、手順
1. ある機能の振る舞いを洗い出し、そ
1. 失敗するテストを書く(テストから書いているため失敗するのは当たり前。)
2. 成功するテストを書く(仮実装をして、テスト側に問題があるのを防ぐ。それから明らかな実装を行う)
  3. リファクタリング(コードの重複をまとめたり、実装を本格化する)
 
 この流れをグルグル回す
 
 - 仮実装 =>　絶対に成功するコードをかく
 - 明らかな実装　=> 実際の実装コード
 - 同じ対象に対して違う角度からテストする(三角測量)
 - railsでのrspecの実行の仕方
  ```  
bundle exec rspec rspecファイルのpathを指定 
 ```
 - optionで-fbをつけると見やすくなる(cfo-a)


## 出力結果の見方(-fbオプションを加えた場合)

+ describeまたはcontextの説明がインテンドでわかりやすく表示されている
+ 緑が成功
+ 赤が失敗
+ Failures:　以降に具体的な間違いを指摘してくれる
+ expected 期待した値
+ got 実際の値　=>  一致しないのでテスト失敗している

## 書き方






### describe
+ テスト対象のグループ分け
+ 入れ子できる　
+ グループの分け方がものだった場合こっち　
+ トップレベルのdedcribeはよくクラス名を書くことが多い
   
 ```
    describe "クラスのテスト" do
    end
    describe クラス名 do
    end
 ```
### context
+ テスト対象のグループ分け
+ describeと同じ　
+ グループの分け方が状況だった場合こっち

```
expect "when method exists" do
end
```
+ 説明文はrspec実行する時に-fdをつけたときに表示されるので、わかりやすいように名前をつけとくのがミソ


### it  
+ テスト対象に対して、期待する振る舞いを記載
+ 説明文は省略できる
  - 例　calcオブジェクトのaddメソッドに引数2,3を渡した時の返り値が5になる
   
```
   it "given 2 and 3, returns 5" do
      calc = Calc.new
      expect(calc.add(2, 3)).to eq(5)
    end
   ```
   
```
#省略形
   it {
    calc = Calc.new
    expect(calc.add(2, 3)).to eq(5)
   }
   ```
+ 省略するとrspecが自動で説明文描いてくれる

```
should eq 5
```
+ 仕様の振る舞いだけ書いておきたい場合。

```
it "振る舞い" 
```


+ 黄色で表示 
+ itで期待する振る舞いを書く時に使う記号 -> <b>macharという</b>
  
    - 公式サイトの資料　https://relishapp.com/rspec/rspec-expectations/v/3-6/docs/built-in-matchers
    - eq　=
    - not_to eq !=
    - to be ture
    - to be false 
    - to be >
    - to be <
    - to_between(a,b),inclusive a~bの間、a,bを含む
    - to respond_to(:abc) オブジェクトにabcメソッドがあるか?
    - to be_integer?
        
```expect(calc).to respond_to(:add)```

 ```
# integer? empty?
 expect(calc.add(2, 3).integer?).to be true
 expect(calc.add(2, 3)).to be_integer
 ```

### before
+ exampleの共通化処理をブロックにまとめる

```
# インスタンス化処理を共通化
before(:option) do 
    @calc = Calc.new
  end

```

+ オプション
  - 省略したらexampleがデフォルトで入る
  - example それぞれのexampleで実行したい
  - context 最初の一回目のexampleだけ実行
  - exampleをまたがって変数を使用する場合は@を前につける

    

### subject
  + 主対象の操作を管理できる
  + describeにクラス名を指定した場合、subjectでインスタンス化できる。
    
```
 # desribeにCalcクラスを指定した場合、Calcオブジェクトになる
expect(subject.add(2,3)).to eq(5)
```
+ subjectをそのまま使うと何を表しているのかわからなくなるので

```
subject(:hoge){ Hoge.new }
``` 

+ こう宣言しとけばhogeを各ブロックで使える
+ beforeと同じだが、exampleで使う時は@要らない。シンボルで管理できる。

### let
  - ほぼsubjectと同じ役割
  - 主対象以外の変数などの操作を管理する

  ```
let(:tax){ 0.08 }
it{expect(seminar.price(100,tax)).to eq(108)}
 ```
  - 遅延評価される
  - 遅延評価ではなく、example毎で必ず実行したい場合は```let!```をつかう
  - exsample毎にキャッシュされる

### test doubl
  - 実装はまだだけどテストはしたい場合に使用
  - method stub　=> 実装していないけれどテストに使えるメソッドを作る。または、テストする必要のない処理などの返り値を指定する
  
    ```
    
    ```
    - allowでseminarというオブジェクトを選択し、receiveでそのオブジェクトのexist?メソッドを選択、その返り値をand_reternで指定している
    - receive_message_chainでメソッドチェーンで複数していできる。
    - withで引数を渡す
  
    ```
   
    ```
    - 引数を持たないメソッドにはno_argsをしていてあげる
  - message expectation
  - 呼ばれなかったらfalseでテストは失敗する