Как сделать так, чтобы эти тесты прошли надежно?
В настоящее время эти тесты ненадежны.
Иногда они проходят. Иногда они терпят неудачу.
Ниже приведены настройки, код и выходные данные, демонстрирующие эту проблему.
Мы будем очень благодарны за предложения по устранению этой проблемы, и я уверен, что они помогут многим другим, поэтому, пожалуйста, прокомментируйте!
Среда тестового кода
- Рельсы 3.2
- RSpec 2.x
- Водосвинка
- Полтергейст
- PhantomJS
- AngularJS
- Google Chrome версии 47.0.2526.106 (64-разрядная)
Тестирование драгоценных камней из Gemfile.lock
capybara (2.1.0)
database_cleaner (0.7.1)
debug_inspector (0.0.2)
guard-bundler (0.1.3)
guard-livereload (1.2.0)
guard-rspec (2.1.2)
jasminerice (0.0.10)
pg (0.17.1)
phantomjs (2.1.1.0)
poltergeist (1.4.1)
protractor-rails (0.0.17)
pry (0.9.12)
rack (1.4.7)
rack-test (0.6.3)
rails (3.2.21)
rails-assets-angular (1.3.20)
rspec-rails (2.11.4)
simplecov (0.8.2)
sprockets (2.2.3)
zeus (0.13.3)
zeus-parallel_tests (0.2.1)
Вещи, которые я пробовал
- Убедитесь, что я использую ожидающие сопоставления DSL Capybara
- Убедитесь, что мой очиститель базы данных настроен правильно
- Протестируйте каждый элемент страницы, предполагая, что его может не быть на странице, но он все еще загружается.
- Сузить несогласованные тесты
- Выполнить непоследовательный тест в одиночку
Определите код Capybara DSL, который приводит к противоречивым результатам тестирования.
- i.e. creating a new record and assuming the page has redirected and that the record is on the page click_on
or
- .click не всегда "работает"
- Обновите Capybara до последней версии (в отдельной ветке)
- Обновлен Poltergeist и RSpec до последней версии (в отдельной ветке, все еще работаю над этим)
Ресурсы, которые я использовал
[1] Capybara The DSL
[2] Советы по Capybara, PhantomJs, Poltergeist и Rspec
И многие более...
Как проводились тесты
rspec spec/integration/costings/show_costing_spec.rb --format documentation
Тестовый код
show_costing_spec.rbrequire "spec_helper"
RSpec.describe "Show a new costing in the listing," do
before :each do
admin_sign_in
create_costing("test1")
end
it "shows the costing after creation" do
within "#costings_table" do
expect(page).to have_css("#name", text: "test1")
end
end
it "shows the details of the new costing after creation" do
expect(page).to have_content("Costings")
within "#costings_table" do
expect(page).to have_content("test1")
all("#show").last.click
end
expect(page).to have_content("Costing Details")
expect(page).to have_css("#name", text: "test1")
end
end
spec_helper.rb
# This file is copied to spec/ when you run 'rails generate r spec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
# Add library functions here so we can test them.
require File.expand_path(File.dirname(__FILE__) + "/../lib/general")
require 'rspec/rails'
require 'rspec/autorun'
# Integration Testing
require 'capybara/poltergeist'
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
end
Capybara.javascript_driver = :poltergeist_debug
Capybara.default_driver = :poltergeist_debug
# Capybara Integration Test Helpers
def admin_sign_in
visit "/login"
#Create staff member in database
Staff.make!(:admin)
#Log In
fill_in "staff_username", with: "adminstaff"
fill_in "staff_password", with: "password"
click_button "login"
end
def create_costing(item)
visit "/api#/costings"
click_on "new_btn"
within "#form_costing" do
find("#name", match: :first).set("#{item}")
find("#description", match: :first).set("test description")
find("#from_date", match: :first).set("15/02/2016")
find("#cost_hourly_cents", match: :first).set("1.00")
click_on "create_btn"
end
end
RSpec.configure do |config|
config.before(:suite) do
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
require File.expand_path(File.dirname(__FILE__) + "/support/blueprints")
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# Allow a 'focus' tag so that we can run just a few tests which we are currently working on
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run focus: true
config.run_all_when_everything_filtered = true
config.filter_run_excluding :slow unless ENV["SLOW_SPECS"]
# Defer Garbage Collection
config.before(:all) { DeferredGarbageCollection.start }
config.after(:all) { DeferredGarbageCollection.reconsider }
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
# config.infer_spec_type_from_file_location!
# Configure Database Cleaner
config.include Capybara::DSL
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
Результаты теста
Test Run 1: Failing
Параметры запуска: include {: focus => true} exclude {: slow => true}
Все примеры были отфильтрованы; игнорируя {: focus => true}
Показать новую калькуляцию в листинге, показывает калькуляцию после создания, показывает детали новой калькуляции после создания (ОТКАЗ - 1)
Неудачи:
1) Показать новую калькуляцию в листинге,
показывает детали новой калькуляции после создания
Сбой / ошибка: expect (page) .to have_content ("test1")
ожидаемый #has_content? (" test1 "), чтобы вернуть истину, получено false
# ./spec/integration/costings/show_costing_spec.rb:20:в блоке (3 уровня) в
# ./spec/integration/costings/show_costing_spec.rb: 19: в блоке (2 уровня) вЗавершено за 5,46 секунды 2 примера, 1 сбой
Test Run 2: Passing
Параметры запуска: include {: focus => true} exclude {: slow => true}
Все примеры были отфильтрованы; игнорируя {: focus => true}
Показать новую калькуляцию в листинге,
показывает калькуляцию после создания,
показывает детали новой калькуляции после создания.Завершено за 3,57 секунды 2 примера, 0 сбоев
Обновление 1
Обновлены гемы тестирования до следующих версий:
capybara (2.6.2) из (2.1.0)
database_cleaner (1.5.1) из (0.7.1) strong>
debug_inspector (0.0.2)
guard-bundler (0.1.3)
guard-livereload (1.2.0)
guard-spec (2.1.2)
jasminerice (0.0 .10)
pg (0.17.1)
phantomjs (2.1.1.0)
полтергейст (1.9.0) из (1.4.1)
транспортир-рельсы ( 0.0.17)
pry (0.10.3) из (0.9.12)
стойка (1.4.7)
испытательная стойка (0.6.3)
рельсы (3.2.21)
rails-assets-angular (1.4.9) из (1.3.20)
rspec-rails (3.4.2) из (2.11.4) )
simplecov (0.8.2)
звездочки (2.2.3)
zeus (0.13.3)
zeus-parallel_tests (0.2.1)
Result 1
К сожалению, обновление этих драгоценных камней, похоже, не имело никакого значения, и мои тесты все еще были нестабильными.
Обновление 2
Я реализовал предложения Тома Уолпола. Гарантированно, что мой admin_sign_in ждет завершения sign_in.
Также обновил мою настройку database_cleaner, как предложил Том.
Result 2
На мой стек эти изменения, похоже, не повлияли.
Примечание. Если кто-то не использует AngularJS, я считаю, что эти изменения могли бы изменить ситуацию. Так что спасибо Том за ваши предложения.
Обновление 3
Мне нужно было получить больше информации о том, что происходило во время моих тестовых прогонов. В сети есть предложения для регистрации, использования драгоценных камней для сохранения снимков экрана и тому подобного, но я не чувствовал, что это будет наиболее эффективным по времени. Я хотел указать, где я хотел бы приостановить тест и просмотреть содержимое переменных и полей формы. В браузере было бы идеально.
Что я использовал
Я использовал save_and_open_page и print page.html для отладки.
К чему я перешел
Когда я работал с RSpec 3.4.2, я добавил вспомогательный метод отладки:
rails_helper.rb
def debugit
puts current_url
require 'pry'
binding.pry
end
Result 3
URL-адрес будет напечатан в консоли, и тест будет приостановлен. На этом этапе я мог бы перейти по URL-адресу, войти в систему, перейти на тестовую страницу и посмотреть, что сделал тест Capybara.
Это позволило мне определить, что источник моих проблем возник, когда тест использовал capybara's fill_in DSL. В некоторых тестовых запусках поля будут заполнены правильно, и форма будет отправлена. В другом случае форма будет заполнена правильно, но кнопка отправки будет нажата слишком быстро. В результате создается запись, но поля ввода имени и описания не сохраняются.
Обновление 4
Я обнаружил, что, поскольку я использовал формы и таблицы ввода AngularJS, AngularJS требовалось немного времени для привязки к полям ввода. Если бы это было не разрешено на этот раз, входные данные не были бы сохранены.
Capybara предоставляет такие методы ожидания, как «внутри» и «найти». Я использовал их, но они не помогли с проблемой времени привязки AngularJS. Я обнаружил, что ng-if можно использовать для создания оператора if для ожидания определенного элемента, который будет означать, что привязка AngularJS к полям формы завершена.
Поэтому я использовал методы ожидания Capybara, чтобы дождаться полей, которые я хотел заполнить, и использовал AngularJS ng-if, чтобы не показывать поля, пока они не будут готовы.
Реализация
index.html.erb
<div ng-if="tableParams.data">
<table id="costings_table ng-table="tableParams" class="table">
<td id="field1">{{table.field1}}</td>
<td id="field2">{{table.field2}}</td>
</table>
</div>
Result 4
Наконец-то испытания прошли! Однако у меня есть все эти методы поиска с xpath, гарантирующие, что конкретные и трудные для таргетинга элементы ожидаются ...
Обновление 5
Несмотря на то, что в моем gemfile я запускал gem phantomJS версии 2.1.1, моя версия командной строки была только 1.X. Это оказалось важным.
Я обновил свою версию командной строки phantomJS до 2.1.1. В то же время я убедился, что все мои поля ввода, кнопки, таблицы и заголовки имеют уникальные идентификаторы. Затем я смог удалить все вхождения find (: xpath), не нарушая тестов.
Result 5
Этот набор тестов теперь надежно проходит все время! Именно то, что я хотел! Да!