自动化测试是软件开发中一个重要但繁琐的环节。尤其是在用户界面(UI)测试中,由于应用界面在开发过程中经常变化,使得UI测试变得脆弱。此外,UI测试需要依赖浏览器来运行,这使得它们比常规单元测试要慢得多。因此,很多人选择不编写UI测试,认为这是可以理解的。
然而,也见过很多应用在UI上出现错误,尤其是在进行小的更改之后。如果这些错误没有在预生产环境中显现出来,那么在部署到生产环境时,可能会面临尴尬的局面。而且,人们并不总是会在预生产环境中完整地测试整个应用。在见过的应用中,能够在生产环境部署前完整执行测试计划的次数,可以说是屈指可数。唯一可以依赖的是单元测试,但正如其名,它们是用于测试(小的)单元,而不是整个应用(即端到端测试)。
当然,可以使用一些测试框架来运行UI测试,例如Selenium。在一些项目中使用过Selenium,但通常因为测试速度慢、测试难以维护等原因而很快放弃。
最近,参加了好朋友Michel (@michelgrootjans)的“Ruby和Rails新手入门”课程,了解到一些Ruby测试gem,它们实际上为.NET应用提供了一些机会。
在这篇博客文章中,想给一个概述,如何设置这些Ruby测试gem,以便它们可以为ASP.NET MVC应用(或任何.NET Web应用)运行UI测试。将在这里描述的技术(和gem)包括:
首先,让设置环境。为此,需要Ruby,可以在这里找到。安装完成后,可以通过在命令行运行以下命令来测试是否一切顺利:
irb
这应该会打开一个Ruby REPL循环,可以在这里测试语句(例如1+1,应该会给2的答案)。
一旦设置完成,退出REPL循环并开始安装所有必要的gem:
gem install rspec
gem install capybara
gem install selenium-webdriver
gem install poltergeist
还需要安装PhantomJS,可以在这里找到,以及Firefox(默认的selenium web driver使用的是Firefox,将在博客文章后面给其他选项)。这就是需要开始的全部。
现在可以开始编写测试了。测试将被放置在spec文件夹中的单独的_spec.rb文件中。例如,如果想为客户编写规范测试,将有一个customers_spec.rb文件,对于产品,将有一个products_spec.rb文件。当然,可以自由地使用任何命名和分组规范测试,只要在spec文件夹中至少有一个_spec文件。
一个spec看起来像这样:
describe '添加新客户' do
it '应该能够创建一个新客户' do
end
end
如所见,从describe开始,它告诉想要测试的行为。it部分包含预期的结果(稍后会添加)。现在不用担心Ruby语法。对于使用BDD风格测试框架的人来说,describe和it语法应该看起来很熟悉。
将要测试的,将是网站的行为。为此将使用capybara和selenium gem。由于希望这个第一个spec以及所有后续的specs使用相同的测试设置(例如要测试的网站的URL),将使用spec_helper.rb文件。在这个文件中,将需要所有必要的gem并进行所有设置。然后每个单独的spec文件将需要这个spec_helper文件:
require 'capybara/rspec'
require 'selenium/webdriver'
Capybara.run_server = false
Capybara.default_driver = :selenium
Capybara.app_host = 'http://localhost/TheApplication'
在require语句之后,配置capybara。首先,告诉它不要运行它的服务器。由于capybara本质上是一个rails测试框架,它默认在rack应用程序下运行。不会有这个,因为应用将在IIS(Express)或类似的东西下运行。接下来告诉它使用哪个驱动程序,最后告诉应用在哪里(如果想测试www.google.com,也可以这样做)。
现在已经设置好了,可以开始编写第一个测试。Capybara实际上允许在Web应用程序中点击按钮和填写字段,这就是将要做的事情:
require 'spec_helper'
describe '添加新客户', :type => :feature do
it '应该能够创建一个新客户' do
visit '/Customer'
click_link 'Add'
fill_in('first_name', :with => 'Gitte')
fill_in('last_name', :with => 'Vermeiren')
fill_in('email', :with => 'mie@hier.be')
click_button 'Create'
page.should have_text 'New customer created'
end
end
如所见,capybara有点击链接、填写字段、选择选项的方法...最后是测试应用中是否得到了预期的结果。可以在这里找到capybara文档和额外的功能。
还添加了:type => :feature哈希到describe中,这样测试就会被识别为rspec测试。
一旦有了这个spec文件,就可以运行测试了。为此,打开一个命令提示符,cd到spec目录上方的目录,然后运行rspec命令:
rspec
会注意到这个命令启动需要一点时间,但一旦运行,它将启动一个Firefox窗口,并在命令提示符中显示一个错误,因为假设还没有实现任何东西来让上面的测试成功。把这个任务留给,读者,编写一个小的Web应用程序来让这个测试通过。一旦有了这个,并且运行了rspec命令,将看到浏览器中的不同字段被在测试中指定的值填充。
现在,向保证,使用RSpec、Capybara、Ruby等的回报是值得的。首先,可以告诉,上面的capybara测试比.NET中类似的测试要干净得多。但除此之外,还可以做得更多。
可以从让测试在无头模式下运行开始,这意味着不再需要浏览器窗口了。为此将使用poltergeist和phantomjs。需要为此修改spec_helper文件:
require 'capybara/rspec'
require 'selenium/webdriver'
require 'capybara/poltergeist'
Capybara.run_server = false
Capybara.default_driver = :selenium
Capybara.javascript_driver = :poltergeist
Capybara.app_host = 'http://localhost/TheApplication'
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app,
:phantomjs => 'C:\\some_path\\phantomjs.exe')
end
这增加了对poltergeist的额外要求,并添加了javascript_driver配置设置。此外,告诉capybara在哪里可以找到phantomjs进程。
还需要在describe语句中添加:js => true哈希,以便它在phantomjs中运行:
describe '添加新客户', :type => :feature, :js => true do
如果现在用rspec运行测试,会注意到Firefox不会运行,只会在命令提示符中得到一个测试成功或失败的总结。
用自己的Web应用程序做了一些测试,发现无头测试的运行速度是使用浏览器的测试的两倍。
实际上,已经对这第一个测试设置相当满意了。它仍然不是最快的测试,但它确实允许进行一些简单的端到端测试,或者甚至开始做一些BDD风格的测试。也可以使用cucumber而不是rspec。
在设置中,扩展了上面的例子,增加了一些额外的配置设置,以便能够轻松地将测试环境从本地切换到预生产环境,从无头测试切换到浏览器测试。