※ この物語はお仕事でのお話です
モノリシックな Rails
↓
API がいくつかある
↓
今年フロントエンドを Nuxt.js にリニューアル
↓
管理機能の画面はいまだモノリシックな Rails
※ この物語はお仕事でのお話です
引き継ぎ当時...
🍝
タイトル・改
これからどうする?
ねらいは、メンバーの
スキルアップとテストの充足、
技術負債 🍝 の解消
どことは言いませんが、界隈で有名な
ESM さんにお願いしました。
「テストがないとデグレーションしてしまう!」
「今は機能追加よりもテストやリファクタリングを優先させる」
CEO や他部署に合意してもらい、
技術負債解消ターンに入った
←今ココ
第 1 期:Unit test 系の Spec を充足させる
第 2 期: Integration test 系の Spec を充足させる
↑今ココ
第 3 期:リファクタリング 💪
基本的な自動テストの考え方や RSpec の書き方は
これらを読めば分かる
また、「使えるRSpec入門」シリーズ
なども大変お世話になっている。
の詳しい説明は、
「初めての自動テスト」でも
紹介されています。
我々は model や decorator などの
Unit テストから書いていくことを
「計画づくり」のときに決めた。
「何をテストしたいのか」をペンディングで書いていく
ことにより、頭が整理されるため
describe Article, type: :model do
  # テスト対象(メソッド名など)
  describe '#published' do
    # 状態(〜の場合)
    context '非公開記事がある場合' do
      # 期待する出力(〜のこと)
      it '公開記事のみ取得できること'
    end
  end
end
describe Article, type: :model do
  describe '#published' do
    context '非公開記事がある場合' do
      before do
        create(:article, name: '公開記事', published: true)
        create(:article, name: '非公開記事', published: false)
      end
        subject(:article_published) { Article.published }
        # 期待する出力(〜のこと)
        it '公開記事のみ取得できること' do
          expect(article_published).map(&:published)).to match_array([true])
        end
    end
  end
end
describe Article, type: :model do
  describe '#some_data' do
  	context '何らかのデータがある場合' do
      let(:bad_article) { create(:article, title: Foo.title, description: Foo.description, tag_type: 1) }
      let(:good_article) { create(:article, title: 'タイトル', description: 'ディスクリプション', tag_type: 'Ruby') }
      subject(:bad_some_data) { bad_article.some_data }
      subject(:good_some_data) { good_article.some_data }
      it 'データの配列が返ってくること' do
        # 分かりにくい例 ×
        expect(bad_some_data).to eq [article.title, article.description, 1]
        # 分かりやすい例 ○
        expect(good_some_data).to eq %w(タイトル ディスクリプション Ruby)
      end
    end
  end
end
我々は全知全能だからコードの中身を知っているだけ。
メソッドの中身がどうなっていようと、期待する値を受け取れればそれで良い。
let(:creator) { Admin::DataCreator.new() }
subject(:contract) {
  # send を使って private メソッドを呼び出して検証することはできる...
  creator.send(:foo, 1, 2, 3)
}
# Table name: users
# ...
# id                     :bigint           not null, primary key
# name             :string(255)
# coach_id          :bigint
# ...
describe User, type: :model do
  describe '.coachs' do
    before do
      create(:user, name: 'テスト A さん', coach_id: nil)
      # 関連するモデルを作れる
      create(:user, name: 'テスト B さん', coach: create(:coach))
    end
    subject(:user_coachs) { User.coachs }
    context 'coach を持っているデータが存在する場合' do
      it 'coach を持っている user が取得できること' do
        expect(user_coachs.count).to eq 1
        expect(user_coachs.first.name).to eq 'テスト B さん'
      end
    end
  end
end
describe 'Api::ContactsController', type: :request do
  describe '.received_mail' do
    subject(:request) {
      post '/api/contacts', params: { contact: { name: '太郎', email: 'taro@co.jp', message: 'メッセージです' } }
    }
    # ...
    # リクエストが成功することなどのテスト
    # ...
    # Api::Mailer.received_mail(Contact.new).deliver
    
    before do
      allow(Api::Mailer).to receive_message_chain(:received_mail, :deliver)
        .with(instance_of(Contact)).with(no_args)
    end
    it 'mailer が呼び出されていること' do
      request
        
        expect(Api::Mailer).to have_received(:received_mail).once
      end
    end
    describe Foo, type: :service do
  describe Foo::Generator do
    describe '.call' do
      subject(:foo) { Foo::Generator.new }
      it 'メッセージが標準出力されること' do
        expect { foo.call }.to output("ファイルを出力しました。\n").to_stdout
        # .to_stderr で標準エラー出力も検証できる
        # expect { foo.call }.to output("エラーが発生しました。\n").to_stderr
        expect(File.exist?(file)).to be true
        end
    end
  end
emd
ちなみに...