原文标题:Autotesting JavaScript with Jasmine and Guard
原文地址:http://edspencer.net/2013/06/15/autotesting-javascript-with-jasmine-and-guard/
我喜欢Rails的一个原因是:他介绍了自动测试的理念给我,即一个监听你文件系统改变的文本,然后在文件发生改变时,自动运行你的单元测试。
因为单元测试通常情况下运行得很快,你可能在你一两次保存文件后就得到了你的测试结果。允许你继续在编辑器中继续编辑代码,只有你在需要详细调试的情况下时,才将转向到浏览器中进行调试――因为有了命令行输出和操作系统的提醒,你可以大部分时间内集中你的主要注意力在问题解决上。
这是一个令人向往的工作方式,并且由于我工作上重新用到了JavsScript。因为我使用过很多ruby的程序,而且我非常熟练轻松地实现了这种方式,证明了这是一个很容易就实现的方式,而且,这是非常明智的,我尝试了这种方式。
Guard 的是“守卫”的意思,这里指是一个 ruby 小插件,他能够扫描你的文件系统中所改变的东西,然后在你所关心文件改变时运行你指定的代码。他为自动测试提供了简单而又有效的,基于文件系统的触发器。首先,让我们确认一下,我们安装了所有必需的ruby gem小插件。
gem install jasmine jasmine-headless-webkit guard-jasmine-headless-webkit guard \
guard-livereload terminal-notifier-guard --no-rdoc --no-ri
这仅仅只是安装了一小部分的ruby插件,用于我们的测试。首先我们先通过安装ruby插件安装优秀的JavaScript行为驱动开发(BDD)测试框架:Jasmine,当然你能够使用你自己所喜爱框架,但是,我认为Jasmine用起来很顺手并且完全可以胜任我们的要求。然后,我们添加jasmine-headless-webkit插件,以及他的 "guard 双胞胎"(通过使用phantomjs在命令行上执行你的测试代码,而不需要在浏览器中执行)。
接下来,我们安装了“guard-livereload”,它能够使得Guard能够作为一个 livereload 的服务器,在你修改文件后自动地在浏览器运行所有测试用例。这初步看起来很强大。同时这有一点疑惑,既然我们已经可以在精简webkit环境运行我们的测试,那为什么还要给自己找麻烦去支持在浏览器中运行呢?恩,因为在我们测试用例发现错误时,我们可以从浏览器中得到更多的信息,例如堆栈跟踪,而这些信息对于实时调试是非常有帮助的。
最后我们安装了“terminal-notifier-guard ”插件,它能够在每次运行完测试用例后给我们一个通知。现在我们已经安装了所有必须的插件了,现在我们开始搭建软件环境了,非常感谢jasmine和guard提供了很简单明了的操作说明。
jasmine init
guard init
接下来,我们要开始运行了,让我们通过运行“guard”命令测试是否搭建成功。
guard
你应该看到的是这样的(原文的图片看不到,这是我自己的截图,注意我这里只装成功gaurd和livereload,所以与原文的图可能有区别):
我们看到guard已经启动完毕,告诉我们在每次测试用例完成运行时,将会通过使用终端监听的方式给操作系统一个响应,同时,将会使用JasmineHeadlessWebkit运行这些测试用例,而不是通过浏览器。你将看到在5ms内运行了5个测试用例,并且你应该看到有一个闪屏的操作系统提示告诉你完成了测试。当你不想一直保持一个终端窗口可见时,例如使用笔记本工作时,这是非常棒的!
这5个测试的内容是什么?它们仅仅是我们通过“jasmine init”创建的示例,你能够在 spec/javascripts 目录找到它们,通常情况下,只有一个文件 PlayerSpec.js
现在,我们尝试去修改这个文件,并且修改后马上保存。结果什么也没发生。原因是通过“guard init” 生成的 Guardfile 文件中的监听文件条件与 jasmine 的文件结构不相符造成的。我们得稍微麻烦一点,手动修改这个 Guardfile 这个文件。
如果你现在打开 Guardfile 文件,你将看到有30行左右的配置选项(不知怎的,笔者这只有11行)。文件中大部分是注释和可选项,这些你都可以随意删除掉的。Guard 期望你的测试文件遵循如下格式“my_spec.js”,注意js文件需要以 "_spec" 结尾。
一个简便的办法是直接修改 spec_location 变量,将后面的 _spec 移除掉就行。然后对 `guard ‘jasmine-headless-webkit’ do` 这一块做同样的操作。最终处理后的结果应该是这样的:
spec_location = "spec/javascripts/%s"
guard 'jasmine-headless-webkit' do
watch(%r{^app/views/.*\.jst$})
watch(%r{^public/javascripts/(.*)\.js$}) { |m| newest_js_file(spec_location % m[1]) }
watch(%r{^app/assets/javascripts/(.*)\.(js|coffee)$}) { |m| newest_js_file(spec_location % m[1]) }
watch(%r{^spec/javascripts/(.*)\..*}) { |m| newest_js_file(spec_location % m[1]) }
end
一旦你修改完毕 Guard,不需要重启 guard,它能够监听到Guardfile的改变,并且自动重启。现在一旦你保存 PlayerSpec.js 文件,你能够看到你的终端立刻运行了你的测试用例,并且给了你测试结束的提示,当然假定你的测试仍然是通过的。
你是不是对 `guard ‘jasmine-headless-webkit’ do` 这块的内容有些疑惑呢?可能你已经猜到了,这就是设置guard将监听的文件。无论什么时候,满足当前匹配的文件一旦发生更改,guard 将会自动运行jasmine-headless-webkit命令,就是运行你的测试用例。这些是默认的选项,所以如果你的js文件没有在这些匹配选项中找到时,你所要做的就是仅仅将它放到正确的目录下即可。
这篇文章的最后一个部分是关于我使用Livereload插件。Livereload由两部分组成:1个浏览器插件(支持Chrome, Firefox 和 其他浏览器),另外一个是我们已经启动过的Guard。首先你要做的是安装浏览器插件([http://livereload.com/]),这是相当简单的。
因为livereload的服务器已经在Guard运行起来了,现在我们要做的是仅仅设置我们的浏览器去加载这些测试用例(在 chrome 网上应用商店,中搜索 livereload,找到“扩展程序”中 LiveReload 安装,注意不是“应用”的那个
)。不幸的是,我找到的唯一一个办法是,重新打开另外一个终端,并且在同一个目录下运行:
rake jasmine
这个操作将会启动一个轻量级的Web服务器,访问地址为:[http://localhost:8888。] 如果现在你在浏览器访问这个网址,将会看到如下内容:
点击一下浏览器中的livereload按钮(前提是你在浏览器中安装了这个插件),再次编辑你的文件,然后你将发现浏览器自动刷新了,并且运行了你的测试用例。这个操作是可选的,但是有一点我觉得是相当有用的,就是在存在某些测试不通过时,我能够立马切换到浏览器中通过追踪堆栈信息和调试工具来查找问题。
到此为止,我们介绍完了循环自动测试和怎么搭建运行环境。下一次当你返回现在代码,仅仅只需要执行 "guard" 和 "rake jasmine" ,然后,你立马就拥有了自动测试环境。最后,如果你发现一种可以不通过打开第二个终端窗口就启动guard服务器的方法,请在下面留言,谢谢!
由于公司的电脑是XP系统的,尝试了多种方法都没有装上这个插件。暂时放下了,等有空到自己的电脑上的centos系统在尝试一下。
failed to build native extension
* 安装 DevKit
* 找不到 gmake
gem install libv8
执行这条命令还是不行的
找不到不包含内核的测试插件
gem install bundler-1.3.5.gem -l gem install bundle-0.0.1.gem -l 17:18:49 - ERROR - Could not load 'guard/jasmine-headless-webkit' or find class Guard::Jasmineheadlesswebkit cd /d e:/software/gem 下载 jasmine-headless-webkit.gem 然后安装: gem install jasmine-headless-webkit-0.8.4.gem -l 安装失败,好像用到了 QT 中的 qmake 工具 Building native extensions. This could take a while... ERROR: Error installing jasmine-headless-webkit: ERROR: Failed to build gem native extension. D:/Ruby187/bin/ruby.exe extconf.rb make: *** No rule to make target `clean'. Stop. D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib/qt/qmake.rb: 97:in ``': No such file or directory - which gmake (Errno::ENOENT) from D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib /qt/qmake.rb:97:in `get_exe_path' from D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib /qt/qmake.rb:53:in `make_path' from D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib /qt/qmake.rb:16:in `make_installed?' from D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib /qt/qmake.rb:103:in `check_make!' from D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8.4/lib /qt/qmake.rb:37:in `make!' from extconf.rb:8 Gem files will remain installed in D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-hea dless-webkit-0.8.4 for inspection. Results logged to D:/Ruby187/lib/ruby/gems/1.8/gems/jasmine-headless-webkit-0.8. 4/ext/jasmine-webkit-specrunner/gem_make.out
从如下网址上下载需要安装的 gem 软件
[http://rubygems.org/]
gem install jasmine-1.3.2.gem -l
官方推荐的是用这种方式安装:
gem install jasmine
asmine requires rspec (>= 1.3.1, runtime)
重新安装 rspec
gem install rspec
jasmine requires selenium-webdriver (>= 0.1.3, runtime)
重新安装 rspec
gem install selenium-webdriver
重新装完这个后,终于可以装 jasmine 了,我可是等了好久啊...
jasmine init 失败
C:\>jasmine init
D:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:in `gem_original
_require': no such file to load -- json (LoadError)
好像是确实json的库,看到Jasmine的requirement列表中,运行时是不需要的,但是开发版是需要的。所以从开发版中下在了gem,发现缺少了rake,就将rake也装上了。
gem install rake-10.1.0.gem
gem install json_pure-1.8.0.gem
编辑 GuardFile,将:
watch(%r{public\.+\.(css|js|html)})
改成
watch(%r{.+\.(css|js|html)})
需要先启动服务器,再启动浏览器中连接,修改被监听的文件,保存后,浏览器中会自动刷新
gem install guard guard-livereload --no-rdoc --no-ri
可能是因为装的 2.0 版本的缘故
安装 1.8.7 就没问题了
gem install guard guard-livereload --no-rdoc --no-ri
可能是因为装的 2.0 版本的缘故
安装 1.8.7 就没问题了
但是启动 Guard 后,浏览器连接到服务器上还是出现问题了。
我只实现了监听文件,使用livereload插件连接guard,这样,在apache下调试简单的js文件还是比较方便的。但因为我的项目是在 MyEclipse 部署服务器,同时在 emacs 中编辑 js 文件,每次更新完毕 js 文件确实会使浏览器重新刷新,但是由于 MyEclipse 没有部署最新的 js 文件,在浏览器上的效果还是比价旧的,所以感觉对我没太大的帮助。当然,如果你是在 MyEclipse 中编辑 js 文件还是比较方便的,至少帮你省去了重新刷新浏览器的操作。
总有些好的工具我们还不了解。要是早些知道的话,能大大提高开发效率,加快项目地开发。所以,有经验的程序员是很值得尊敬的,也不用担心老程序员被新程序员替代,这些经验是很宝贵的财富。同时,这是我第一篇翻译的开发资料,学到了很多,只是花费的时间有些多,但这些花费时间是很值得的。
我没有在 XP 中搭建成这篇文章中最终要的自动测试和终端提醒功能,如果大家知道有安装成功的办法,请在留言中告诉我,谢谢。