Day 9 整理重复烦人的程序码!

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

昨天我们实作了把 example 给拆开,并且让整个测试更具备逻辑。

今天我们要让程序码更乾净,解决一些不断重复的程序码,在我刚开始学习时,觉得多打一两行也还好吧。

到现在要我打移动距离去改三个字都让我觉得痛苦,如果今天放大成 100 倍呢?我相信如果一个小小的改动要连续做一百次,应该是不会有人愿意吧哈哈!

Before hooks

下面是我们昨天实作的测试码,接着我们要来重构它。

重构的要点在於减少不必要的程序码,加速效能,让他看起来更舒服!

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

这段程序码,最需要改动的地方就在於第 3, 8 行,因为是完全一模一样的程序码,所以可以使用我们要介绍的 Before hooks 来解决这件事情!

先上完成的程序码:

RSpec.describe Burger do
  before do
    @burger = Burger.new('Beef', 'Cheddar')
  end
  
  it "has cheese" do
    expect(@burger.cheese).to eq('Cheddar')
  end
  
  it "has meat" do
    expect(@burger.meat).to eq('Beef')
  end
end

上面的程序码会得到 PASS!

接着我们来解释这到底是什麽作用,首先这个 before 的原型应该是这样:

before(:example) do
  ...
end

意思就是指,在每一个 example 前,做这件事情!应该是一个很好懂的方法,也非常实用,当然里面的 :example 可以做改变,这是更进阶的写法,之後会再提到!

所以我们完全不写参数给他的话,他就会自动的认定要在每一个 example 前执行 block 里面的内容!

这边示范为什麽要提到每一个 example 呢?

我们在 before 的 block 里面加上一段会印出来的文字。

RSpec.describe Burger do
  before do
    p 'Hello, this is before hooks'
  end
  
  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

接着我们来看 Out put !

很明显地,他在每一个 example 前执行!

所以先前的测试代码,在进入每一个 example 前,都会有一个实体变数 @burger 产生并一同加入 example 里面!

那至於为什麽要使用 @burger 而不是 burger 呢?

这就牵扯到 Ruby 变数的作用域问题,我们不深入的讨论这件事,但大致上来说,我们可以把一个 block 想像成一个新的领地,若你不加上 @ 这个符号成为实体变数,你是没有穿梭 block 的能力!

用原始的 Ruby Method

上面的方法是 RSpec 提供给我们的方法,但 RSpec 是可以直接写 Ruby Code 的,所以我们动动小脑筋,要怎麽做到和 before hook 一样的效果呢?

上代码:

RSpec.describe Burger do
  def burger
    Burger.new('Beef', 'Cheddar')
  end
  
  it "has cheese" do
    expect(burger.cheese).to eq('Cheddar')
  end
  
  it "has meat" do
    expect(burger.meat).to eq('Beef')
  end
end

不要怀疑喔!这样得程序码也会过关喔!

但不熟悉 Ruby 的人一定想说你在写三小... 但这真的会动,虽然不会有人这样写,因为後续会造成特殊的问题,但这也是一个方法啦,如果你确定你的数值不会有任何的改变,还是用 before hooks 吧~

他在读取到第 7 行的时候呼叫了 burger 这个我们定义的方法,而在 Ruby 中最後一行可以不用写 return, 所以他会自动的 return 一个 burger 物件。

所以我们可以这样看第 7 行

expect(Burger.new('Beef', 'Cheddar').cheese).to eq('Cheddar')

这是他会动的原因,但不要这样写,只是稍微提一下!因为这样真的会有问题~

小结

今天介绍了减少程序码的好方法 before,这将会在之後的 RSpec 生涯中偶尔地出现!

什麽?你说这才偶尔,那干嘛教呢?

哎唷,总是什麽方法都要看过才好啊!你才知道什麽是好,什麽是不好,像今天示范的用原始 Ruby 写的方法,也会动啊,但会遇上变动性的问题。

所以明天将会介绍在 RSpec 里面,遇到变动性问题该怎麽解决?以及最强大的方法 let 也会在明天一并介绍起来~


<<:  Material UI in React [Day 22] Data Display (part 2) 分隔线 & 列表

>>:  透明这回事 (Part 2)

创建App-现界面与连接

创建App-现界面与连接 经过了十五天的努力,现在就来看看现有的界面功能吧,我依照功能来区分:登入、...

Day 21 | Livewire 实作 Todo List(三): 切换其他日期的待办事项

实作待办事项的第三天,今天把切换日期的功能做好就完成啦!!今天会透过路由传递日期像是这样 https...

使用 Effect Hook( Day17 )

上一篇介绍过 State Hook 用来储存状态,Effect Hook 则用来处理 functio...

Day23 - 将台湾证券交易所的每日收盘行情存入 DB

前言 前面已经知道如何抓「台湾证券交易所」的每日收盘行情 CSV 档,接下来要处理资料,并存入 DB...

DAY 5 html 基础网页

在昨天将 index 成功推上 Github 後,今天该让他有点东西了。 打开 VSCODE 後 按...