Rails + Capybara-webkit - покрытие кода javascript?
Я изучаю использование capybara-webkit для тестирования приложений, близких к реальности. Это абсолютно необходимо, так как приложение имеет очень богатый пользовательский интерфейс на основе JS, а часть Rails состоит в основном из вызовов API.
Вопрос в том, существуют ли какие-либо инструменты для интеграции в конвейер тестирования, которые могли бы обрабатывать код Javascript и сообщать о его охвате? Ключевым моментом здесь является возможность легко интегрироваться в рабочий процесс тестирования (так же, как rcov/simplecov) - мне не нравится идея сделать это самостоятельно с помощью jscoverage или аналога:)
Спасибо заранее.
2 ответа
Обновление: Начиная с версии 1.05 JSCover, хаки, которые я описал в моем предыдущем ответе, больше не нужны. Я обновил свой ответ, чтобы отразить это.
Мне удалось заставить JSCover работать в трубопроводе Rails + Capybara, но для того, чтобы он заработал, потребовалось немало взлома. Я построил небольшое задание на грабли, которое:
- использует конвейер ресурсов rails для генерации скриптов
- вызывает java jar, чтобы обработать все файлы и создать пустой отчет во временном каталоге
- исправляет скрипт jscover.js для работы в "режиме отчета" (просто добавьте в конце jscoverage_isReport=true)
- копирует результат в /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 с двумя корректировками:
- Запустите тестирование через прокси-сервер JSCover.
- Сохраните отчет о покрытии в конце набора тестов.
См. Документацию JSCover для получения дополнительной информации. Версия 1.0.5, содержащая эти изменения, должна быть выпущена через несколько дней.