Что такое Capybara
Фреймворк веб-автоматизации функциональных тестов, эмулирующих взаимодействие пользователя с приложением/сайтом. Представляет собой библиотеку (в терминологии Ruby — гем) для работы с web-based-драйвером. Применяется юзер-френдли DSL-язык (Domain Specific Language) описания действий веб-драйвера. Capybara ищет релевантный элемент в DOM и выполняет действие (клик по кнопке, переход по ссылке и все прочее).
Capybara основывается на идее, что в современном веб-приложении практически все происходит асинхронно.
Верификация наличия элемента или проверка какого-то условия — Capybara по умолчанию ожидает появления контента или перехода условия в состояние true. Таймауты можно настраивать.
Поддерживаемые веб-драйверы:
- rack::test: (дефолтный)
- selenium-webdriver
- capybara-WebKit
Ruby-фреймворки для работы с Capybara
Это:
- В первую очередь Cucumber, Ruby-based инструмент для BDD (здесь подробнее о Cucumber и BDD)
- RSpec, BDD-фреймворк, развитие концепции JBehave
- Minitest — пакет для тестирования на Ruby, набор инструментов для TDD и BDD с моками и бенчмарками
Плюсы Cabybara
- Несложная настройка для Rails и Rack, все работает из коробки
- Интуитивное API
- Быстрое переключение бекенда из headless-режима в реальный браузер без внесения изменений в тесты
- Мощная синхронизация — не нужно задавать вручную ожидание в асинхронных процессах
- Встроенная поддержка Selenium
- А WebKit поддерживается через внешний гем
Подключение других инструментов
Начальная настройка:
brew install ruby brew cask install chromedriver gem install bundler gem install cucumber selenium-webdriver gem install rspec cucumber - init. // Create cucumber based test folder strucuture rspec - init. // Create RPSec based test folder structure bundle init. bundle gem <Project_Name> bundle install // Install dependency mentioned in Gemfile
В данном случае работаем с указанными выше тестовыми фреймворками RSpec и MiniTest. В принципе, можно работать с любым из них. Конфигурация:
(Перед тем как ознакомиться, как работает Capybara, желательно посмотреть ее методы.)
Проект в Capybara
Состоит из следующих компонентов:
env.rb
Здесь конфигурация драйверов:
require "selenium-webdriver" require "capybara" require "cucumber" require "rubygems" require "capybara/cuprite" require "allure-cucumber" require "capybara-screenshot/cucumber" World(Capybara::DSL) Capybara.threadsafe = true Before do |scenario| Capybara.save_path = "screenshot" Capybara.register_driver :chrome do |app| Capybara::Selenium::Driver.new(app, :browser => :chrome) end if ENV["BROWSER"] == "chrome" Capybara.default_driver = :chrome $driver = Capybara::Session.new(:chrome) Capybara.javascript_driver = :chrome log("Chrome driver is getting instantiated") elsif ENV["BROWSER"] == "firefox" Capybara.default_driver = :firefox Capybara.register_driver :firefox do |app| options = { :js_errors => true, :timeout => 360, :debug => false, :inspector => false, } Capybara::Selenium::Driver.new(app, :browser => :firefox) end else Capybara.default_driver = :cuprite $driver = Capybara::Session.new(:cuprite) log("Headless chrome driver is getting instantiated is getting instantiated") end log(ENV["BROWSER"]) log("Driver instacne has been created for Scenarios") end After do |scenario| if scenario.failed? timestamp = "#{Time.zone.now.strftime("%Y-%m-%d-%H:%M:%S")}" end Capybara.reset_sessions! end ############ Adding Alure Report ############# # Allure AllureCucumber.configure do |c| c.results_directory = "report/allure-results" c.clean_results_directory = true c.link_tms_pattern = "https://example.org/tms/{}" c.link_issue_pattern = "https://example.org/issue/{}" c.tms_prefix = "TMS_" c.issue_prefix = "ISSUE_" end
features-файл
Здесь будут сценарии, в BDD-формате:
#features/githubhome.feature @regression @SEVERITY:trivial @ISSUE:YZZ-100 @TMS:9901 Feature: Github homepage Scenario: Github homepage loads properly Given I am on github homepage Then the title of the page should be "GitHub: Where the world builds software · GitHub" Scenario: Sign in to github page Given I am on github homepage When I click on sign in button Then the title of the page should be "Sign in to GitHub · GitHub" Scenario: Sign up to github page Given I am on github homepage When I click on sign up button Then the page should have "Create your account" Scenario: Sign up to github page Given I am on github homepage When I click on sign up button And I Enter details for account creation Then the page should have "Create your account"
Step definition
DSL-код для выполнения тестов:
require "capybara" require "capybara/dsl" require "rspec" require_relative "../support/page_module" World(Capybara::DSL) include Pages Given(/^I am on github homepage$/) do visit "http://www.github.com" end When(/^I click on sign in button$/) do signin = Pages::SignIn.new signin.signin_github end When(/^I click on sign up button$/) do signup = Pages::SignUp.new signup.click_on_signup end And(/^I Enter details for account creation$/) do signup = Pages::SignUp.new signup.signup_github end Then(/^the title of the page should be "(.*)"$/) do |titleText| expect(@browser.title).to be == titleText end Then(/^the page should have "(.*)"$/) do |pageContent| expect(page).to have_content(pageContent) end
page_module.rb
Инкапсулированные page object и действия.
Можно применять разные гемы типа“page-object” и“prism” для написания тест-кейсов в POM.
(Если возникают трудности с пониманием Page Object Model, здесь большой подробный гайд).
require "capybara/dsl" World(Capybara::DSL) module Pages include Capybara::DSL class SignIn def signin_github find(:xpath, '//a[@class="HeaderMenu-link no-underline mr-3"]').click end end class SignUp def click_on_signup find(:xpath, '//a[@class="HeaderMenu-link d-inline-block no-underline border border-gray-dark rounded-1 px-2 py-1"]').click end def signup_github find(:xpath, '//input[@id="user_login"]').set("mk") find(:xpath, '//input[@id="user_email"]').set("mk@gmail.com") find(:xpath, '//input[@id="user_password"]').set("mkgmailcom") end end end
Rakefile
Инструмент для управления тасками и автоматизации билда. Здесь прописываются (и группируются) таски (задачи), и описываются зависимости в namespace.
Можно вызвать нужные таски и указать им “<browser name>” как параметр, чтобы запустить только в этом браузере. Также прописывается тег в таске, чтобы запустить только один нужный тест (или набор тестов одного предназначения), например @smoke или @regression.
require "rubygems" require "cucumber" require "cucumber/rake/task" require "rake/clean" require "rake/testtask" require "rspec/core/rake_task" CLEAN.include("*.tmp") CLOBBER.include("*.tmp", "build/*") CLEAN.include(".html") task :default => ["clean"] task :clean do rm_rf "screenshot/*" end Cucumber::Rake::Task.new(:run_features, "This is my cucumber rake task") do |t, args| #t.profile = "runCucumberTest" # comment below line of code to use this line of code.both have same purpose. t.cucumber_opts = %w{--tags @regression} end task :runCucumberTest, [:arg1] do |t, args| puts "Args were: #{args} of class #{args.class}" puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}" ENV["BROWSER"] = args.arg1 puts "Env browse name, #{args.arg1}" Rake::Task[:run_features].invoke() end task :default => [:runCucumberTest] ########### Running MiniTest task ***************** Rake::TestTask.new(:runMiniTest) do |t| t.pattern = "test/*.rb" end task :runMiniTest do |t| Rake::TestTask[:minitest].invoke() end ############ Running RSpec Task ############## task :runRSpecTest, [:arg1] do |t, args| puts "Args were: #{args} of class #{args.class}" puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}" ENV["BROWSER"] = args.arg1 puts "Env browse name, #{args.arg1}" Rake::Task[:runRSpecTest].invoke() end RSpec::Core::RakeTask.new(:runRSpecTest) do |t| t.pattern = "spec/*_spec.rb" t.rspec_opts = "--tag regression" end
Запуск таска, командой:
$rake 'runCucumberTest['chrome']
Что такое RSpec
RSpec (официальный сайт) — инструмент тестирования для Ruby, заточенный под BDD-тестирование. Наиболее часто применяемая QA-библиотека для Ruby. Несмотря на широкий набор функций и наличие DSL, достаточно прост для новичка.
Отличия от Cucumber DSL:
RSpec создает папку ‘spec’ с тестами. Кроме ‘env.rb’, есть файт ‘spec_helper.rb’, загружающий все Rails-окружение, многочисленные helper-файлы и параметры конфигурации.
В RSpec применяются два способа создания экземпляра драйвера. Первый: регистрация драйвера в spec_helper, создание экземпляра, и применение во всех spec-файлах. Пример:
require "selenium/webdriver" require "capybara" require "capybara/cuprite" require "capybara-screenshot/rspec" require "capybara/rspec" Capybara.configure do |config| config.default_max_wait_time = 10 # seconds config.default_driver = :firefox end RSpec.configure do |config| config.include Capybara::DSL end include Capybara::DSL Capybara.register_driver :chrome do |app| Capybara::Selenium::Driver.new(app, :browser => :chrome) end if ENV["BROWSER"] == "chrome" Capybara.default_driver = :chrome @driver = Capybara::Selenium::Driver.new(:chrome) elsif ENV["BROWSER"] == "firefox" Capybara.register_driver :firefox do |app| Capybara::Selenium::Driver.new(app, :browser => :firefox) end Capybara.default_driver = :firefox @driver = Capybara::Selenium::Driver.new(:firefox) else Capybara.default_driver = :cuprite @driver = Capybara::Session.new(:cuprite) end
#######githubuser_spec.rb require 'page_module' require "spec_helper" RSpec.describe "Github home page" do before :each do visit "http://www.github.com" end context "Creating GitHub Page user account" do it "Github homepage loads properly", smoke: true do expect(@session.title).to be == "GitHub: Where the world builds software · GitHub" end it "Sign in to github page", smoke: true do signin = Pages::SignIn.new(@session) signin.signin_github end it "Sign up to github page", smoke: true do signup = Pages::SignUp.new(@session) signup.click_on_signup signup.signup_github end end after :each do @session.reset_session! end end
Второй способ: ‘named session’, создающая несколько сессий из одного драйвера. Пример такого кода — внизу в ссылках.
Запуск теста RSpec
Из терминала:
$ bundle exec rspec spec/githubuser_spec.rb
$bundle exec rspec spec/*.rb
Через Rake: указывается, в каком браузере запускать. Также можно в Rakefile указать ‘-tag’.
$rake ‘runRpecTest[‘chrome’]’
Из Test Explorer:
Все RSpec-тесты отображаются в TestExplorer, можно выбрать нужный и запустить:
Minitest
Пакет для тестирования под Ruby, поддерживающий TDD (что это?), BDD, моки и бенчмарки. Небольшой, быстрый, нацеленный на легкую читаемость тестов. Кроме модульных и интеграционных тестов (это его традиционное применение), можно тестировать контроллеры.
Как и в Cucumber и RSpec, здесь есть ‘test_helper.rb’. В примере ниже не включен код инициализации драйвера, только добавлен в файл класса.
require "capybara/minitest" require "minitest/autorun" require_relative "test_helper" class HomeSpec < Minitest::Test include Capybara::DSL def setup Capybara.register_driver :selenium do |app| Capybara::Selenium::Driver.new(app, :browser => :chrome) end Capybara.default_driver = :selenium_chrome # Capybara.save_path = "test/tmp" end def test_mk assert_equal "1", "2" end def test_hello visit "http://www.github.com" assert_content "Homepage" page.must_have_content "Homepage" end end
Запуск:
$ruby test/github_minitest.rb
На этом всё. Если нужно подробнее, пишите в коменты или в ТГ.
Ссылки
- https://github.com/teamcapybara/capybara
- https://github.com/mattheworiordan/capybara-screenshot#better-looking-html-screenshots
- https://github.com/allure-framework/allure-ruby
- https://makandracards.com/makandra/14017-useful-methods-to-process-tables-in-cucumber-step-definitions
- https://rdoc.info/gems/kosmas58-cucumber/0.3.102/Cucumber/Ast/Table
- https://www.rubydoc.info/gems/capybara/Capybara
***