Rails + Capybara-webkit - покрытие кода javascript?

Я изучаю использование capybara-webkit для тестирования приложений, близких к реальности. Это абсолютно необходимо, так как приложение имеет очень богатый пользовательский интерфейс на основе JS, а часть Rails состоит в основном из вызовов API.

Вопрос в том, существуют ли какие-либо инструменты для интеграции в конвейер тестирования, которые могли бы обрабатывать код Javascript и сообщать о его охвате? Ключевым моментом здесь является возможность легко интегрироваться в рабочий процесс тестирования (так же, как rcov/simplecov) - мне не нравится идея сделать это самостоятельно с помощью jscoverage или аналога:)

Спасибо заранее.

2 ответа

Обновление: Начиная с версии 1.05 JSCover, хаки, которые я описал в моем предыдущем ответе, больше не нужны. Я обновил свой ответ, чтобы отразить это.

Мне удалось заставить JSCover работать в трубопроводе Rails + Capybara, но для того, чтобы он заработал, потребовалось немало взлома. Я построил небольшое задание на грабли, которое:

  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

Теперь это было добавлено к JSCover (в транке) - связанный поток в JSCover здесь.

Мне удалось заставить JSCover работать в трубопроводе Rails + Capybara, но для его работы потребовалось немало взлома

Эти изменения теперь находятся в стволе JSCover и будут частью версии 1.0.5. Там есть рабочие примеры (включая записанный пример Selenium IDE) и документация.

Для работы обнаружения веток требуется дополнительная работа, поскольку в ней используются объекты, которые нельзя легко сериализовать в JSON.

Это функция для этого, которая используется в новом коде.

Во всяком случае, конечный результат работает хорошо

Согласен. Это делает JSCover пригодным для использования инструментами более высокого уровня, которые плохо работают с iFrames или несколькими окнами, которых избегает этот подход. Это также означает, что покрытие кода может быть добавлено к существующим тестам Selenium с двумя корректировками:

  1. Запустите тестирование через прокси-сервер JSCover.
  2. Сохраните отчет о покрытии в конце набора тестов.

См. Документацию JSCover для получения дополнительной информации. Версия 1.0.5, содержащая эти изменения, должна быть выпущена через несколько дней.

Другие вопросы по тегам