E2E Тестирование в Rails 7.1.2 в GitLab Runner CI/CD, с помощью Selenium-Webdriver (4.8.6), Capybara (3.39.2), Docker Compose
20 января 2024
Настройка Docker Compose
Для тестирования E2E Capybara запускает webdriver. Сейчас Selenium предлагает широчайшие возможности для тестирования. Для своего маленького проекта я взял всего лишь chrome. Суть такова, что когда Gitlab Runner запускает тестирование, есть отдельный докере с chrome. Например, так:
version: '3.0' services: browser: image: seleniarm/standalone-chromium shm_size: 2gb volumes: - /dev/shm:/dev/shm app: image: my_blog_development build: context: . dockerfile: prod.Dockerfile args: - PRECOMPILEASSETS=YES environment: - RAILS_ENV=test - SELENIUM_HUB_HOST=browser links: - db - browser depends_on: db: condition: service_healthy browser: condition: service_started ...
SELENIUM_HUB_HOST говорит, собственно, название хоста (совпадает с название сервиса), где вертится chrome. Docker Compose разрешит это имя в IP-адрес сам.
Настройка Rails
Можно и закрепить версии, а то вдруг опять поменяют интерфейс как относительно недавно
# Gemfile group :development, :test do gem 'capybara' #, "~> 3.39.2" gem 'selenium-webdriver' #, "~> 4.8.6" end
Путь файлы конфигурации подгружаются сами
# spec/rails_helper.rb Rails.root.glob('spec/support/**/*.rb').sort.each { |f| require f }
Добавить файл конфигурации Capybara
# spec/support/capybara_config.rb require 'capybara' require 'selenium-webdriver' def ensure_selenium_running! timer = Capybara::Helpers.timer(expire_in: 20) begin TCPSocket.open(ENV['SELENIUM_HUB_HOST'], 4444) rescue StandardError if timer.expired? raise 'Selenium is not running. ' \ "You can run a selenium server easily with: \n" \ ' $ docker-compose up -d selenium_firefox' else puts 'Waiting for Selenium docker instance...' sleep 1 retry end end end Capybara.register_driver :remote_chrome do |app| options = Selenium::WebDriver::Options.chrome options.add_argument('no-sandbox') if ENV['SELENIUM_NO_HEADLESS'].present? options.add_argument('--start-maximized') # чтобы было видно окно браузера для отладки тестов else options.add_argument('--headless') options.add_argument('--window-size=1400,1400') end options.add_argument('--ignore-gpu-blocklist') options.add_argument('--enable-features=VaapiVideoDecode') ## failback options # если на скриншотах будут черные квадраты вместо сайта #options.add_argument('--disable-gpu') #options.add_argument('--disable-software-rasterizer') ensure_selenium_running! Capybara::Selenium::Driver.new app, browser: :remote, capabilities: options, url: "http://#{ENV['SELENIUM_HUB_HOST']}:4444/wd/hub" end RSpec.configure do |config| config.before(:each, type: :system) do driven_by :remote_chrome Capybara.app_host = "http://#{IPSocket.getaddress(Socket.gethostname)}:3000" Capybara.server_host = IPSocket.getaddress(Socket.gethostname) Capybara.server_port = 3000 Capybara.server = :puma, { Silent: true } end end
А вот и самый простой тест
# spec/features/index_spec.rb require 'rails_helper' RSpec.describe 'User', type: :system do it 'visits page' do visit "/" expect(page).to have_text('Stan\'s blog') end end
А как отлаживать тесты?
Для удобства пробросим порты и отключим аутентификацию для VNC. Да, в хаб встроен VNC сервер и даже вэб VNC клиент
# docker-compose.devel.yml - Docker Compose для разработки browser: image: seleniarm/standalone-chromium shm_size: 2gb environment: - SE_VNC_NO_PASSWORD=true - VNC_NO_PASSWORD=1 ports: - "5900:5900" #for VNC access - "4444:4444" #for webdriver access - "7900:7900" #for web VNC access volumes: - /dev/shm:/dev/shm app: environment: - RAILS_ENV=development - BUNDLE_WITHOUT="" - SELENIUM_HUB_HOST=browser - SELENIUM_NO_HEADLESS=1 # чтобы видно было окно браузера ...
Теперь можно подключиться localhost:4444 или localhost:7900 и посмотреть за ходом выполнения теста и полазить в DevTools (sleep 60 в тесте поможет продлить удовольствие от созерцания страницы в режиме выполнения теста)