我目前在重写我一个客户的一个简单的电子商务应用程序。新版本使用Scala和优秀的Lift框架来实现,是一个已完成六年的的struts/JSP版本的重写。核心应用大部分是相同的,但我加入一系列新的和改进的管理功能。
通常,我会建立个简单且容易理解的应用程序,例如使用普通TDD的原则,先创建单元测试再由其驱动代码编写。我有时也会加入一些基本的UI测试,通常像使用Selenium,或只是运用HtmlUnit来从前端来验证。不过,我喜欢用这些不同类型的项目来探索更好的完成方式。因此,我决定使用Aslak Hellesøy的优秀的Cucumber框架的行为驱动开发方法(BDD)。 (等我搞清楚一切后,我将发布更多关于安装以及Cucumber和cuke4duke结合sbt使用的详细信息,!)
在这篇文章中我想整合Cucumber的特点和情景,并探讨一些我关于如何以及在何种项目以及哪部分使用BDD的思考。
对什么使用BDD
我是TDD方式的坚决拥护者,我打算在关于底层细节部分(即单元测试和组件测试)中遵循这一点。因此,我期待将BDD使用于高级别的业务需求和验收标准中。我的目标是使用BDD和Cucumber来确保我编写的应用程序确实满足了其业务期望。底层测试将仍然使用ScalaTest,以确保我所写的完成了我所期望它完成的,并同时去除了结构上以及实现细节的影响。
哪里可以整合BDD
鉴于对BDD适用范围的定位,我一直在努力改进的是在我的应用程序中以Cucumber步骤定义(步骤定义是实际执行场景以及由行为决定的条件的代码部分)为目标的正确的程度。以下各段落描述了每一个我曾考虑过的不同的选项,其优点和缺点:
用户界面使用BDD——在此方法中的步骤定义被实现为对正在运行的网络应用程序执行。这通常是使用了如Selenium或HtmlUnit技术实现的。每个场景加载网页,点击链接,填写并提交表格,对返回的HTML文档和相关资源进行断言。
优点:
行为会在整个应用程序中被断言。
该BDD的方法不仅可以用来驱动用户界面的发展还可以驱动应用逻辑。
缺点:
你只能对已完成的且配置完的应用程序执行特定的步骤——这可能使开发速度较慢。
一个基于Web的用户界面通常是一个Web应用程序中最不稳定的部分,因此可能由于用户界面调整导致步骤被打破,使得它的行为看起来不佳。步骤定义可能会变得相当脆弱。
使用BDD在这个部分可能不太适合,特别是当有用户体验和可视化设计人员存在,往往会导致UI的快速变化
在这个部分的测试一般需要写入大量的样板文件代码——这使得BDD的步骤定义更加复杂。 基于Web的用户界面测试可能更适合使用一套UI测试,可以只专注于验证界面显示和交互。
在Web协议使用BDD——在此方法中的步骤定义直接针对网络协议用于连接到该应用程序进行测试。例如,通过各个步骤进行HTTP调用应用程序并断言返回的结果是正确的,且包含预期的内容。
优点:
不必担心网页的复杂性,Javascript等等脚本或许在专门的一套UI测试上进行会更好。
非常适合用于RESTful或其他网络服务,返回的是结构化的数据,而不是HTML文档。
缺点:
你仍然只能对已完成的且配置完的应用程序执行特定的步骤
构建复杂的程序来仿真Ajax,可能比单单对用户界面进行测试更加复杂。
对返回的HTML内容的断言可能会比在UI部分使用像Selenium的框架更加复杂。
在这一部分的构建和测试也需要你支持一套的UI测试。
对于Web应用程序,在HTTP层的接口可能会改变相当频繁,需要经常更改步骤定义。这将是特别常见的繁重的Ajax应用程序。
控制器使用BDD——在此方法中,我们忽略了应用程序的用户界面和视图的部分。相反,相反,我们连接整个应用程序的控制器/片断层。步骤定义,然后将预先定义的请求写入控制器/片断层并断言响应动作和数据是正确的。
优点:
特点可以作为所创建的测试阶段的一部分来测试——无需额外配置。
由于应用程序的逐步完成,在这个部分上测试更趋于稳定。
在代码级别的调用和断言往往比用户界面的要容易。
缺点:
选择web框架是一套好的测试功能所必需的,可以使请求和响应能更容易的被模拟和断言。
在这个级别的测试往往要花费大量的逻辑,用于用户界面的交互,而不是对业务规则的断言。
要测试UI,一套UI测试是必需的,并且为了驱动UI,也将使相同的控制器/片断层被使用到。
服务使用BDD——在这最后的一个方法,我们要对控制器/片断层底层的部分进行测试。这通常是对服务级别的代码的测试,但也可能需要对域层次对象写一些步骤定义。由于这个部分,我们更关注测试应用程序的商业行为,而不是应用与用户的交互行为。
优点:
特点可以作为所创建的测试阶段的一部分来测试——无需额外配置。
在这个层的代码通常会比在较高层的更加稳定,从而使测试脆弱性更低。
在这个层的步骤定义通常比对UI或控制器要容易写以及维护。
我们在测试实际的业务规则,而不是用户可能如何与应用程序交互。
我们需要更少的测试特定的工具以及框架的支持。
缺点:
在这个层次的测试与更高层的对比起来,更少的对应用程序流量进行锻炼。
此外还需要一套测试来验证用户界面和控制器,以确保该系统的用户交互调用的服务使用了正确的数据,正确的顺序并正确的显示了结果。
企业可能更期待验证他们与应用程序的交互方式的行为。
开发人员必须非常有纪律,以确保没有业务规则,逻辑或行为被归到了控制器层来实现。
因此,应该如何抉择?
在看过所有可以使用BDD和Cucumber的地方后,我必须得出这样的结论,有没有彻底的赢家。这种感觉对我来说,步骤定义最好的搭配是,在服务层测试行为(验证业务规则和行为),与另一组测试用户界面相结合。通过组合这两种方法来覆盖应用应该能够足以有信心其行为是正确的。
这就使我开始思考创造行为特征描述的最好方式。难道我们应该创建一个对所需的行为的说明,然后写两个步骤定义——一个用于服务层,一个用于用户界面?还是我们写一个功能定义为企业服务描述所需要的行为,然后特别的为系统的用户交互提供可供选择的行为?
我仍然不能确定正确的回答这些问题。有没有人有任何想法或经验?在此同时,我要建立我的应用程序并尝试这两种方法,看看哪个完成的更好。
【英文原文:http://skipoleschris.blogspot.co.uk/2010/11/best-way-to-apply-bdd.html】
{测试窝原创译文,译者:大头}
译者简介:大头,在读日本九州大学修士,计算机专业,主研究方向为文本挖掘,及自然语言处理。