使用 RSpec 进行行为驱动测试

发表于:2007-9-27 15:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:网络转载

        测试热潮现在传播到了 Ruby 编程社区,并且愈演愈热。在过去一年里,测试领域中最为瞩目的创新应属 RSpec 的引入和快速发展,这是一种行为驱动测试工具。通过本文了解 RSpec 如何改变人们思考测试的方式。 
        在过去十年中,软件开发人员对测试的热情日渐低迷。同一时期出现的动态语言并没有提供编译程序来捕捉最基本的错误,这使得测试变得更加重要。随着测试社区的成长,开发人员开始注意到,除了捕获 bug 等最基本的优点外,测试还具有以下优势:

        测试能够改进您的设计。进行测试的每个目标对象必须具备至少两个客户机:生产代码和测试用例。这些客户机强制您对代码进行解耦。测试还鼓励开发人员使用更小、更简单的方法。 
        测试减少了不必要的代码。在编写测试用例时,您养成了很好的测试习惯,即只编写运行测试用例所需的最少代码。您抵制住了对功能进行编码的诱惑,因为您目前还不需要它。 
        推动了测试优先开发。您编写的每个测试用例会确定一个小问题。使用代码解决这个问题非常有用并且可以推动开发。当我进行测试驱动开发时,时间过得飞快。
测试提供了更多的自主权。在使用测试用例捕获可能的错误时,您会发现自己非常愿意对代码进行改进。

 
测试驱动的开发和 RSpec
        有关测试的优点无需赘述,我将向您介绍一个简单的使用 RSpec 的测试驱动开发示例。RSpec 工具是一个 Ruby 软件包,可以用它构建有关您的软件的规范。该规范实际上是一个描述系统行为的测试。使用 RSpec 的开发流程如下:

        编写一个测试。该测试描述系统中某个较小元素的行为。 
        运行测试。由于尚没有为系统中的相应部分构建代码,测试失败。这一重要步骤将测试您的测试用例,检验测试用例是否在应当失败的时候失败。 
        编写足够的代码,使测试通过。 
        运行测试,检验测试是否成功。 
        实质上,RSpec 开发人员所做的工作就是将失败的测试用例调试为成功的测试用例。这是一个主动的过程。本文中,我将介绍 RSpec 的基本用法。

        首先,假设您已安装了 Ruby 和 gems。您还需要安装 RSpec。输入下面的内容:

gem install rspec

使用示例
        接下来,我将逐步构建一个状态机。我将遵循 TDD 规则。首先编写自己的测试用例,并且直到测试用例需要时才编写代码。Rake 的创建者 Jim Weirich 认为这有助于角色扮演。在编写实际的生产代码时,您希望充当一回 jerk 开发人员的角色,只完成最少量的工作来使测试通过。在编写测试时,您则扮演测试人员的角色,试图为开发人员提供一些有益的帮助。

        以下的示例展示了如何构建一个状态机。如果您以前从未接触过状态机,请查阅 参考资料。状态机具有多种状态。每种状态支持可以转换状态机状态的事件。测试驱动开发入门的关键就是从零入手,尽量少地使用假设条件。针对测试进行程序设计。

        使用清单 1 的内容创建名为 machine_spec.rb 的文件。该文件就是您的规范。您还不了解 machine.rb 文件的作用,目前先创建一个空文件。

清单 1. 最初的 machine_spec.rb 文件
    require 'machine'

        接下来,需要运行测试。始终通过输入 spec machine_spec.rb 运行测试。清单 2 展示了预料之中的测试失败:

清单 2. 运行空的规范
  ~/rspec batate$ spec machine_spec.rb
/opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require':
 no such file to load -- machine (LoadError)
        from /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
        from ./state_machine_spec.rb:1
        from ...
   
 

        在测试驱动开发中,您需要进行增量开发,因此在进行下一次开发前,需要先解决此次测试出现的问题。现在,我将扮演 jerk 开发人员的角色,即只完成满足应用程序运行所需的最少工作量。我将创建一个名为 machine.rb 的空文件,使测试通过。我现在可以以逸待劳,测试通过而我几乎没做任何事情。

        继续角色扮演。我现在扮演一个烦躁的测试人员,促使 jerk 开发人员做些实际的工作。我将编码以下规范,需要使用 Machine 类,如清单 3 所示:

清单 3. 初始规范
  require 'machine'

describe Machine do
  before :each do
    @machine = Machine
  end
end

        该规范描述了目前尚不存在的 Machine 类。describe 方法提供了 RSpec 描述,您将传入测试类的名称和包含实际规范的代码块。通常,测试用例需要执行一定数量的设置工作。在 RSpec 中,将由 before 方法完成这些设置工作。您向 before 方法传递一个可选的标志和一个代码块。代码块中包含设置工作。标志确定 RSpec 执行代码块的频率。默认的标志为 :each,表示 RSpec 将在每次测试之前调用 set up 代码块。您也可以指定 :all,表示 RSpec 在执行所有测试之前只调用一次 before 代码块。您应该始终使用 :each,使各个测试彼此独立。

        输入 spec 运行测试,如清单 4 所示:

清单 4. 存在性测试失败
  ~/rspec batate$ spec machine_spec.rb


./machine_spec.rb:3: uninitialized constant Machine (NameError)

 

        现在,烦躁的测试人员要促使 jerk 开发人员做点什么了 — jerk 开发人员现在需要创建某个类。对我来说,就是修复测试出现的错误。在 machine.rb 中,我输入最少量的代码,如清单 5 所示:

清单 5. 创建初始 Machine 类
  class Machine
end
 

        保存文件,然后运行测试。毫无疑问,清单 6 显示的测试报告没有出现错误:

清单 6. 测试 Machine 是否存在
  ~/rspec batate$ spec machine_spec.rb


Finished in 5.0e-06 seconds

0 examples, 0 failures

41/41234>
《2023软件测试行业现状调查报告》独家发布~

精彩评论

  • jingwdongw
    2011-1-10 14:14:52

    请问我用rspec如何输出中文内容啊?可以正常输出英文字符,但中文输出总是乱码?这个问题可以解决吗?

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号