阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

使用 Selenium 和 Castle 进行测试驱动开发

  • 2007-03-29
  • 本文字数:3464 字

    阅读完需:约 11 分钟

引言

测试驱动开发(TDD,Test Driven Development)的例子大多是基于非常简单的单元测试。如何在大规模的应用中使用 TDD 常常是一项挑战。在本教程中,我们将展示如何使用 Selenium 和 Castle 以测试先行原理来构建一个 Web 应用。

前期准备

比方说,开发者需要应用“测试先行”的思想,为应用程序编写一种带有以下特征的方法:

管理用户(添加新用户,删除,编辑用户资料,所有用户列表)

在该测试用例中,每个用户都必须拥有一个全名、一个用户名、一个密码和一个邮件地址等,所有的信息都是必须的。

基本步骤

典型的步骤如下:

  1. 编写测试
  2. 确保测试失败
  3. 编写代码使测试成功
  4. 重构
  5. 重复以上步骤

第一个测试

第一个要进行的测试是添加新用户的测试。测试驱动开发与其说是测试的技术不如说是设计的技术,因为当编写测试的时候,我们将规定代码或页面的工作方式,这个过程就是设计。

对于添加一个新用户而言,像下面这样简单的表单就够了:

对于功能测试,开发者需要打开添加页面(准备阶段),填写表单并保存(执行阶段)和确认用户是否被保存了(项目的确认阶段)。为了做到这一点,开发者需要更新页面,在左侧添加一个新的包含用户信息的列表,以便在点击“保存”按钮后可以验证用户存在与否。

使用 Selenium

对于像这样的工作,开发者需要一个能够适合他们的执行这个行为的工具。Selenium 在浏览器中可以方便地做到这一点,它也是一个很好的开源工具,可以根据你自己的需要进行修改。Selenium 提供了基于 Web 的功能测试,而且只需要一个为开发人员运行这些行为的编译器,Selenium 就能使这些测试的编写过程像 HTML 测试那么简单:

