Знакомство с Capybara

Что такое Capybara

Капибара улыбчивая
Капибара — дружелюбное животное

Фреймворк веб-автоматизации функциональных тестов, эмулирующих взаимодействие пользователя с приложением/сайтом. Представляет собой библиотеку (в терминологии Ruby — гем) для работы с web-based-драйвером. Применяется юзер-френдли DSL-язык (Domain Specific Language) описания действий веб-драйвера. Capybara ищет релевантный элемент в DOM и выполняет действие (клик по кнопке, переход по ссылке и все прочее).

Capybara основывается на идее, что в современном веб-приложении практически все происходит асинхронно

Верификация наличия элемента или проверка какого-то условия — Capybara по умолчанию ожидает появления контента или перехода условия в состояние true. Таймауты можно настраивать.

Логотип фреймворка Capybara
Логотип тестового фреймворка может выглядеть даже так

Поддерживаемые веб-драйверы:

  1. rack::test: (дефолтный)
  2. selenium-webdriver
  3. capybara-WebKit
Capybara - как она работает
Как работает Capybara

Ruby-фреймворки для работы с Capybara

Это:

  1. В первую очередь Cucumber, Ruby-based инструмент для BDD (здесь подробнее о Cucumber и BDD)
  2. RSpec, BDD-фреймворк, развитие концепции JBehave
  3. 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, желательно посмотреть ее методы.)

Проект в 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:

Отличия Cucumber от RSpec
Отличия Cucumber от RSpec

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, можно выбрать нужный и запустить:

Запуск тестов из TestExplorer в Capybara
Запуск тестов из TestExplorer в Capybara

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
Капибара зевает
Капибара кричит, то ли зевает

На этом всё. Если нужно подробнее, пишите в коменты или в ТГ.

Весь код этого проекта здесь.

  1. https://github.com/teamcapybara/capybara
  2. https://github.com/mattheworiordan/capybara-screenshot#better-looking-html-screenshots
  3. https://github.com/allure-framework/allure-ruby
  4. https://makandracards.com/makandra/14017-useful-methods-to-process-tables-in-cucumber-step-definitions
  5. https://rdoc.info/gems/kosmas58-cucumber/0.3.102/Cucumber/Ast/Table
  6. https://www.rubydoc.info/gems/capybara/Capybara

Источники: 1,2

***

Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

? Популярное

? Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас