shared_examplesで冗長なテストファイルをすっきりすまーと
RSpecで、おんなじようなexamplesがたくさん出てきたときに、shared_example
でまとめてしまって簡単にしたのでソースコードのdiffをメモっとく。
summary
テストする項目は、作成したメールのうち、
- 適切な題になっているか
- 適切な受信メールアドレスになっているか
- 適切な送信元メールアドレスになっているか
- bodyの内容
という感じになっていて、ここを共通化する。
無料会員と有料会員にそれぞれ登録したタイミングで送信するメールを想定してみる。
diff
# `$ git diff` RSpec.describe UserMailer, type: :mailer do let!(:user) { create(:user) } + # it tests `subject`, `to`, `from`, `body.encoded` + shared_examples "Basic email info" do + it "renders the subject" do + expect(@mail.subject).to eq subject + end + it "renders the receiver email" do + expect(@mail.to).to eq [user_email] + end + it "renders the sender email" do + expect(@mail.from).to eq [co_mail_address] + end + it "assigns @confirmation_url" do + expect(@mail.body.encoded).to match confirmation_url + end + end + describe "#welcome_free_membership" do + let!(:subject) { "無料会員登録が完了しました" } + let!(:user_email) { user.email } + let!(:co_mail_address) { "info@sample.com" } + let!(:confirmation_url) { root_path } + + before { @mail = UserMailer.welcome_free_membership(user) } + it "sends an email" do expect do mail.deliver_now end.to change { ActionMailer::Base.deliveries.size }.by(1) end - it "renders the subject" do - expect(mail.subject).to eq "会員登録が完了しました" - end - it "renders the receiver mail" do - expect(mail.to).to eq [user.email] - end - it "renders the sender email" do - expect(mail.from).to eq ["info@sample.com"] - end - it "assigns @confirmation_url" do - expect(mail.body.encoded).to match root_path - end + + it_behaves_like "Basic email info" end describe "#welcome_monthly_membership" do let!(:user) { create(:user) }sample.com + let!(:subject) { "会員登録が完了しました" } + let!(:user_email) { user.email } + let!(:co_mail_address) { "info@sample.com" } + let!(:confirmation_url) { root_path } + + before { @mail = UserMailer.welcome_monthly_membership(user) } + describe do it "sends an email" do expect do mail.deliver_now end.to change { ActionMailer::Base.deliveries.size }.by(1) end - it "renders the subject" do - expect(mail.subject).to eq "会員登録が完了しました" - end - it "renders the receiver mail" do - expect(mail.to).to eq [user.email] - end - it "renders the sender email" do - expect(mail.from).to eq ["info@sample.com"] - end - it "assigns @confirmation_url" do - expect(mail.body.encoded).to match root_path - end + + it_behaves_like "Basic email info" end end
2つだと+の方がまだ多いなー。でも重複して書くコードの量が減ったのと、これからmailerが増えることに恩恵にさずかれるのでベターなリファクタリングだとは思う。
めっちゃスッキリしたし、イミュータブルな値も全部変数として使いまわせるようにすることで、柔軟性も増しました。いい感じ。