shared examplesとは

### shared exampleはクラスとモジュールの振る舞いを記述させる
>Shared examples let you describe behaviour of classes or modules. 

>When declared, a shared group’s content is stored. 

### 他のexample groupのコンテキストでのみ実行に必要な共有グループのいくつかのコンテキストを供給する
>It is only realized in the context of another example group, which provides any context the shared group needs to run.

### 気になる単語
* Shared examples、shared group
* context、example group

https://qiita.com/masatom86650860/items/4102721b1f8a99b2987c

# このどれかを使ってshared_exampleを呼び出す
>A shared group is included in another group using any of:
```rb
  include_examples "name"      # include the examples in the current context
  it_behaves_like "name"       # include the examples in a nested context
  it_should_behave_like "name" # include the examples in a nested context
  matching metadata            # include the examples in the current context
```
# shared_exampleを使ったテスト
```rb
 RSpec.shared_examples "some example" do |parameter|
    \# Same behavior is triggered also with either `def something; 'some value'; end`
    \# or `define_method(:something) { 'some value' }`
    let(:something) { parameter }
    it "uses the given parameter" do
      expect(something).to eq(parameter)
    end
  end

  RSpec.describe SomeClass do
    include_examples "some example", "parameter1"
    include_examples "some example", "parameter2"
  end
```
### 動かしてみた 変数の上書きされている　エラー
```rb
RSpec.describe SomeClass do
    include_examples "some example", "parameter1"
    include_examples "some example", "parameter2"
end
```
```
expected: "parameter1"
     got: "parameter2"

(compared using ==)


  0) User uses the given parameter
     Failure/Error: expect(something).to eq(parameter)

       expected: "parameter1"
            got: "parameter2"

       (compared using ==)
```
### 最初のテストは失敗する
>You’re actually doing this (notice that first example will fail):
```rb
  RSpec.describe SomeClass do
    \# Reordered code for better understanding of what is happening
    let(:something) { "parameter1" }
    let(:something) { "parameter2" }

    it "uses the given parameter" do
      \# This example will fail because last let "wins"
      expect(something).to eq("parameter1")
    end

    it "uses the given parameter" do
      expect(something).to eq("parameter2")
    end
  end
```
## 上のコードを動かしてみた結果
```
expected: "parameter1"
     got: "parameter2"

(compared using ==)


  0) User uses the given parameter
     Failure/Error: expect(something).to eq("parameter1")

       expected: "parameter1"
            got: "parameter2"

       (compared using ==)
```
変数が上書きされているからエラーが起こったと考える

# エラーが起こる原因
### shared groupを含んだファイルを前にロードするためには厳格な名前規則が必要だ
>WARNING: Files containing shared groups must be loaded before the files that use them. While there are conventions to handle this, RSpec does not do anything special (like autoload). Doing so would require a strict naming convention for files that would break existing suites.
### 同じコンテキスト内で複数回呼ぶと最後に呼ばれたやつが勝つ
>WARNING: When you include parameterized examples in the current context multiple times, you may override previous method definitions and last declaration wins. So if you have this kind of shared example (or shared context)

# 上のエラーを回避
### 同じcontextで同じ名前のメソッドを複数宣言すると警告される
>To prevent this kind of subtle error a warning is emitted if you declare multiple methods with the same name in the same context. 

### 上の警告を防ぐために`include_examples`を`it_behaves_like`に置き換える
>Should you get this warning the simplest solution is to replace include_examples with it_behaves_like, in this way method overriding is avoided because of the nested context created by it_behaves_like

### どちらかを変えると両方通る
```rb
RSpec.describe User do
  include_examples "some example", "parameter1" # 以下2行同じコンテキスト内だと考える
  it_behaves_like "some example", "parameter2"
end
```


### requireでファイルを要求する
>The simplest approach is to require files with shared examples explicitly from the files that use them. 

### require ファイル名と書くと特定のパスから呼び出される
>Keep in mind that RSpec adds the spec directory to the LOAD_PATH, so you can say require 'shared_examples_for_widgets' to require a file at #{PROJECT_ROOT}/spec/shared_examples_for_widgets.rb.

## spec/support/にあるshared examplesを含むファイルを置き、...requireする
>One convention is to put files containing shared examples in spec/support/ and require files in that directory from spec/spec_helper.rb:
```rb
Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
```

## 同じファイルに全てあるときはshared groupを宣言するだけで良い
>When all of the groups that include the shared group reside in the same file, just declare the shared group in that file.

https://rspec.info/features/3-13/rspec-core/example-groups/shared-examples/#:~:text=Shared%20examples%20let,in%20that%20file

# 感想
shared examplesは関数で、shared groupはshared examplesで使われるcontextを言うのだろう。
* requireを使ってみる
* `include_examples`を`it_behaves_like`に置き換える

* `Dir["./spec/support/**/*.rb"].sort.each { |f| require f }`を使ってみる
* include_examples "name", it_behaves_like "name", it_should_behave_like "name", matching metadata  の意味の使い分けを知りたい