测试 利用快照来测试 Controller 和 View

yesmeck · 2016年09月05日 · 最后由 42thcoder 回复于 2016年09月09日 · 7461 次阅读

Facebook 出品的一个 js 测试框架 Jest 最近推出一个新功能,给第一次跑测试的结果生成一个快照,后面就可以用这个快照来保证代码不会被搞坏。

受 Jest 的启发,我觉得这个快照测试也可以用到 Rails 的 controller 和 view 测试中来,见 https://github.com/yesmeck/rspec-snapshot

拿 Ruby China 的测试举个🌰,比如这个测试,利用 rspec-snapshot 的话可以写成这样:

it 'should work' do
  @replies = create_list(:reply, 3, user: user, topic: topic)
  get "/api/v3/users/#{user.login}/replies.json", offset: 0, limit: 2

  expect(response.body).to match_snapshot('users/:login/replies')
end

这样只要在第一次写测试的时候保证生成的快照是正确的,后面就可以保证这个接口不会被不小心搞坏掉。

VCR 是用来对外部 HTTP 请求进行快照的,LZ 几年前就在用啦 😂

哈哈抱歉没有仔细读 LZ 的内容拉。类似的 e2e test 中 view 我试过截图然后比较 diff 来保证 view 没有被破坏。

总觉得这个 第一次写测试的时候保证生成的快照是正确的 思路有点怪,难道对结果的断言会变,或者一直保持不变?

@hz_qiuyuanxin 测试更多的时候是希望及时的发现错误和潜在的错误

快照不能描述你想要达到什么目的,如果快照错了呢?

所以要在第一次生成快照的时候要查看快照确保证快照是正确的。

还是这个例子,这里其实是手写了测试希望得到的结果(你也要保证没有写错),用快照的话就是这个希望得到的结果是自动生成出来的,生成出来后要查看确保生成出来是正确的。

这个特别是在 API 返回的结果非常复杂的时候会很方便,我们业务中一些 model 会有几十个字段,如果要对在测试里把 API 希望得到结果完整的写一遍会很啰嗦,用快照就可以省掉这一步。

#4 楼 @hz_qiuyuanxin #6 楼 @Rei

确实跟平时的测试思路有点不一样,一般的逻辑是先写一个“预期结果”,然后执行要测试的方法得到“执行结果”跟“预期结果”进行比较。

用快照的话就是先执行要测试的方法得到“执行结果”,然后肉眼确定“执行结果”正确,后面就可以把这个正确的“执行结果”作为“预期结果”,这样同样可以保证在迭代的时候不把原有功能搞坏。

9 楼 已删除

#9 楼 @Rei

不是,我觉快照比较适用的场景是返回数据很复杂的 JSON API 和 view,在“预期结果”很复杂的时候手写一遍是比较烦的。

#5 楼 @onemagicant @yesmeck

我认为,测试案例的目的为了验证逻辑的正确性,通过采用断言来实现,而结果并不是确定性的。 另外,通过肉眼来确定第一次返回的复杂数据结构,这苦逼活应该交给计算机,程序员应该处理逻辑性部分。

it 'should work' do
  @replies = create_list(:reply, 3, user: user, topic: topic)
  get "/api/v3/users/#{user.login}/replies.json", offset: 0, limit: 2
  expect(json['replies'].size).to eq 2
  fields = %w(id user body_html topic_id topic_title)
  expect(json['replies'][0]).to include(*fields)
  expect(json['replies'][0]['id']).to eq @replies[2].id
  expect(json['replies'][0]['topic_title']).to eq topic.title
  expect(json['replies'][1]['id']).to eq @replies[1].id

 expect(response.body).to match_snapshot('users/:login/replies') # 其他信息快照记录
end

@hz_qiuyuanxin

如果是 vcr 那种风格的快照,match_snapshot 会很难实现。

返回数据很复杂的 JSON API, 更适合的解决方案是: https://github.com/sharethrough/json-schema-rspec

需要 登录 后方可回复, 如果你还没有账号请 注册新账号