Day 8 超多的范例?怎麽办呢?

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

昨天我们做了一个关於汉堡种类的测试,但真正的测试怎麽可能这麽少呢!

所以我们今天要更进一步的来把它变得稍微复杂一点,并且让他看起来更乾净,更好一些!

Describe 後面改用常数吧!

RSpec.describe Burger do
  it "has a type" do
    burger = Burger.new('Big mac')
    expect(burger.type).to eq('Big mac')
  end
end

还记得我们两天才撰写测试的时候,describe 後面加入的是 "Burger" 字串,但我们现在可以改用常数,也就是我们测试类别的名称。

只是少了两个括号有什麽差别吗?当然有,他的好处可以让我们少写很多的程序码,我们後面会提到直接使用 常数 到底有哪些优势!(关键字:subject )

一个萝卜一个坑

我们现在的测试只有单单测试一个汉堡的种类,但我们现在要让他更复杂一些。

我们想要让汉堡可以有肉类和起司的选项,我们要把大麦克给拆开来看看!

以下为逐步图,从原本的作法一步一步拆开来!

# 原本的状况
RSpec.describe Burger do
  it "has a type" do
    burger = Burger.new('Big mac')
    expect(burger.type).to eq('Big mac')
  end
end

这边我们希望汉堡可以放入两种种类,分别是牛肉、以及切达起司!

我们一样保持先把测试给完成再去改你的程序码,渐渐地习惯这种流程,不要急着去改,这样就丧失了 TDD 的意义了!

# 第一步
RSpec.describe Burger do
  it "has a type" do
    burger = Burger.new('Beef', 'Cheddar')
    expect(burger.type).to eq('Big mac')
  end
end

下面的写法看起来非常合理,但却有些瑕疵。

在 RSpec 里面我们会希望测试可以越乾净越好,一个 example 尽量只有一个 expectation 这样会让我们可以把功能切的更细、考虑到更多,尤其在 Output 也会完全不一样!

而且这边的叙述也不够精确, has a type 但却没有说是什麽样的类型,当测试的数量不断地增加的时候,这就会造成你在看错误讯息时更大的负担!

# 第二步
RSpec.describe Burger do
  it "has a type" do
    burger = Burger.new('Beef', 'Cheddar')
    expect(burger.meat).to eq('Beef')
    expect(burger.cheese).to eq('Cheddar')
  end
end

下面是我们把 expectation 拆成两个 example 的样子!

也把两个 example 的叙述变得更仔细,让人可以一目了然这个测试的目的是什麽!

有没有觉得画面变得更清楚啦?虽然我们的例子都很短,你可能觉得放一起也没关系,但养成好习惯会让以後事半功倍喔!

# 第三步
RSpec.describe Burger do
  it "has cheese" do
    burger = Burger.new('Beef', 'Cheddar')
    expect(burger.cheese).to eq('Cheddar')
  end
  
  it "has meat" do
    burger = Burger.new('Beef', 'Cheddar')
    expect(burger.meat).to eq('Beef')
  end
end

好的,现在我们的测试已经根据新的需求有了改变,想当然我们输入测试的指令一定不会通过的。

接着又来到 TDD 的第二个步骤了,我们要让这个测试 PASS !

阅读错误再次通过测试!

输入了 rspec spec/burger_spec.rb

我们再来阅读这个错误的问题在哪,错误的地方在於类别的 initialize 方法这边。

错误的问题则是下方的 ArgumentError 可以看到他写到只期待一个参数,但我们却给了两个参数。

好的没问题,我们来到 burger.rb 存放类别的档案,稍作修改一下!

class Burger
  attr_accessor :type

  def initialize(meat, cheese)
   @type = type 
  end
end

我们给了他两个参数了,接着我们在输入 rspec spec/burger.rb 来看看错误的讯息是什麽?

喔!这次发生错误的地方在测试的档案中,原因是我们的 Burger 没有 meat 这个方法,昨天的也有提到这样的问题该如何解决!简简单单~

给他两个方法让他可以读取就好啦~

class Burger
  attr_accessor :meat, :cheese

  def initialize(meat, cheese)
   @type = type 
  end
end

肯定会通过的吧?

啊...太大意了,我们应该要注意到实体变数的问题,目前这个物件里面没有存放肉和起司的变数,快加给他!

class Burger
  attr_accessor :meat, :cheese

  def initialize(meat, cheese)
    @meat = meat
    @cheese = cheese
  end
end

恭喜啊!我们又通过了一次测试了!

记得我刚刚前面有提到 example 不要重复测试的重要性吗?

看看这边的 Output 就很明显像是作文一样,告诉我们汉堡有肉有起司,但若是你全部都写在一个 example 里面,就会变得不清不楚了~

一个 it 代表的是一个 example 喔,这会关系到测试的可读性!所以不是越省越好喔~

小结

记得今天的开头,我有提到先把 describe 後面的字串描述改成类别的常数吧?

仔细看看,今天我们的测试码就有两行是一模一样的重复代码,TDD 的第三步就是要重构程序码以及测试代码!

明天我将会介绍整理 RSpec 的方式,有许多的小帮手能够让我们的测试码更简洁,更易读!


<<:  Day 0xC - Debug 地狱第三天,终於逃脱了 (建立订单)

>>:  Day 22 - Follow Along Links

【面试】视讯面试要点

因应疫情,全部都是视讯线上面试, 这边收集一些点,以便未来提醒自己。 面试当天要测试硬体(镜头、麦克...

Ruckus R320 AP设定问题

哈罗 想请教一下各位 目前公司开一家新店 我们用了Ruckus R320的AP 因为是跨县分店 我们...

Day 23. Zabbix 通知设定 - Custom alertscripts - Line

在 SMTP Mail 之後,今天要跟大家介绍第二种通知方式 Custom alertscripts...

Day23:交给专业的来

我们来看看Executor介面的内容: package java.util.concurrent; ...

Day25:【技术篇】JavaScript 套件 - classnames

一、前言   classnames 是一个方便 JavaScript 管理 class name 的...