Я заметил странную проблему, которую я не мог решить в течение нескольких дней.
У меня есть сервер Rails 5 API с системными тестами, использующими RSpec и Capybara + Selenium-webdriver, которые ведут без головыХром.
Я использую Capybara.app_host = 'http://localhost:4200'
, чтобы тесты подключались к отдельному серверу разработки, на котором запущен интерфейс Ember.Интерфейс Ember просматривает пользовательский агент, чтобы узнать, а затем отправлять запросы в тестовую базу данных Rails API.
Все тесты работают нормально, за исключением тех, которые используют фиксации файла RSpec .
Вот одна из спецификаций, которая терпит неудачу:
describe 'the affiliate program', :vcr, type: :system do
fixtures :all
before do
Capybara.session_name = :affiliate
visit('/')
signup_and_verify_email(signup_intent: :seller)
visit_affiliate_settings
end
it 'can use the affiliate page' do
affiliate_token = page.text[/Your affiliate token is \b(.+?)\b/i, 1]
expect(affiliate_token).to be_present
# When a referral signs up.
Capybara.session_name = :referral
visit("?client=#{affiliate_token}")
signup_and_verify_email(signup_intent: :member)
refresh
# It can track the referral.
Capybara.session_name = :affiliate
refresh
expect(page).to have_selector('.referral-row', count: 1)
# When a referral makes a purchase.
Capybara.session_name = :referral
find('[href="/videos"]').click
find('.price-area .coin-usd-amount', match: :first).click
find('.cart-dropdown-body .checkout-button').click
find('.checkout-button').click
wait_for { find('.countdown-timer') }
order = Order.last
order.force_complete_payment!
Rake::Task['affiliate_referral:update_amounts_earned'].invoke
# It can track the earnings.
Capybara.session_name = :affiliate
refresh
amount = (order.price * AffiliateReferral::COMMISSION_PERCENTAGE).floor.to_f
amount_in_dom = find('.referral-amount-earned', match: :first).text.gsub(/[^\d\.]/, '').to_f * 100
expect(amount).to equal(amount_in_dom)
end
end
Это не удастся, возможно, в 99% случаев.Есть странный случай, когда это проходит.Я могу заставить свой набор тестов в конечном итоге пройти, запустив его в цикле в течение дня.
Я закончил тем, что обновил все версии до последней (Узел 10, последний Ember, последний Rails), но проблема сохраняется.
Я могу опубликовать пример репо, который воспроизведет проблему позже.Я просто хотел опубликовать это в случае, если кто-нибудь столкнулся с проблемой.
Вот типичная трассировка стека, когда тайм-аут случается:
1.1) Failure/Error: page.evaluate_script('window.location.reload()')
Net::ReadTimeout:
Net::ReadTimeout
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/webmock-3.3.0/lib/webmock/http_lib_adapters/net_http.rb:97:in `block in request'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/webmock-3.3.0/lib/webmock/http_lib_adapters/net_http.rb:110:in `block in request'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/webmock-3.3.0/lib/webmock/http_lib_adapters/net_http.rb:109:in `request'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/http/default.rb:121:in `response_for'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/http/default.rb:76:in `request'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/http/common.rb:62:in `call'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/bridge.rb:164:in `execute'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/oss/bridge.rb:584:in `execute'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/remote/oss/bridge.rb:267:in `execute_script'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.14.0/lib/selenium/webdriver/common/driver.rb:211:in `execute_script'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/capybara-3.8.2/lib/capybara/selenium/driver.rb:84:in `execute_script'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/capybara-3.8.2/lib/capybara/selenium/driver.rb:88:in `evaluate_script'
# /home/mhluska/.rvm/gems/ruby-2.5.1/gems/capybara-3.8.2/lib/capybara/session.rb:575:in `evaluate_script'
# ./spec/support/selenium.rb:48:in `refresh'
# ./spec/support/pages.rb:70:in `signup_and_verify_email'
# ./spec/system/payment_spec.rb:43:in `block (3 levels) in <top (required)>'
Я должен отметить, что это не всегда происходитс page.evaluate_script('window.location.reload()')
.Это может произойти с чем-то мягким, например visit('/')
.
Edit : я попытался отключить Ember FastBoot (рендеринг на стороне сервера) с помощью переменной DISABLE_FASTBOOT
env и внезапно все тестыпроходить.Я думаю, что каким-то образом приборы RSpec в некоторых случаях приводят к тому, что Ember FastBoot не завершает рендеринг.Это, безусловно, соответствует сброшенным соединениям, которые я иногда видел в производственных журналах.
Я экспериментировал с клиентским кодом, и это может быть связано с моим использованием FastBoot's deferRendering
call .
Редактировать : я использую следующие версии:
- ember-cli: 3.1.3
- ember-данные: 3.0.2
- рельсы: 5.2.1
- rspec: 3.8.0
- капибара: 3.8.2
- selenium-webdriver: 3.14.0
- Google Chrome: 69.0.3497.100 (официальная сборка) (64-разрядная версия)
Редактировать : я использую это несколько странноУзел / Экспресс библиотека fastboot-app-server для выполнения рендеринга на стороне сервера.Я обнаружил, что иногда он удаляет важные заголовки ответа (Content-Type и Content-Encoding).Мне интересно, не способствует ли это этой проблеме.
Редактировать : я добавил строгую Политику безопасности контента, чтобы убедиться, что во время набора тестов не выполняются внешние запросы,может быть причиной Net::ReadTimeout
.
Я проверяю вкладку сети Chrome в тот момент, когда она блокируется и кажется, что ничего не загружается.Обновление браузера вручную позволяет тестам забрать и продолжить работу.Как странно.
Я потратил пару недель на это сейчас, и, возможно, пришло время отказаться от тестов Selenium.
Я обновился до Chrome 70 и chromedriver 2.43.Похоже, что это не имеет значения.
Я попытался использовать гем rspec-retry для принудительного обновления, когда истекает время ожидания, но кажется, что драгоценному камню не удалось поймать исключение времени ожидания.
Я проверил сырой запрос к chromedriver, где вещи висят.Похоже, это всегда POST http://127.0.0.1/session/<session id>/refresh
.Я попытался обновить по-другому: visit(page.current_path)
, который, кажется, все исправляет!