对于希望将自己的测试整合到一个持续集成的工具中的开发者而言,最大的喜讯莫过于,他们可以用自己喜欢的语言(如 C#、JAVA、VB.NET、Ruby 或者 Python 等)来编写测试,并利用 Selenium 的一个名为 Selenium RC 的扩展实现整合。

比如使用 Selenium RC 时,该测试的.NET 版如下:

第二步,保证初始的测试失败

在这一阶段开发者没有写任何代码,因此测试失败。 首先启动 Selenium RC 服务器(一个处理 Selenium 指令并将它们传送给浏览器的小型 java 服务器):

java -jar selenium-server.jar

意料之中,运行的测试失败:

这是一个好现象,因为这意味着测试在应该失败时失败了。否则这次测试就没有起到任何作用,是毫无意义的。

第三步,编写代码

在 TDD 实施步骤的第三步中,开发者需要编写代码。这意味着当反向测试时,代码应该不会运行失败。下一步建立 User 控制器,然后建立视图并运行测试:

接着再建立一个空的 add.vm,并且重新运行该测试:

Selenium.SeleniumException: ERROR: Element link=Add new user not foundat Selenium.HttpCommandProcessor.DoCommand(String command, String[] args)

at Selenium.DefaultSelenium.Click(String locator)
at MRProjectTest.Functionals.Selenium.ManageUsersTests.TestAddNewUser() in
ManageUsersTests.cs:line 34

因为错误报告说在网页上找不到内容,所以我们就把内容添加到 add.vm 中:

重新测试:

错误再次出现,因为将表单的内容提交到 create.aspx 之后,点击页面按钮的行为尚未实现。

然后添加如下代码以保存数据:

现在我们稍等片刻,因为无论 list 行为还是数据库中都不存在 User 类。

在表示层下对其它层进行 TDD

为了构造代码,开发者需要根据“测试先行”构造 User 类。 虽然在有的情况下这没有必要,因为 ActiveRecord 已经很好地被测试过了,并且它也通过了功能测试。 但仍需指明应该如何处理一些更为复杂的情况。

接下来的测试不是功能测试,而是集成测试,一个利用数据库的单元测试:

测试它会不会失败。其实它甚至没有进行编译,所以首先是构造一个没有任何方法的 User 类,强制编译其代码:

现在,运行测试:

Castle.ActiveRecord.Framework.ActiveRecordException: An ActiveRecord class (UserManagement.Model.User) was used but the framework seems not properly initialized. Did you forget about ActiveRecordStarter.Initialize() ?at Castle.ActiveRecord.ActiveRecordBase.EnsureInitialized(Type type)

at Castle.ActiveRecord.ActiveRecordBase.Save(Object instance)
at Castle.ActiveRecord.ActiveRecordBase.Save()
at MRProjectTest.Database.UsersDataAccessTests.TestSaveNewUser()
in UserDataAccessTest.cs:line 23

错误表明 User 类没有在 ActiveRecord 中初始化,因此对测试调整如下:

为 ActiveRecord 与构造器加上适当的属性,并且重新运行测试。现在相应的数据库表还没有,但这可以在测试中添加如下代码迅速进行补救:

ActiveRecordStarter.CreateSchema();// 创建数据库 schema

运行完测试后,数据库表就生成了,但仍有一个问题:

System.NotImplementedException: todoat UserManagement.Model.User.Find(Int64 id) in User.cs:line 72

at MRProjectTest.Database.UsersDataAccessTests.TestSaveNewUser() in
UserDataAccessTest.cs:line 41

完成对 User 类 Find() 方法的实现:

<span color="#0000ff"> public static User Find(long id)<br></br> {<br></br> return (User) FindByPrimaryKey(typeof(User),id,false)<br></br> }</span>终于,一个数据库测试能够运行了!

自顶而下的 TDD 方法

通常,由于前面提到的两个原因(译者注:ActionRecord 已经很好的被测试过,并且通过了功能测试),这类数据库测试是不需要的,但是我们还是做了这种测试,因为在一个针对 n 层应用的测试先行的垂直开发环境中,自顶而下的 TDD 流程才能被理解。

回到功能测试

既然 User 类存在并且数据库访问正常,是时候继续进行表示层的工作了。

实现 list 的行为和视图:

<span color="#0000ff"> public void List()<br></br> {<br></br> PropertyBag["users"] = User.FindAll();<br></br> }</span>创建一个 list.vm:

上面的视图中使用了 GridComponent。现在运行测试,开发者应该会首次看到正常运行的 UI 测试。

编辑功能

下一步就需要给网站增加用户编辑的功能。 功能的流程是这样的:在用户列表页面,每一个用户都有一个编辑链接,一旦用户点击链接后会转到编辑页面,在那里可以修改用户的详细信息。当表单保存后,用户就返回到列表页面。现在编写测试:

一个用户被添加到了数据库,当列表网页被打开的时候,就有内容可以编辑了。但还有一个问题。如果测试运行两次,那么同一个用户将在数据库中被插入两次。为了避免这种潜在的错误,照下面这样做就可以了:

运行所有的测试,编辑的测试现在是失败的:

Selenium.SeleniumException: ERROR: Element link=Edit not foundat Selenium.HttpCommandProcessor.DoCommand(String command, String[] args)

at Selenium.DefaultSelenium.Click(String locator)
at MRProjectTest.Functionals.Selenium.ManageUsersTests.TestEditUser() in
ManageUsersTests.cs:line 28

为解决这个问题,在 list.vm 中添加编辑链接:

然后修改控制器中的行为:

<span color="#0000ff"> public void Edit(long id)<br></br> {<br></br> PropertyBag["user"] = User.Find(id);<br></br> }</span>现在编辑这个行为的视图:edit.vm

因为值同样会被保存到 update 行为中,我们还会有下面的代码:

<span color="#0000ff"> public void Update([DataBind("user")] User user)<br></br> {<br></br> user.Update();<br></br> RedirectToAction("list");<br></br> }</span>

成功了!!

开始重构

还有机会在一些地方进行重构。首先,TestAddNew 和 TestEdit 方法几乎相同:

同时:

运行测试,一切照样运行。现在进一步研究展示视图中的代码,它们有同样的问题:add.vm 和 edit.vm 几乎如出一辙。 将公用部分单独放入 _form.vm。运行测试依然可以确定该应用程序是正常工作的:

对于删除操作,同样可以利用“测试先行”的原理。对于数据验证或者用户可以使用的任何功能,添加新的测试,然后加入代码最终使其通过这些测试。

结论

这是一个使用增量体系结构的方法来利用 TDD 设计应用的例子。在实际的系统体系结构中,架构师与开发者不需要提前一个月进行设计。在代码被编写与测试时,架构和设计才被构建起来。在这种情况下,经常会有变化,因为持续重构代码可以使代码更加优化,这些都是 TDD 的原则与“测试先行”所支持的。

Resources 资源:

  1. Selenium - http://www.openqa.org :开源网站功能测试工具
  2. Castle Project (MonoRail and ActiveRecord) - http://www.castleproject.org/ :开源的轻量级 ASP.NET /ADO.NET 选择

源代码下载

关于译者

王川川,混迹于武汉大学 Google Camp ,热衷于 Web 开发,目前关注 IBM 的 portal 产品相关开发。

2007-03-29 08:083164

评论

发布
暂无评论
发现更多内容

Dynamic Wallpaper for Mac(Mac动态壁纸桌面)v17.5中文版

影影绰绰一往直前

dynamic wallpaper怎么设置动态屏保?dynamic wallpaper破解下载

Rose

Dynamic Wallpaper下载 Mac壁纸app 动态屏保

搭建拍卖直播商城平台最新商业模式,让你实现多元化盈利

软件开发-梦幻运营部

2024-03-09:用go语言,我们把无限数量的栈排成一行,按从左到右的次序从 0 开始编号, 每个栈的的最大容量 capacity 都相同。实现一个叫「餐盘」的类 DinnerPlates, Di

福大大架构师每日一题

福大大架构师每日一题

数据库中 SQL Hint 是什么?

LakeShen

数据库 sql

深入解析汽车MCU的软件架构

智趣匠

汽车电子 汽车

青否数字人直播的无限续写功能到底有多牛!

青否数字人

数字人

After Effects 2023中文版下载 及 ae2023介绍

Rose

adobe After Effects 2023下载 AE2023中文直装版

LLM 推理优化探微 (3) :如何有效控制 KV 缓存的内存占用,优化推理速度?

Baihai IDP

程序员 AI LLM 白海科技 大模型推理

Video Converter X2 for Mac(功能齐全的视频格式转换器)v1.3.1激活版

影影绰绰一往直前

汉化版数据库 Navicat for SQL Server mac永久使用

Rose

数据库 SQL Server Navicat 数据库下载

microsoft office ltsc 2021最新永久密钥分享 Mac/win

Rose

office2021 Mac破解版 office2021密钥 office ltsc 2021中文版

团队管理者应该参与编程吗?

刘华Kenneth

编程 管理

脑机接口+AI,会让人类进化到什么阶段?

算法的秘密

Redis之bitmap类型解读

百度搜索:蓝易云

redis 云计算 Linux 运维 BitMap

香水界的黑科技:AI助力设计新香型

算AI

人工智能 创新

Aiseesoft iPhone Cleaner for Mac(ios清理工具)v1.0.30中文激活版

影影绰绰一往直前

DJ Mix Pads 2 - Remix Version for Mac(独特DJ混音创作软件)v16.0.1激活版

影影绰绰一往直前

Photoshop 2024 透视变形功能介绍

Rose

Photoshop 2024直装版 透视变形 ps2024教程

如何正确定义性能瓶颈

老张

性能优化 性能测试 性能基线

PHP用CURL发送Content-type为application/json的POST请求方法

百度搜索:蓝易云

php Linux 运维 云服务器 curl

OpenSearch 与 Elasticsearch:哪个开源搜索引擎适合您?

极限实验室

搜索引擎 elasticsearch opensearch service

如何在 Parallels Desktop for Mac 中备份、恢复或转移 Windows 虚拟机

Rose

虚拟机 Windows系统 Parallels Desktop教程 备份、恢复或转移

ubuntu中使用iptables限制端口

百度搜索:蓝易云

Linux ubuntu 防火墙 iptables 云服务器

Garden Planner for Mac(园林绿化设计软件)v3.8.59注册激活版

影影绰绰一往直前

Aiseesoft iPhone Unlocker for Mac(苹果设备解锁工具)v2.0.38激活版

影影绰绰一往直前

MediaHuman YouTube Downloader mac(YouTube视频下载工具)v3.9.9.89中文注册版

影影绰绰一往直前

CleanMyMac X v4.15.1 最新破解版下载 Macos系统 最佳清理工具

Rose

CleanMyMac X中文版 CleanMyMac X破解版 Mac系统清理 苹果电脑系统优化

Linux系统:CentOS 7 CA证书服务器部署

百度搜索:蓝易云

Linux centos 运维 云服务器 ECS

AI微调营 毕业总结

Ksnshejn

Capture One Pro 23 飞思 最新中文版 摄影调色软件

Rose

Capture One Pro 23 飞思 摄影调色软件 摄影后期

使用Selenium和Castle进行测试驱动开发_研发效能_Dan Bunea_InfoQ精选文章