简体   繁体   English

Selenium Chrome在Rails Rspec Docker环境中启用事务处理夹具后看不到数据库更改

[英]Selenium Chrome not seeing database changes with transactional fixtures enabled in Rails Rspec Docker environment

I'm so close yet so far from getting my Selenium tests working in my new Docker dev environment. 我距离让Selenium测试在新的Docker开发环境中工作还很遥远。

I recently did a big upgrade from ruby 2.4.2 to 2.6.3 . 我最近做了一个从ruby 2.4.2到2.6.3的大升级。 Around the same time I also switched from a local environment to a setup with Docker. 大约在同一时间,我还从本地环境切换到了Docker的设置。 Everything migrated fine except for this one last issue. 除最后一个问题外,一切都正常迁移。

With browser tests, it appears that the browser can't see the changes to the database, for example, when I create a user, and then log in through the web UI on the browser, the returned webpage says "user and pass doesn't not exist". 通过浏览器测试,似乎浏览器看不到数据库的更改,例如,当我创建一个用户,然后通过浏览器上的Web UI登录时,返回的网页显示“ user and pass not”不存在”。 Also, the changes don't appear in the database even in the middle of the test, though I think that's normal when transactional_fixtures is enabled. 另外,即使在测试过程中,更改也不会出现在数据库中,尽管我认为启用transactional_fixtures时这是正常的。

The problem goes away when config.use_transactional_fixtures = false . config.use_transactional_fixtures = false时,问题消失了。 But then I have to deal with database cleaning, which I tried and was also problematic. 但是然后我不得不处理数据库清理,这是我尝试过的,也是有问题的。 Note that this all worked fine in ruby 2.4.2 on my local MacOS. 请注意,这在我的本地MacOS上的ruby 2.4.2中都可以正常工作。

I can access the browser via VNC on port 5900 and see the tests running fine until it needs to do anything that requires data from the db, like logging in via the browser with a username that was created programmatically in the spec. 我可以通过端口5900上的VNC访问浏览器,并查看测试运行良好,直到它需要执行需要数据库中数据的任何操作为止,例如使用浏览器使用规范中通过编程方式创建的用户名登录。

It's not clear to me where the database information goes if it's not in the database, or how the browser can access this data? 如果数据库中没有数据库信息,我还是不清楚,或者浏览器如何访问这些数据? This article seems to discuss the relevant issue of Capybara and the web server sharing the same db connection to access uncommitted db changes. 本文似乎在讨论Capybara和共享相同数据库连接以访问未提交的数据库更改的Web服务器的相关问题。 But I'm still lost after several days 🤦‍♂️ 但是几天后我仍然迷路了

Here are my configs. 这是我的配置。

Dockerfile Docker文件

FROM ruby:2.6.3
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client pdftk xvfb

RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip
RUN mv chromedriver /usr/bin/chromedriver
RUN chown root:root /usr/bin/chromedriver
RUN chmod +x /usr/bin/chromedriver

RUN echo "chromedriver -v"
RUN chromedriver -v
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
ENV BUNDLER_VERSION='2.0.2'
RUN gem install bundler --no-document -v '2.0.2'

RUN echo $BUNDLER_VERSION
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml docker-compose.yml

version: '3'
services:
  db:
    image: postgres:9.6.15
    volumes:
      - data:/var/lib/postgresql/data
    environment:    
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
    ports:
      - "5432:5432"
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && RAILS_ENV=test bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
    links:
      - selenium
  redis:
    image: redis:alpine
    command: redis-server
    ports:
      - "6379:6379"
  sidekiq:
    depends_on:
      - db
      - redis
    build: .
    command: sidekiq -c 1 -v -q default -q mailers
    volumes:
      - '.:/myapp'
    env_file:
      - '.env'

  selenium:
    image: selenium/standalone-chrome-debug:3.0.1-germanium
      # Debug version enables VNC ability
    ports: ['4444:4444', '5900:5900']
      # Bind selenium port & VNC port
    logging:
      driver: none
      # Disable noisy logs.

volumes:
  data: 

spec/rails_helper.rb spec / rails_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
require 'support/factory_bot'
require 'support/session_helpers'
require 'support/record_helpers'

@both = ['artist','gallery']

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # 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 = true

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  #
  # You can disable this behaviour by removing the line below, and instead
  # explicitly tag your specs with their type, e.g.:
  #
  #     RSpec.describe UsersController, :type => :controller do
  #       # ...
  #     end
  #
  # The different available types are documented in the features, such as in
  # https://relishapp.com/rspec/rspec-rails/docs
  config.infer_spec_type_from_file_location!

  # Filter lines from Rails gems in backtraces.
  config.filter_rails_from_backtrace!
  # arbitrary gems may also be filtered via:
  # config.filter_gems_from_backtrace("gem name")


  config.include Features::SystemTestHelpers#, type: :system

end

# fixes a glitch in most recent chromedriver or chrome where it can't access remote URLs
# https://github.com/teamcapybara/capybara/issues/2181
require "selenium/webdriver"

Capybara.app_host = "http://web:3000"
Capybara.javascript_driver = :selenium_chrome_headless
Capybara.run_server = false

Capybara.register_driver :selenium_chrome_headless do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w(no-default-browser start-maximized enable-features=NetworkService,NetworkServiceInProcess) }
  )
  Capybara::Selenium::Driver.new app, browser: :remote, url: "http://selenium:4444/wd/hub", desired_capabilities: capabilities
end

entrypoint.sh 入口点

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

bundle install

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

An excerpt of a spec that's breaking 规范的摘录

spec/system/record_gallery_spec.rb 规范/系统/record_gallery_spec.rb

require 'rails_helper'

feature 'User creates a work' do

  scenario 'with most fields filled out', driver: :selenium_chrome_headless do 
    gallery_sign_in

    visit new_work_path
    # breaks here ^^

    ...

  end
end

the helper function referenced above 上面引用的助手功能

def gallery_sign_in(user: nil, id: nil, custom_pdf: nil)
  user = create(:user, id: id, custom_pdf: custom_pdf) unless user
  user.role = 'gallery'
  user.save

  visit login_path
  fill_in 'user[email]', with: user.email
  fill_in 'user[password]', with: user.password
  click_button 'Login'
  return user
end

Rails 5.1 does support sharing the DB connection between the Application under test and the tests (transactional testing) but only if you're letting Capybara start the instance of the application under test, since the tests and the app need to be running as separate threads under the same process. Rails 5.1确实支持在被测应用程序和被测应用程序(事务性测试)之间共享数据库连接,但前提是您要让Capybara启动被测应用程序的实例,因为测试和应用程序需要作为单独的线程运行在相同的过程中。 You're specifically telling Capybara not to to run the app under test ( Capybara.run_server = false ) and instead telling it to run against an app instance you're starting separately ( Capybara.app_host = "http://web:3000" ). 您是专门告诉Capybara不要运行被测应用程序( Capybara.run_server = false ),而是告诉它要针对要单独启动的应用程序实例运行( Capybara.app_host = "http://web:3000" )。 In that configuration there is no way to share the DB connection between the tests and the AUT so you have to disable transactional testing ('config.use_transactional_fixtures = false') and use database_cleaner (or something else similar) to handle resetting the DB between each test. 在该配置中,无法共享测试与AUT之间的数据库连接,因此您必须禁用事务测试('config.use_transactional_fixtures = false')并使用database_cleaner(或其他类似方法)来处理每个数据库之间的数据库重置。测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM