【问题标题】:Rails integration tests failing when selenium-webdriver enabled and passing when omitted启用 selenium-webdriver 时 Rails 集成测试失败,省略时通过
【发布时间】:2016-02-26 05:39:22
【问题描述】:

我有以下使用 RSpec 和 Capybara 编写的集成测试,它以 js: true 失败,并且在我省略它时通过。

当我手动测试应用程序时,它工作正常。一旦 Rails 4 服务器从http://localhost:3000 启动,用户就会从/ 重定向到/signin。使用 devise gem 验证用户。

gem 依赖有问题吗?我错过了什么吗?

宝石文件

group :development, :test do
  gem 'sqlite3',     '1.3.11'
  gem 'byebug',      '3.4.0'
  gem 'spring',      '1.1.3'
  gem 'i18n-tasks'
  gem 'rspec-rails'
end

group :test do
  gem 'capybara'
  gem 'selenium-webdriver'
end

login_spec.rb

require 'rails_helper'
RSpec.feature "Login:", js: true do
  scenario "-display login page to the user" do
    visit "/"
    expect(page).to have_xpath("//input[@type='email']")
    expect(page).to have_xpath("//input[@type='password']")
    expect(page).to have_content("Login to Dashboard")
    expect(page).to have_xpath("//input[@type='checkbox']")
    expect(page).to have_content("Forgot your password?")
  end
end

运行规范的命令:

rspec -b spec/feature/login_spec.rb

错误日志:

    Failures:

      1) Login: -display login page to the user
         Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"

         ActionController::RoutingError:
           No route matches [HEAD] "/assets/login_header-117f87e381545e9f6d5a7accb7aa72188a0304644af6891c42e1cd57f38fad67@2x.jpg"
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.2/lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.2/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.2/lib/rails/rack/logger.rb:38:in `call_app'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.2/lib/rails/rack/logger.rb:20:in `block in call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.2/lib/active_support/tagged_logging.rb:68:in `block in tagged'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.2/lib/active_support/tagged_logging.rb:26:in `tagged'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.2/lib/active_support/tagged_logging.rb:68:in `tagged'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.2/lib/rails/rack/logger.rb:20:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/request_store-1.3.0/lib/request_store/middleware.rb:9:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.2/lib/action_dispatch/middleware/request_id.rb:21:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/runtime.rb:18:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/lock.rb:17:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.2/lib/action_dispatch/middleware/static.rb:113:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/sendfile.rb:113:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.2/lib/rails/engine.rb:518:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.2/lib/rails/application.rb:164:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/urlmap.rb:66:in `block in call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `each'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/capybara-2.6.2/lib/capybara/server.rb:19:in `call'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rack-1.6.4/lib/rack/handler/webrick.rb:88:in `service'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/2.1.0/webrick/httpserver.rb:138:in `service'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/2.1.0/webrick/httpserver.rb:94:in `run'
         # C:/RailsInstaller/Ruby2.1.0/lib/ruby/2.1.0/webrick/server.rb:295:in `block in start_thread'
         # ------------------
         # --- Caused by: ---
         # Capybara::ExpectationNotMet:
         #   expected to find xpath "//input[@type='checkbox']" but there were no matches. Also found "", which matched the selector but not all filters.
         #   C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/capybara-2.6.2/lib/capybara/node/matchers.rb:97:in `block in assert_selector'

原始页面 Html

<!-- Login Block -->
  <div class="block push-bit">
    <!-- Login Form -->
    <form class="form-horizontal form-bordered form-control-borderless" id="new_user" action="/signin" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="56u6N33zmqwC3dEO3Nh7aZZqOIRgtphs/hoRXKXP3QRKZ2OfgZ6FpGPpFb6FiMc95DfWD/oOWvZVoepqbivjzw==" />

                <div class="alert
    alert-danger
     alert-dismissible" role="alert" id="alert">
  <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  <span id="alert-msg">You need to sign in or sign up before continuing.</span>
