RSpec是用于Ruby语言的BDD测试框架。主要有3个独立的部分组成:
- rspec-core
- rspec-expectation
- rspec-mocks
RSpec提供的API允许我们以一种贴近自然语言表达的方式来编写测试用例。
目录结构
通常使用RSpec的项目目录结构如下:
<your project>
|--> lib/ # 源代码目录
|-->spec/ # 测试文件放入spec目录
|-->xxxx_spec.rb # xxxx_spec.rb为测试文件
基础概念
RSpec中包括如下基础概念:Group,Example, Expectation
- Group:表示测试用例的集合
- Example:功能API的使用示例
- Expectation:功能API的执行期望结果
test,spec和example的区别
这3个概念都表示我们编写的测试用例,可以互相替换使用,但是各自的语义侧重不同:
- test:验证一段代码执行正确
- spec:描述一段代码的期望行为
- example:展示API的期望应用方式
针对上述概念,RSpec提供了如下的API:
- RSpec.describe:创建example结合(测试用例集合,记得test、spec和example是可替换的概念,只是语义侧重不同)
- it:创建单个的example(单个的测试用例)
- expect:验证期望的结果(其他测试框架中的assert语句)
举例子:
Sandwich = Struct.new(:taste, :toppings)
RSpec.describe 'An ideal sandwich' do
it 'is delicious' do
sandwich = Sandwich.new('delicious', [])
taste = sandwich.taste
expect(taste).to eq('delicious')
end
end
执行测试
在项目目录下执行rspec命令,RSpec会在spec目录下寻找xxxx_spec.rb的文件,将其作为测试文件,并运行其中的测试用例。
共享设置
一个example组里,多个example执行前可能会设置相同的东西,RSpec提供了3种方式方便我们抽取设置(set up)逻辑:
Hooks
RSpec提供了before方法,该方位会在每个example(test,或者叫spec)执行前执行。
Sandwich = Struct.new(:taste, :toppings)
RSpec.describe 'An ideal sandwich' do
before {@sandwich = Sandwich.new('sandwich', [])}
it 'is delicious' do
taste = @sandwich.taste
expect(taste).to eq('delicious')
end
end
Helper方法
每个example组都是一个Ruby类。所以,我们可以在类中定义helper方法,达到设置共享的目的,如:
Sandwich = Struct.new(:taste, :toppings)
RSpec.describe 'An ideal sandwich' do
def sandwich
@sandwich ||= Sandwich.new('sandwich', [])
end
it 'is delicious' do
taste = sandwich.taste
expect(taste).to eq('delicious')
end
end
使用let
RSpec提供了let函数,方便设置共享,可以将上述例子的helper方法替换成如下的函数定义。
let(:sandwich) { Sandwich.new('delicious', [])}
let将变量sandwich与后面的block绑定,使用了memoization技术,当有example首次访问sandwich变量的时候,关联的block执行将结果保存,后续对sandwich的访问都会直接返回。
Content mainly from 「Effective testing with Rspec 3」by Myron Maston, Ian Dees