Day 6 RSpec 超基础语法!

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

昨天的文章介绍了 TDD 的流程和精神等等。

今天我们要正式进入 RSpec 的世界,所以我们从最一开始容易见到的几种语法开始做解释和教学!

describe method

假设我们今天要开一间汉堡店,那我们就要来想像汉堡店的测试!

首先我们在 Spec 档案里面加入一个 burger_spec.rb 的档案!

这样我们就可以开始来写啦~

 Rspec.describe 'Burger' do
   ...
 end

这个 describe 呢,主要在解释我们要测试的主要目标是什麽?( 这边是测试汉堡这个类别 ),而这边也有一个 Ruby 小小的惯例,就是可以省略 ( ) 小括号,所以原本应该是这样...

RSpec.describe('Burger') do
  ...
end

所以从这边我们可以了解到,describe 应该是 RSpec 的类别方法唷!

接着 describe 也同时要接收一个 Ruby 的 block 用 do..end 的方式接在後面。

写到这边,我们已经完成了一个 example group,直翻的话叫做:例子的集合???

也就是我们提供了一个 example 的地基,在这里面可以放入许多的小 example,在 RSpec 的世界中,每一个我们所期待的事件都是一个 example,而 describe 在做的事情就组织着这些小东西!

it method

上面的例子中,我们建立了一个 example group 而在这个介绍的语法里,我们要建立单一个测试,也就是一个小的 example

回到上面的例子,我们继续写下去,我们想了一下,希望汉堡要有种类,就用坊间常见的汉堡来做例子就可以了!

RSpec.describe 'Burger' do
  it 'has a type' do
    ...
  end
end

可以看到我们写了一个 it 这也是一种方法,只能存活在 example group 里面,而後面会接一段字串来描述这个测试的目的是什麽?然後再接一个 block。

这个 it 方法最大的价值就在於,他能够让一个测试变得易读,然後清楚的描述这个行为是什麽。

而不是在描述的地方写到你是如何做到的,不需要写我是用 Array 来存放,或用 Hash 做 map,诸如此类的东西,不需要被特别的提出来!只需要专注在这个测试的行为是什麽?什麽样的行为?

像我们刚刚写的就很明确,一个汉堡他应该要有种类,非常的易读!

这主要是 it 这个方法的目的,描述一个测试的行为,不是结果喔!结果会有另一个方法来执行,但这边的目的在於 描述物件的行为

expect & eq methods

接着继续来开发我们的汉堡店,还记得开发的需求是说 汉堡需要有不同的种类,就着我们就来想像一下,我们需要做出汉堡的实体,然後给予他种类,并通过测试。

上述也算是一个 TDD 的回圈喔!还记得吗?现在我们在根据需求并使其通过测试!

RSpec.describe 'Burger' do
  it 'has a typy' do
    burger = Burger.new('Big mac')
    ...
  end
end

我们在这边建立了一个 burger 的实体,便给予他种类的名称Big mac,接着我们需要测试它,所以我们会用到一个叫做 expect 的方法。

expect 这个方法接收的参数是我们要测试的对象,也就是我们刚刚做出来的 burger

那要记得我们这次测试的目的是,希望他有一个种类,所以我们在 expect 的後方写的是 burger.type 并希望得到我们要的答案!

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

接着我们继续的写下去:

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

我们专注在第四行上面,如果用我破烂的英文来翻译的话,会是

期待汉堡的种类等於 Big mac

这样应该是还蛮容易阅读的,虽然不是文法很精确的英文,但我觉得看得很舒服!

我们重新的整理一下我们写了一些什麽,以及他们有什麽用途。

首先是 expect,他是一个 RSpec 提供的方法,可以接受物件、物件的属性、方法、甚至是基本的 Ruby 运算式,而这个 expect 方法会针对你传入的参数进行运算,并且回传一个物件。

#<RSpec::Expectations::ExpectationTarget:0x00007fb81f240278 @target="Big mac">

若是把 expect(burger.type) 印出来就会长的像上面一样,是一个物件的概念,以及具备 @target 这个实体变数 ( @target 会是我们主要接受测试的项目喔! )

而这个物件会拥有 to 这个实体方法,这个 to 方法呢,需要接受一个叫做 matcher 的物件,那这个物件是怎麽产生的?

就在於後面我们写入的 eq('Big mac') 这个方法也会产生一个物件

#<RSpec::Matchers::BuiltIn::Eq:0x00007fdb92afa3f0 @expected="Big mac">

具有一个 @expected 的实体变数!

to 这个方法呢,简单的来说就是比对这两个物件的实体变数,回传成功或是失败,当然实际上更复杂一点,有针对许多的情况来做 raise error 但基本逻辑就是这样进行的,所以若是你没有传入 matcher 这个例子就没有办法完成!

OK,所以到这边我们已经写完了一个最基本的测试了!接着我们对着终端机输入 rspec spec/burger_spec.rb 会看到~

竟然没有通过...但相信看过昨天的文章就能够知道错误是在哪里发生的,而明天开始将会一步一步地读懂错误的讯息并且使其通过测试~毕竟看懂错误讯息也是工程师很重要的一项技能喔!

小结

今天我们学会了整个 RSpec 的主架构,从利用 describe 框出一个区块让我们写小 example 再到使用 it 来叙述我们测试的行为,以及利用 expecteq 来进行比对测试!

这样可以算是一个 unit test 罗!运用这几个方法,相信很简单的测试也难不倒你了,但可惜的是我们最後遇到了错误讯息,但没关系!我们明天来解决它。


<<:  Day5 Python 基础教学 (四)

>>:  [Day5] POSTMAN及取得Nonce值

Day 15 — To Do List (1) 了解 HTML Service

昨天我们做完前置作业了,今天我们来看一下这个 HTML Service 是怎麽用! 简单来说,就是可...

第26天:实作档案上传功能(3)

昨天我们档案上传功能有个问题是不能上传太大的档案,根据我的研究发现,写入档案的部分所需要的时间是不一...

证书颁发机构(CA)-Web服务器证书格式

-网站WentzWu.com的X.509证书样本 因为如今在实践中很少使用正斜杠“ /”作为分隔符...

Angular 路由(Day24)

在完成登入功能之前,我想要先介绍一下Angular的路由系统 Angular Routing: In...

Day22_控制项(A17营运持续管理之资讯安全层面)-2021/10/05

▉A.17 Information Security Aspects Of Business营运持续...