</div>

        <div class="form-group">
          <div class="col-xs-12">
            <div class="input-group">
              <span class="input-group-addon"><i class="gi gi-envelope"></i></span>
              <input label="Email:" wrapper="{:class=&gt;&quot;required&quot;}" id="login-email" class="form-control input-lg" placeholder="Email" type="email" name="user[email]" />
            </div>
          </div>
        </div>

        <div class="form-group">
          <div class="col-xs-12">
            <div class="input-group">
              <span class="input-group-addon"><i class="gi gi-asterisk"></i></span>
              <input label="Password:" wrapper="{:class=&gt;&quot;required&quot;}" id="login-password" class="form-control input-lg" placeholder="Password" type="password" name="user[password]" />
            </div>
          </div>
        </div>

        <div class="form-group form-actions">
          <div class="col-xs-4">

                <label class="switch switch-primary" data-toggle="tooltip" title="Remember Me?">
                  <input name="login-remember-me" type="hidden" value="0" /><input id="login-remember-me" name="login-remember-me" type="checkbox" value="1" />
                  <span></span>
                </label>
          </div>
          <div class="col-xs-8 text-right">
            <button name="button" type="submit" class="btn btn-sm btn-primary" id="login">
                <i class="fa fa-angle-right"></i> Login to Dashboard
</button>          </div>
        </div>

        <div class="form-group">
          <div class="col-xs-12 text-center">

    <a id="link-reminder-login" href="/users/password/new">Forgot your password?</a><br />

          </div>
        </div>
</form>    <!-- END Login Form -->


  </div>
  <!-- END Login Block -->

【问题讨论】:

    标签: ruby-on-rails selenium-webdriver rspec devise capybara


    【解决方案1】:

    首先猜测是您通过 CSS 隐藏了页面上的复选框(然后设置标签以显示它已被选中)。默认的机架测试驱动程序不处理大多数 CSS,因此它仍然会找到复选框,但是当您使用 js: true 时,您使用的是处理 CSS 的真实浏览器。您可以尝试将测试更改为

    expect(page).to have_xpath("//input[@type='checkbox']" , visible: :all)
    

    看看是不是这个问题。现在看到你的 html 看起来你可能正在使用 bootstrap-switch(?) ,它确实隐藏了真正的复选框,所以如果你只关心有一个复选框,你可以在上面做任何事情。或者,您可以检查实时页面上的 html 并查看库添加到页面的 html,并检查其中的一些。中间位置可能是检查隐藏的复选框,但检查它是否在开关包装器内 - 类似于

    expect(page).to have_css('.boostrap-switch-container input[type="checkbox"]', visible: :hidden) # adjust class as necessary for the wrapper produced by the library
    

    这将验证开关的 JS 是否已运行,创建它的包装器,并隐藏其中的复选框。

    我确实质疑为什么您使用 xpaths 来查找这些元素,而您可以使用 ids/names/labels/placeholders 来查找它们并使内容更具可读性

    现在您已经添加了 html - 查看密码字段,没有实际的

    expect(page).to have_field("Password", type: 'password')  # placeholder
    expect(page).to have_field("login-password", type: 'password')  # id
    expect(page).to have_field("user[password]", type: 'password') # name
    

    通常我会选择第一个,因为它正在测试用户应该看到的内容。

    【讨论】:

    • 我进行了您上面建议的更改,但现在出现以下异常。 Capybara::ExpectationNotMet: # expected to find field "password" of type "password" but there were no matches
    • 这是一个如何编写测试的例子。第一个字符串需要与密码字段的 id/name/placeholder 或标签文本匹配 - 如果您想要准确的答案,请发布您的 html
    • 我应该发布带​​有新问题的 html 还是应该修改现有问题?
    • 通过添加实际的 html 代码来编辑原始问题。
    • @user2325154 已更新以匹配您的 html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 2015-04-29
    相关资源
    最近更新 更多