Day 17 Matcher 介绍 (中)

该文章同步发布於:我的部落格

今天一样继续来介绍实用的 Matcher 和举例~

all matcher

在一开始写 Ruby 的时候,你可能会想用跑回圈的方式来测试所有的值!

RSpec.describe "loop test" do
  it "use each to test" do
    [1, 3, 5].each do |num|
      expect(num).to be_odd
    end
  end
end

这样也没有什麽问题,但当 RSpec 有提供给你更好的方法的时候,我们就没有必要自己来跑回圈。

这样很容易让测试的阅读性变得很困难,所以接下来的这个 all matcher 可以一次的测试所有的值,而且让语法变得非常易读!

RSpec.describe "all matcher" do
  it "check every value" do
    expect([1, 3, 5]).to all(be_odd)
    expect([1, 3, 6, 5, 8]).to all(be_an(Integer))
    expect([1, 3, 4, 7, 9]).to all(be < 10)
    expect([], [], []).to all(be_empty)
    expect([2, 4, 6]).to all(be_even)
  end
end

我们可以看到 all 後面可以接收所有 RSpec 的 matcher

接着我们可以再用一行流的方式来练习看看~

RSpec.describe "all matcher" do
  it [1, 3, 5] do
    it { is_expected_to all(be_odd) }
    it { is_expected_to all(be < 10) }
    it { is_expected_to all(be_an(Integer)) }
  end
end

be matcher ( nil, falsy, truthy)

这个 be matcher 和之前提到的 be 不太一样,这个主要是拿来测试 true & false 的值!

而在 Ruby 的世界中,只有两个东西不是 true 的,就是 false & nil

意思就是所有的物件都是 true 的,都是正向的。

我们可以用一些简单的示范来看看:

> if "-1"
> p 'true'
> else
> p 'false'
> end
> # 'true'

这边的 -1 虽然看起来像是负面的数值,但他在 Ruby 的世界中依然是一个 true 的物件,所以这边的判断式会走向印出 "true"

接着就可以来使用这个 be matcher

RSpec.describe "be matcher" do
  it "can test true" do
    expect(true).to be_truthy
    expect("-100").to be_truthy
    expect(:test).to be_truthy
    expect([-50, -100]).to be_truthy
    expect({}).to be_truthy
    expect(0).to be_truthy
  end
  
  it "can test nil false" do
    expect(nil).to be_falsy
    expect(false).to be_falsy
    # 整个 Ruby 世界中唯二的 falsy 物件
  end
end

相信上面这个范例就可以很清楚的理解到这个 matcher 的使用方法啦~

change matcher

这个 matcher 蛮有趣的,但实用度比较低,我就使用范例稍微介绍一下!

RSpec.describe "change matcher" do
  subject {[1, 2, 3]}
  
  it "check object change state" do
    expect { subject.push(4) }.to change { subject.length }.from(3).to(4)
    expect { subject.push(4) }.to change { subject.length }.by(1)
    expect { subject.pop }.to change { subject.length }.by(-1)
  end
end

先提一下为什麽我们要用 { } 而不是像平常一样使用 ( ),是因为如果我们想要对物件执行 Ruby 方法的时候,都像这样 block 的方式!

而他也可以接受不止一行的参数,你可以在里面进行计算,执行原生的 Ruby 方法等等...

而整个 matcher 的重点就在後面很有趣的写法!我们塞了一个数字进去 array 後,subject 的长度从 3 到 4 的过程!就是我们要测试的!

後面补上的 by(1) 写法,就是改变的数值,因为每次都要写 from...to... 实在是太麻烦了,於是 RSpec 也给我们这样的黑魔法来使用!

contain_exactly matcher

这个 Matcher 的工作在於确认 确实涵盖的值且不在乎顺序

我们用范例来说明!

RSpec.describe "contain_exactly matcher" do
  it "check exactly contain" do
    expect([1,2,3]).to contain_exactly(1,3,2)
    expect([1,2,3]).to contain_exactly(2,1,2)
    expect([1,2,3]).to contain_exactly(3,2,1)
  end
end

其实非常的简单,他关注的点是里面的内容物是不是都在,但他不在意顺序!

这个其实使用的地方蛮少的,因为自己在写的时候还是希望测试的格式是固定的,也有可能是我自己想不到使用的他的时机~

start_with & end_with matcher

看到这个英文的开头,应该能够大概猜到他的使用方式!就是要测试这个物件的开头或是他的结尾~

且主要的用法是在 String Array 身上!

我们来看看范例吧!

RSpec.describe "start_with & end_with" do
   descirbe "SnoppyDog" do
     it "check the substring from begin to end" do
       expect(subject).to start_with("Snop")
       expect(subject).to start_with("S")
       expect(subject).to start_with("SnoppyDo")
       expect(subject).to end_with("pyDog")
       expect(subject).to end_with("og")
     end
     
     it { is_expected_to start_with("Sn") }
     it { is_expected_to end_with("Dog") }
   end
   
   descirbe [1, 3, 7] do
     it { is_expected_to start_with(1, 3) }
     it { is_expected_to end_with(3, 7) }
   end
end

但他就不像刚刚的 contain_exactly 一样不在意顺序了!

start_with 本身就带有一种方向的感觉,所以我们的 matcher 要给予照着顺序的参数~

小结

Matcher 的数量真的是有够多,当然要怎麽使用端看自己要测试的重点是什麽~

说不定有些冷门的 Matcher 刚刚好很契合你这个测试的目的也说不定!

重点就是多看一些有趣的 Matcher 然後收藏在浅意识中,想到的时候再去查资料就可以了~


<<:  Day16:终於要进去新手村了-Javascript-回圈-while

>>:  [DAY13?]SSH container

17.unity显示/隐藏物件(SetActive)

想要制作一个假背包,利用按钮显示背包,再按下按钮关闭背包。 要使用GameObject.SetAct...

Day 19-infrastructure 也可以 for each 之四:for & dynamic block

这篇是 infrastructure 也可以 for each 第四篇,上次漏发了,今天补发 本章介...

Day 30. 结语

#结语 最後一天,专案完成了,铁人赛完赛 不过第9天就中断了比赛 真的是觉得太~~~~~~~~~~...

[Day 23]从零开始学习 JS 的连续-30 Days---箭头函式

函式陈述式与函式表达式差异 函式陈述式 : function num(x) { return x *...

[iT铁人赛Day23]练习题(2)

嗨,大家好,由於本人昨天去打了疫苗,然後晚上9点开始被副作用折腾 以至於过了12点不能马上发文 然後...