Mar*_*ska 6 rspec ruby-on-rails capybara ember.js selenium-webdriver
我注意到一个我几天都无法解决的奇怪问题.
我有一个Rails 5 API服务器,系统测试使用RSpec和Capybara + Selenium-webdriver驱动无头Chrome.
我正在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
Run Code Online (Sandbox Code Playgroud)
这可能会失败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)>'
Run Code Online (Sandbox Code Playgroud)
我应该指出它并不总是会发生page.evaluate_script('window.location.reload()').它可能发生在一些良性的事情上visit('/').
编辑:我尝试使用DISABLE_FASTBOOTenv变量禁用Ember FastBoot(服务器端渲染),突然所有测试都通过.我想在某种情况下,RSpec灯具会导致Ember FastBoot无法完成渲染.这肯定与我在生产日志中偶尔看到的连接断开有关.
我一直在试验客户端代码,这可能是由于我使用了FastBoot的deferRendering调用.
编辑:我使用以下版本:
编辑:我正在使用这个有点不稳定的Node/Express库fastboot-app-server来进行服务器端渲染.我发现它有时会删除重要的响应头(Content-Type和Content-Encoding).我想知道这是否有助于解决这个问题.
编辑:我添加了严格的内容安全策略,以确保在测试套件中没有可能导致的外部请求Net::ReadTimeout.
我检查Chrome网络选项卡,当它锁定时,似乎什么都没有加载.手动刷新浏览器允许测试接收并继续运行.多么奇怪.
我现在花了几个星期的时间,可能是时候放弃Selenium测试了.
我升级到Chrome 70和chromedriver 2.43.它似乎没有什么区别.
我尝试使用rspec-retry gem在超时发生时强制刷新但是gem似乎无法捕获超时异常.
我已经检查过对chromedriver的原始请求.它看起来总是如此POST http://127.0.0.1/session/<session id>/refresh.我尝试以另一种方式刷新:visit(page.current_path)这似乎解决了问题!
我终于通过切换page.driver.browser.navigate.refresh到visit(page.current_path).
我知道这是一个丑陋的黑客,但这是我能找到的唯一能让事情正常工作的方法(请参阅我在问题编辑中的各种尝试)。
我查看了每次导致超时的 chromedriver 请求:POST http://127.0.0.1/session/<session id>/refresh。我只能猜测这是 chromedriver 的某种问题。也许顺便说一句,它仅在多个 chromedriver 实例处于活动状态时才会挂起(当使用多个 Capybara 会话时会发生这种情况)。
编辑:我还需要考虑查询参数:
def refresh
query = URI.parse(page.current_url).query
path = page.current_path
path += "?#{query}" if query.present?
visit(path)
end
Run Code Online (Sandbox Code Playgroud)
我尝试这样做,visit(page.current_url)但这也导致超时。
| 归档时间: |
|
| 查看次数: |
607 次 |
| 最近记录: |