RSpecで削除メソッドのControllerをテストしたら"expected #count to have changed by -1, but was changed by 0"が出た件


この記事の目的

未経験エンジニア3ヶ月目のたっきーです。
開発に携わってRSpecでテスト書いてと言われましたが、とても苦戦し特にError文を検索しても回答が出てこない事が辛すぎてポエム記事を書くことになりました。
書き方や原因が考えていることと違ったら、「トンチンカンな事言ってるぞ」と編集リクエストください。
みなさまに育てていただけると嬉しいです。
※そのままのコードではなく、紹介用なので簡素化したコードで書いてます。

起きた事

Railsで書いたdestroyアクションのメソッドのテストを書いたら、
"expected #count to have changed by -1, but was changed by 0"と出た。
ググっても、日本語の記事が全然出てこないしよくわかんないし、そもそもRSpec自体よくわかんない状態でとても困った。
あとExpected response to be a , but was <404>もエラーで出ていた。

コード

spec.rb
    context 'categoryを削除し、更新する' do

      before :each do
        @delete = create(:category)
      end

      subject { delete :category_destroy, id: @category_delete }

      # カテゴリ(category)を削除する
      it "deletes the category" do
        expect{ subject }.to change(Category,:count).by(-1)
      end

      # その後#index にリダイレクトすること 
      it "redirects to admin/custom#index" do
        subject
        expect(response).to redirect_to customizes_index_path 
      end

    end

指摘されている事

僕のコード上では-1になる事をexpect(期待)しているのに、結果は0だよって言われてる。
つまり、削除がされていないんじゃないのか??

どこを確認すればいいのか

僕は今回、先輩に泣きついてlogディレクトリのtest.logってファイルを調べて。ヒントをもらった。
もう一度$bundle exec rspec テストファイル名してみると、色々コードが出てきたが
その中にちゃんとcategory deleteの文字がある。
通ってはいるが、どこかで落ちているのだ。

解決方法

結論をいうと、factorybotと呼ばれるgemにテストデータを書いていなかったから怒られたのだ。
なので、factories.rbファイルに下記を追加した。

factories.rb
  factory :category do
    name {Faker::Name.title}
    label {Faker::Name.title}
    priority {1}
  end

Fakerはテストデータを簡単に作ってくれるgemのようです。
https://qiita.com/Keisuke69/items/edcaadc100361cf945e2

結論

結局、controllerで定義したメソッドをviewで呼ぶように
RSpecでもfactorybotで定義したテストデータの変数をspecでファイルで呼んでくるだけのようだ。

RSpecの書き方ととfactorybotの書き方

[書き方]spec.rb
RSpec.describe '削除' do
  it 'カテゴリ削除' do
    expect(条件式).to eq 
  #expectの内容はcontrollerによる!
  end
end

RSpecの書き方細かく説明できません。
もし書き方について知りたい方は@jnchitoさんのこちらの記事で見てみてください。
https://qiita.com/jnchito/items/42193d066bd61c740612
まだまだ全然わからないけど、未経験の僕でも雰囲気だけでもバンバン伝わってくる
非常に丁寧な記事です。

[書き方]factory.rb
factory :◯◯ do
    カラム名1 {Faker::Name.title}
    カラム名2 {Faker::Name.title}
    カラム名3 {1}
  end