[WIP] Rails rspec document
创建: 2019/10/09
更新: 2019/11/30 补充before的参数 all/each
更新: 2020/4/22 补充多个before的运行顺序, 补充after, around
https://rspec.info/documentation/
安装与使用 | |||||||
Gemfile |
group :development, :test do gem 'rspec-rails', '~> 3.8' end
|
||||||
bash |
rails g rspec:install
|
||||||
生成spec文件 |
# RSpec hooks into built-in generators $ rails generate model user invoke active_record create db/migrate/20181017040312_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb # RSpec also provides its own spec file generators $ rails generate rspec:model user create spec/models/user_spec.rb # List all RSpec generators $ rails generate --help | grep rspec
|
||||||
运行 |
# Default: Run all spec files (i.e., those matching spec/**/*_spec.rb) $ bundle exec rspec # Run all spec files in a single directory (recursively) $ bundle exec rspec spec/models # Run a single spec file $ bundle exec rspec spec/controllers/accounts_controller_spec.rb # Run a single example from a spec file (by line number) $ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8 # See all options for running specs $ bundle exec rspec --help
● 避免每次都输入bundle exec bundle binstubs rspec-core
|
||||||
基本方法 | |||||||
describe/context |
给测试增加命名空间 ● context主要用于分条件测试,相当于if RSpec.describe 'sample test' do ... end ● 除了最外侧的,其他的可以省略 RSpec. RSpec.describe 'sample test' do describe 'A' do ... end end ● 参数除了字符串,也可以是class, 还可以省略 RSpec.describe Sample do
...
end
|
||||||
xdescribe/xcontext |
跳过测试, 状态为pending |
||||||
it/example/specify |
测试的基本单位(example) 完全同名it/example/specify RSpec.describe 'sample test' do it 'sample it' do end end ● it为叶代码块,内部不能有describe/context等 ● 同一个describe内部也可以有多个it describe 'sample' do it '...' { ... } it '...' { ... } ... end
● 同一个it内可以有多个expect describe 'sample' do it '...' { expect(...).to ... expect(...).to ... expect(...).to ... end end ● 不附加代码块默认为pending 可以用作待完成项目 |
||||||
xit/xexample/xspecify |
跳过测试, 状态为pending |
||||||
except |
描述期待的情况 RSpec.describe 'sample test' do it '1+1=2' do expect(1+1).to eq 2 end end
|
||||||
callback |
|
||||||
let |
参数作为变量使用,值为let代码块的返回值 lazyLoad let(:...) { ... }
|
||||||
let! |
直接评价, 不是lazyload 和before一样 |
||||||
subject |
测试对象为明确的一个(即在一定范围内expect的参数相同) 测试对象为subject的返回值 subject { ... } subject do ... end # 例 subject { User.name } subject { 1 }
● 用了subject则 expect 换成 is_expected
|
||||||
shared_examples it_behaves_like |
定义相同的it,重复利用 shared_examples 'name' do it { is_expected.to ... } end # 没定义subject的 shared_examples 'name' do it { expect(...).to ... } end 使用 it_behaves_like 'name'
● 例 RSpec.describe Book do let(:book) { Book.create(title: title) } subject { book.title } shared_examples 'sample' do it { is_expected.to eq(title) } end describe '#title = a' do let(:title) { 'a' } it_behaves_like 'sample' end describe '#title = b' do let(:title) { 'b'} it_behaves_like 'sample' end end
|
||||||
shared_context include_context |
和上面差不多 例 RSpec.describe Book do let(:book) { Book.create(title: title) } subject { book.title } shared_examples 'sample' do it { is_expected.to eq(title) } end shared_context 'title = a' do let(:title) { 'a' } end shared_context 'title = b' do let(:title) { 'b' } end context '#title = a' do include_context 'title = a' it_behaves_like 'sample' end context '#title = b' do include_context 'title = b' it_behaves_like 'sample' end end
|
||||||
pending |
用于测试出错,暂时保留 context '#title = b' do include_context 'title = b' pending 'must be error' it_behaves_like 'sample' end
|
||||||
skip | 跳过测试, 状态仍然为pending | ||||||
to, not_to/to_not |
后面指定matcher
expect(...).to ...
is_expected.to ...
|
||||||
matcher | |||||||
eq | 是否相等, == | ||||||
be |
● 和 =, >=, <= 配合使用, 比较值大小 ● 不带符号则相当于equal?, 比较是不是同一个(指针是否相同) expect(User.first).to be User.first
|
||||||
be_xxx |
ruby/rails的带?的方法去掉问号前面加be_ (方法必须返回true/false) |
||||||
be_truthy / be_falsey |
和be true/false区别 nil也算falsey |
||||||
change + from / to / by |
expect{...}.to change{...}.from(...).to(...) expect{...}.to change(...).by(...)
|
||||||
include | 用于对数组/hash/字符串进行验证 | ||||||
raise_error | 可以加参数表示具体抛出的错误 | ||||||
be_within + of |
be_within(Y).of(X) x+-Y范围内 |
||||||
mock | |||||||
feature | |||||||