簡體   English   中英

Capybara + Selenium-webdriver + RSpec文件夾具+ SSR給出Net :: ReadTimeout

[英]Capybara + Selenium-webdriver + RSpec file fixtures + SSR giving Net::ReadTimeout

我注意到一個我幾天都無法解決的奇怪問題。

我有一個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

這可能會失敗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('/')這樣的良性事物上。


編輯 :我嘗試使用DISABLE_FASTBOOT env變量禁用Ember FastBoot(服務器端渲染),並突然通過所有測試。 我想在某種情況下,RSpec燈具會導致Ember FastBoot無法完成渲染。 這肯定與我在生產日志中偶爾看到的連接斷開有關。

我一直在試驗客戶端代碼,這可能是由於我使用了FastBoot的deferRendering調用


編輯 :我使用以下版本:

  • ember-cli:3.1.3
  • 余燼數據:3.0.2
  • 鐵軌:5.2.1
  • rspec:3.8.0
  • 水豚:3.8.2
  • selenium-webdriver:3.14.0
  • 谷歌瀏覽器:69.0.3497.100(官方版)(64位)

編輯 :我正在使用這個有點不穩定的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.refreshvisit(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

我嘗試過visit(page.current_url)但也提供了超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM