4

我正在研究使用 capybara-webkit 对应用程序进行一些接近现实的测试。这是绝对必要的,因为该应用程序具有非常丰富的基于 JS 的 UI,并且 Rails 部分主要是 API 调用。

问题是:是否有任何工具可以集成到可以检测 Javascript 代码并报告其覆盖率的测试管道中?这里的关键是能够轻松集成到测试工作流中(就像 rcov/simplecov)——我不喜欢自己用 jscoverage 或类似物来做这个想法:)

提前谢谢了。

4

2 回答 2

1

更新:从 JSCover 版本 1.05 开始,不再需要我在之前的答案中概述的技巧。我已经更新了我的答案以反映这一点。

我设法让JSCover在 Rails + Capybara 管道中工作,但确实需要一些黑客才能让它工作。我建立了一个小 rake 任务:

  1. 使用 rails 资产管道生成脚本
  2. 调用 java jar 来检测所有文件并在临时目录中生成一个空报告
  3. 修补 jscover.js 脚本以在“报告模式”下运行(只需在末尾添加 jscoverage_isReport=true)
  4. 将结果复制到 /public/assets 以便测试在不需要任何更改的情况下获取它,因此可以在浏览器中自动打开覆盖率报告

然后我添加了一个设置任务以在测试开始时清除浏览器的 localStorage,并添加一个拆卸任务,在最后写出完成的报告。

def setup
  unless $startup_once
    $startup_once=true
    puts 'Clearing localStorage'
    visit('/')
    page.execute_script('localStorage.removeItem("jscover");')
  end
end
def teardown
  out=page.evaluate_script("typeof(_$jscoverage)!='undefined' && jscoverage_serializeCoverageToJSON()")
  unless out.blank? then
    File.open(File.join(Rails.root,"public/assets/jscoverage.json"), 'w') {|f| f.write(out) }
  end
end

无论如何,最终结果很好,这样做的好处是它也适用于无头浏览器,因此它也可以包含在 CI 中。

*** 更新 2:这是一个自动执行步骤的 rake 任务,将其放入 /lib/tasks

# Coverage testing for JavaScript
#
# Usage:
# Download JSCover from: http://tntim96.github.io/JSCover/ and move it to
#   ~/Applications/JSCover-1
# First instumentalize the javascript files:
#   rake assets:coverage
# Then run browser tests 
#   rake test
# See the results in the browser
#   http://localhost:3000/assets/jscoverage.html
# Don't forget to clean up instrumentalization afterwards:
#   rake assets:clobber
# Also don't forget to re-do instrumentalization after changing a JS file


namespace :assets do
  desc 'Instrument all the assets named in config.assets.precompile'
  task :coverage do
    Rake::Task["assets:coverage:primary"].execute
  end

  namespace :coverage do
    def jscoverage_loc;Dir.home+'/Applications/JSCover-1/';end
    def internal_instrumentalize

      config = Rails.application.config
      target=File.join(Rails.public_path,config.assets.prefix)

      environment = Sprockets::Environment.new
      environment.append_path 'app/assets/javascripts'
      `rm -rf #{tmp=File.join(Rails.root,'tmp','jscover')}`
      `mkdir #{tmp}`
      `rm -rf #{target}`
      `mkdir #{target}`

      print 'Generating assets'
      require File.join(Rails.root,'config','initializers','assets.rb')
      (%w{application.js}+config.assets.precompile.select{|f| f.is_a?(String) && f =~ /\.js$/}).each do |f|
        print '.';File.open(File.join(target,f), 'w') {|ff| ff.write(environment[f].to_s) }
      end
      puts "\nInstrumentalizing…"
      `java -Dfile.encoding=UTF-8 -jar #{jscoverage_loc}target/dist/JSCover-all.jar -fs #{target} #{tmp} #{'--no-branch' unless ENV['C1']} --local-storage`
      puts 'Copying into place…'
      `cp -R #{tmp}/ #{target}`
      `rm -rf #{tmp}`
      File.open("#{target}/jscoverage.js",'a'){|f| f.puts 'jscoverage_isReport = true' }

    end

    task :primary => %w(assets:environment) do
      unless Dir.exist?(jscoverage_loc)
        abort "Cannot find JSCover! Download from: http://tntim96.github.io/JSCover/ and put in #{jscoverage_loc}"
      end
      internal_instrumentalize
    end

  end

end
于 2013-08-24T16:15:10.247 回答
1

现在已将其添加到 JSCover(在主干中) - JSCover 的相关线程在这里

我设法让 JSCover 在 Rails + Capybara 管道中工作,但它确实需要相当多的黑客才能让它工作

这些更改现在位于 JSCover 的主干中,并将成为版本 1.0.5 的一部分。那里也有工作示例(包括 Selenium IDE 记录的示例)和文档。

需要做一些额外的工作才能使分支检测正常工作,因为它使用无法轻松序列化为 JSON 的对象

这是一个在新代码中使用的函数。

无论如何,最终结果效果很好

我同意。这使得 JSCover 可以被高级工具使用,这些工​​具不能很好地与 iFrame 或通过这种方法避免的多个窗口一起工作。这也意味着可以通过两项调整将代码覆盖率添加到现有的 Selenium 测试中:

  1. 使测试通过 JSCover 代理运行
  2. 将覆盖率报告保存在测试套件的末尾

有关更多信息,请参阅 JSOver 的文档。包含这些更改的 1.0.5 版应在几天内发布。

于 2013-09-15T07:25:59.727 回答