转载

[RSpec] subject , expect , context, is_expected, be_xxx

有同學最近在問 RSpec 的問題,因為會回答很多次,乾脆寫「一個經典例子」,來介紹 RSpec 的常見 syntax,來介紹一串重要的手法。

例子:Course#publish?

publish? 的判斷方式是 published_at 這個欄位存在與否。

class Course < ActiveRecord::Base        def published?     published_at.present?   end end

觀念 1: 測試要寫 正 / 負場景

在這個例子裡面,因為是測 boolean 值,比較好的方式,是要寫正反例子。

RSpec.describe Course, type: :model do    describe "#publish?" do      it "return true when published_at present?" do        course = FactoryGirl.create(:course, published_at: Time.now)       expect(course.published?).to be_truthy     end      it "return false when published_at blank?" do        course = FactoryGirl.create(:course)       expect(course.published?).to be_falsey     end   end    end

觀念 2 :當 when 與重複語句出現,應抽出變成 context

  • when published_at present?
  • when published_at blank?

這兩句是場景,所以接下來可以改寫成

RSpec.describe Course, type: :model do   describe "#publish?" do       context "when published_at present?" do        it "return true" do          course = FactoryGirl.create(:course, published_at: Time.now)         expect(course.published?).to be_truthy       end     end      context "when published_at blank?" do        it "return false" do          course = FactoryGirl.create(:course)         expect(course.published?).to be_falsey       end     end    end end

觀念 3 : 用 let 抽出 course,it 內只測 expect

將物件抽到 let。

RSpec.describe Course, type: :model do describe "#publish?" do       context "when published_at present?" do        let(:course) { FactoryGirl.create(:course, published_at: Time.now) }       it "return true" do          expect(course.published?).to be_truthy       end     end      context "when published_at blank?" do        let(:course) { FactoryGirl.create(:course) }       it "return false" do          expect(course.published?).to be_falsey       end     end    end end

觀念 4 : Minimal Valid Object 與「測試真正的變因」

但是在步驟 3 中,這樣的測試手法,是生成了「兩個不同的物件」去測。但我們寫這個測試的目的是要「測試一個物件,在published_at值不同」的情況下的回傳狀況。

真正的「宿主」是 Coruse 本身。所以我們改用 subject。傳 nil 與 現在的時間,去測試真正要測的行為。

RSpec.describe Course, type: :model do   describe "#publish?" do       subject(:course) { described_class.new :published_at => published_at }      context "when published_at present?" do        let(:published_at) { Time.now }       it "return true" do          expect(course.published?).to be_truthy       end     end     context "when published_at blank?" do        let(:published_at) { nil }       it "return false" do          expect(course.published?).to be_falsey       end     end    end    end

觀念 5 : xxxx? 可以使用 be_xxxxx 去測試

describe "#publish?" do       subject(:course) { described_class.new :published_at => published_at }      context "when published_at present?" do        let(:published_at) { Time.now }       it "return true" do          expect(course).to be_published       end     end     context "when published_at blank?" do        let(:published_at) { nil }       it "return false" do          expect(course).not_to be_published       end     end    end

觀念 6 :is_expected

測 return true/ false 看起來像是超多餘的。而且我們是對 subject 測,所以又可以改成 is_expected

RSpec.describe Course, type: :model do   describe "#publish?" do       subject(:course) { described_class.new :published_at => published_at }       context "when published_at present?" do        let(:published_at) { Time.now }       it { is_expected.to be_published }     end     context "when published_at blank?" do        let(:published_at) { nil }       it { is_expected.not_to be_published }     end   end    end

最後看起來是不是變得很好維護呢?

← Content Marketing 這樣做 - See / Think / Do framework
原文  http://blog.xdite.net/posts/2016/06/10/rspec-subject-expect-context-is-expected-be
正文到此结束
Loading...