使用RSpec编写具有可读性的功能测试

简介:
 Chris Zetter是FutureLearn产品组的一名开发者,他为我们讲述了自己的小组为了使 功能测试兼具可维护性与可读性,在把Cucumber替换为RSpec之后是如何来编写测试的。
  测试是建立与维护一个大型平台不可或缺的一部分。每当我们为FutureLearn这个平台增添新功能时,我们都会编写自动化的功能测试来记录这些新功能是如何运作的,并确保他们不运转时我们也能知晓。
   令人爱恨交加的Cucumber
  Cucumber是一款用来编写功能测试的常用工具,每当我们开启项目时它都是我们的不二选择。它可以让我们以用户的视角编写出高层级的行为驱动测试。
Feature: Enrolment
Scenario: Enrolling in a course
Given there is a course
And I am logged in as a learner
When I enrol on a course
Then the course should appear in 'my courses'
  我们乐于使用Cucumber因为它可以使根据用户故事编写测试变得简单易行,而且写完的测试通俗易懂。然而使用Cucumber也有些许不足之处。首先,我们已经在项目里使用了RSpec,再引入Cucumber意味着又要多维护一个测试框架;其次,由于两者的DSLs和测试运行器不同,在他们之间进行脑筋切换又会带来额外开销;最后,我们特别不喜欢Cucumber所使用的正则表达式,因为同 Ruby的标准方法调用相比,它们使测试变得更加晦涩难懂。
   编写更好的RSpec features
  那么,我么该如何在不失测试可读性的前提下停用Cucumber呢?
  我们已经开始使用RSpec features来替代Cucumber,它们通常看起来会是这样:
feature 'Enrolment' do
scenario 'Enrolling in a course' do
course = FactoryGirl.create(:course)
learner = FactoryGirl.create(:learner)
login_as learner
visit course_path(course)
find('.join').click
expect(page).to have_content('Thanks for joining!')
visit '/'
expect(page).to have_main_header('My Courses')
expect(page).to have_content(course.full_title)
end
end
  它们总是趋于变得很长,使得难以辨明其究竟在测试些什么。而且难以区分诸如Arrange, Act, Assert(在Cucumber里又被称为’Given’、’When’和’Then’)这些部分。我们试过在代码中这些步骤里添加注释,但它们就和通常那些程序代码里的注释一样不尽如人意:一段时间之后这些注释就变得与实际代码不同步了。
  一般来说,如果是在程序里别的地方写出这么长的方法,我们就会有所警觉,并且通常会采用提取方法的办法进行重构。何不也这么做呢?让我们依据Cucumber步骤的风格,把这些代码也提取成一个个方法吧。
feature 'Enrolment' do
scenario 'Enrolling in a course' do
given_there_is_a_course
and_i_am_logged_in_as_a_learner
when_i_enrol_on_a_course
then_the_course_should_appear_in_my_courses
end
def given_there_is_a_course
@course = FactoryGirl.create(:course)
end
def and_i_am_logged_in_as_a_learner
@learner = FactoryGirl.create(:learner)
login_as @learner
end
def when_i_enrol_on_a_course
visit course_path(@course)
find('.join').click
expect(page).to have_content('Thanks for joining!')
end
def then_the_course_should_appear_in_my_courses
visit '/'
expect(page).to have_main_header('My Courses')
expect(page).to have_content(@course.full_title)
end
end
   我们有何发现
  我们移除了全部的Cucumber功能测试,并把它们中大部分用新式的RSpec features加以重写。这样一来即可保证拥有Cucumber所提供的优秀的可读性,又使得测试变得更加便于编写和维护。
  我们做了一个慎重的决定,不把各个features文件里提取的方法进行复用,因为担心这么做会使得测试难于理解。我们发现在编写一个feature下的多条scenario时,会不自觉的就想要进行代码复用。

最新内容请见作者的GitHub页:http://qaseven.github.io/
相关文章
|
芯片
毕业设计 基于51单片机的手机蓝牙控制8位LED灯亮灭设计
毕业设计 基于51单片机的手机蓝牙控制8位LED灯亮灭设计
424 0
|
2月前
|
SQL JSON 缓存
别再用过时的地区数据了!闸北区都消失了,教你一次性搞定省市区同步更新!(附实战源码)
本文记录了更新地区表至最新行政区划的完整实践:从权威数据源获取2024年省市区数据,通过Python脚本实现新旧表(省-市-区三级)精准比对,支持新增、软删除及层级关系维护,并附详细代码与分步缓存策略,兼顾准确性、安全性和可追溯性。(239字)
229 5
|
6月前
|
弹性计算 搜索推荐 应用服务中间件
阿里云服务器租用费用价格表:从入门级配置到企业级高性能收费标准
阿里云服务器优惠汇总:轻量应用服务器200M带宽38元/年起,ECS云服务器2核2G 99元/年,2核4G 199元/年,4核16G 89元/月,8核32G 160元/月,香港轻量25元/月起,GPU服务器低至1681元/月,新老用户同享,续费同价,限时秒杀,配置丰富,适合个人与企业多种应用场景。
1641 4
|
9月前
|
存储 大数据 Unix
Python生成器 vs 迭代器:从内存到代码的深度解析
在Python中,处理大数据或无限序列时,迭代器与生成器可避免内存溢出。迭代器通过`__iter__`和`__next__`手动实现,控制灵活;生成器用`yield`自动实现,代码简洁、内存高效。生成器适合大文件读取、惰性计算等场景,是性能优化的关键工具。
443 2
|
Android开发 UED Kotlin
Android中如何跳转到Wi-Fi开关设置页
本文介绍如何在Android应用开发中使用隐式Intent引导用户至特定系统设置页面,如Wi-Fi设置页,并提供Kotlin代码示例。通过设置Intent的Action属性并检查设备兼容性,可轻松实现跳转功能,提升用户体验。此外,还列举了其他常用设置页面的Intent Action及注意事项。
474 15
|
IDE 测试技术 开发工具
NumPy 代码调试与错误处理
【8月更文第30天】NumPy 是 Python 中用于科学计算的核心库之一,提供了高性能的多维数组对象和大量的数学函数。尽管 NumPy 提供了许多方便的功能,但在实际编程过程中难免会遇到各种各样的问题。本文将介绍一些调试 NumPy 代码的技巧,并讨论如何处理常见的错误。
1016 2
|
算法
第四章 KMP算法理论基础
第四章 KMP算法理论基础
400 0
|
机器学习/深度学习 计算机视觉
YOLOv8改进 | Neck | 在网络中替换c2f为融合蛇形卷积的C2f_DySnakeConv
本专栏介绍的DSCNet采用蛇形动态卷积,增强对细长弯曲结构(如血管)的特征提取。该卷积操作灵感来自蛇形曲线,能自适应调整权重以关注管状结构局部特征。通过动态卷积核,网络能更好地处理形状变异,提升目标检测的准确性和鲁棒性。
|
存储 缓存 边缘计算
网站静态资源访问加速
本方案使用阿里云CDN产品来分发OSS上的网站静态文件,不仅可以降低源站的负载压力,还能够提升网站的访问性能,同时还能在高并发场景下为您节约成本。
416 4
|
大数据 Linux 虚拟化
OVA Import:一个最快速度打造Linux虚拟机的操作 | Linux vmware
OVA Import:一个最快速度打造Linux虚拟机的操作 | Linux vmware
442 0

热门文章

最新文章