Призрак оперы

Поэтому мы хотели найти способ просто проверить, работают ли наши различные веб-приложения и веб-страницы, без необходимости проверять их каждый час или получать уведомления от наших клиентов (что всегда смущает).

Можно было либо использовать существующий сервис, либо написать что-то самостоятельно, и, поскольку я уже создавал нечто подобное в прошлом с одним из моих предыдущих коллег (которого я благодарю за предоставленные знания), я подумал: «Я могу это сделать!».

И я сделал. Хотя это было больно.

Я написал свой код на Ruby и использовал Selenium WebDriver и PhantomJS, чтобы иметь возможность выполнять все мои тесты без реального браузера, таким образом, все тесты выполняются Selenium на PhantomJS, и мы просто видим результаты в терминале.

Я собираюсь перечислить шаги и дать подробное вступление и резюме для каждого из них. В зависимости от вашего уровня уверенности в программировании вы можете пропустить вступление, если вы уже знаете свои вещи.

Если вы хотите получить базовый макет, вы можете форк my repo on GitHub и попробовать :)

Шаг 1. Самоцветы

Введение

Я использовал очень мало драгоценных камней, чтобы все настроить, я расскажу вам немного о каждом из них.

  • Slack-notifier: (см. это на шаге 3.2). Я хотел, чтобы мое приложение уведомляло меня о Slack, когда что-то идет не так с моими тестами, поэтому я получил гем-уведомитель slack и создал очень маленький и милый бот, который выглядит потрясающе. Жемчужина Slack-notifier совершенно необязательна, если у вас нет страсти к Slack-уведомлениям или крутизне в целом, вы можете пропустить это. Я не сужу. Однако, если вы круты, вот где вы можете найти все подробности о создании собственного Slack-бота с помощью драгоценного камня Slack-notifier.

  • phantomjs: вам это понадобится. Это то, что позволяет вам запускать все ваши тесты и фактически перемещаться без браузера. Вы можете рассматривать PhantomJS как фальшивый невидимый браузер, который ваш код может использовать, как если бы это был человек, вводящий адрес в Chrome или Safari или в другом месте, которое вы использовали бы для этого вручную. Если вы не хотите использовать PhantomJS по * причинам, которые меня не волнуют *, вы можете указать Selenium использовать настоящий браузер для выполнения всех необходимых тестов. Но я не буду вдаваться в подробности из-за * причин, которые вам наплевать *.
  • selenium-webdriver: (см. его на шаге 2 - сводка) Selenium делает все классные вещи. Webdriver - это маленький невидимый пользователь, который позволит вам перейти на страницу (.get), найти что-то (.find-element), щелкнуть что-то и другие приятные вещи, которые вы бы сделали сами, если бы вы тестировали вручную, чтобы что-то работало. должным образом. Ты нуждаешься в этом.
  • dotenv: (подробнее см. в шаге 2 и шаге 3.0) Итак, мне пришлось использовать dotenv, потому что я не хотел, чтобы мой Slack URI был в моем коде, так что dotenv позволяет вам хранить и использовать информацию, которая будет видна только вам в вашей локальной среде (если вы сделаете себе одолжение, gitignore это). Это необязательно, особенно если вы не собираетесь создавать очень крутого слэк-бота, который будет рассказывать вам милые вещи с помощью смайликов-призраков.
  • rake: (см. шаг 4). Rake - это диспетчер задач, вы пишете в rakefile, что вы хотите, чтобы произошло с другими вашими файлами и когда, затем вы выполняете свой rakefile, и он позаботится обо всем ваших задач за вас. Если вы не хотите указывать Heroku на выполнение нескольких разных команд для запуска всех ваших тестов, вы можете использовать rake и написать rakefile.

Резюме

Gemfile:

‘https://rubygems.org'
ruby ‘2.3.1’
gem ‘slack-notifier’
gem ‘phantomjs’
gem ‘selenium-webdriver’, ‘~>2.53.4’
gem ‘dotenv’
gem ‘rake’

Теперь $ gem install bundler и $ bundle install в корне вашего проекта, и вы почти закончили с шагом 1.

Единственное, чего не хватает, что не является драгоценным камнем, но все же необходимо установить, - это исполняемый файл для PhantomJS. Вы не можете ожидать, что вся эта магия произойдет без установки браузера без монитора, даже если вы его не видите, это все равно браузер! Итак, $ npm install -g phantomjs, и вперед.

Шаг 2. Помощник

Введение

Вам понадобится помощник, если вы планируете иметь более одного тестового файла, чтобы вы могли переместить фрагменты кода, которые вы собираетесь повторно использовать, в отдельный файл, который затем можно будет вызывать в каждом из ваших тестовых файлов. В помощнике у вас будут все ваши require утверждения.

В моем случае мне потребовалось следующее:

require ‘phantomjs’
require ‘selenium-webdriver’
require ‘time’
require ‘dotenv’
Dotenv.load

Я добавил Dotenv.load в конце, потому что, очевидно, Ruby не знает, что делать после запроса dotenv, и вы должны сказать ему, чтобы он загрузил его, иначе переменные ENV не будут распознаваться, и slack-URI не будет установлен как переменная окружающей среды. Если вы не планируете использовать slackbot, вам не нужно беспокоиться об этом, если только вы не планируете иметь другие вещи, которые хотите сохранить в тайне.

У моего помощника естьsetup, run and teardown методов.

  • setup будет определять мой драйвер и тип браузера, который он будет использовать: @driver = Selenium::WebDriver.for :phantomjs, если вы планируете использовать другой браузер, просто укажите имя браузера, который вы собираетесь использовать, вместо :phantomjs. После того, как я столкнулся с некоторыми проблемами во время моих тестов, так как я не мог найти свои элементы в окне браузера, я сделал его снимок и обнаружил, что размер моего фантомного окна браузера был для мобильных устройств, поэтому мои элементы были скрыты, а мои тесты не удалось бы, даже если страница была поднята, поэтому я изменил размер окна следующим образом: @driver.manage.window.resize_to(1300,500), а затем все заработало.
  • В run методе есть все, что должно произойти при загрузке файла. Если вы не хотите распечатывать красивое сообщение, в котором рассказывается, сколько времени длился ваш тест, вы можете пропустить start_time, end_time и puts
def run
  start_time = Time.now

  setup
  yield
  teardown

  end_time = Time.now
  puts 'Total test duration: ' + (end_time - start_time).round(2).to_s + ' seconds'
end
  • teardown просто завершит работу драйвера с помощью @driver.quit.

Итак, в основном мы определяем наш драйвер в настройке, мы выходим из него в процессе разборки и помещаем настройку и разборку в наш метод запуска, чтобы они происходили по порядку и позволяли нам yield наши блоки кода.

Резюме

Вкратце test_helper.rb:

require 'phantomjs'
require 'selenium-webdriver'
require 'time'
require 'dotenv'
Dotenv.load 
def setup
  @driver = Selenium::WebDriver.for :phantomjs
  @driver.manage.window.resize_to(1300, 500)
end 
def teardown
  @driver.quit
end 
def run
  setup
  yield
  teardown
end

Теперь вы можете require ‘test_helper.rb’ в своих тестовых файлах, и любой блок кода, который вы собираетесь иметь, будет передан yield и будет следовать тому же потоку, который указан в помощнике. 🎉

Шаг 3.0 (ДОПОЛНИТЕЛЬНО). Создайте свой SlackBot

Для этого даже не требуется вступление или резюме. Ваш файл slackbot.rb должен выглядеть примерно так:

require 'slack-notifier'

notifier = Slack::Notifier.new ENV['SLACK_URI']
notifier.ping "Something's wrong! Go to <#{@appLink}|#{@appName}> for details! "

slack-notifier - это гем, о котором мы говорили на шаге 1. ENV - это переменная окружения «ключ», используемая нашим гемом dotenv и позволяющая нам получить доступ к переменным, записанным в файле .env. (так вы пишете переменную окружения в вашем .env файле = SLACK_URI=https://yourLinkGoesHere). ping - это метод, исходящий от драгоценного камня Slack, который отправляет уведомление на выбранный вами SLACK_URI.

Шаг 3.1. Напишите свои тесты

вступление

Создайте папку, в которую войдут все ваши тестовые файлы. Каждый из ваших тестовых файлов должен иметь require ‘test_helper.rb' в первой строке файла, чтобы код, который вы пишете в нем, выполнялся в test_helper и чтобы ваш драйвер был определен.

В приведенных ниже примерах вы увидите файл, включающий переменные и методы использования slackbot, а также тот, который в них не нуждается.

В примере со Slackbot я сохранил имя своего приложения и ссылку на переменные, которые я хочу использовать в файле slackbot.rb (на полшага вверх). Это связано с тем, что у меня есть разные приложения, которые я хочу протестировать, и я хочу, чтобы тестовый файл определял переменные @appName и @appLink с тем, что я собираюсь тестировать в данный момент.

В примерах, приведенных в сводке этого раздела, вы увидите begin — rescue блок. Я решил использовать исключение Ruby, потому что таким образом, если драйвер не может получить ссылку или элемент не найден, выполнение файла не будет аварийным и вместо этого будет выводиться сообщение об ошибке (или в случае slackbot, отправьте уведомление на мой канал 👻). Я, наверное, мог бы использовать Selenium Expectations, но мне это показалось проще.

Другие люди могут иметь другое мнение по этому поводу, а я новичок в программировании, так что не верьте мне на слово 😸

Для тех, кто очень новичок в кодировании (новее меня, по крайней мере 😄), я хочу уточнить, что я могу использовать переменную @driver в тестовом файле, потому что я определил ее в помощнике и импортировал помощник в свой тест файл, поэтому все, что в нем содержится, будет следовать. Та же концепция применяется к @appName и @appLink, которые я определяю в своих тестовых файлах, а затем использую в моем файле slackbot после его загрузки в среду, в которой были определены переменные.

Резюме

Пример тестового файла со Slackbot:

run do
  @appName = 'MyApp'
  @appLink = 'https://myapp.com'

  begin
    @driver.get @appLink
    @driver.find_element(yourSelectorOfChoice: 'example')
    puts 'Congrats! Your website is up!'
  rescue
    puts 'Whoops! Something went wrong here :('
    load './slackbot.rb'
  end
end

Пример тестового файла без slackbot:

run do

  begin
    @driver.get 'https://myapp.com'
    @driver.find_element(yourSelectorOfChoice: 'example')
    puts 'Congrats! Your website is up!'
  rescue
    puts 'Whoops! Something went wrong here :('
  end
end

yourSelectorOfChoice - это селектор любого типа, который вы решите использовать вместе с find_element.

Шаг 4 (ДОПОЛНИТЕЛЬНО). Напишите свой Rakefile

вступление

Если вы хотите, чтобы ваш планировщик Heroku был чистым, вам нужно иметь в своем проекте Rakefile, чтобы вы могли выполнять все свои различные тесты, вызывая только одно действие.

Я столкнулся с несколькими проблемами при настройке моего Rakefile из-за того, что я продолжал указывать разные пути для разных файлов, но после долгих усилий мне удалось найти древовидную структуру, которая заставила все работать.

Резюме

Вот как может выглядеть rakefile!

desc "Goes to myapp.com"
task :tests_myapp do
  ruby './tests/test-file.rb'
end

task :default => [:tests_myapp]

Чтобы добавить больше задач, просто создайте другую задачу и добавьте ее в список таких задач:

desc "Goes to myapp.com"
task :tests_myapp do
  ruby './tests/test-file1.rb'
end
desc "Goes to myotherapp.com"
task :tests_myotherapp do
  ruby './tests/test-file2.rb'
end
task :default => [:tests_myapp, :tests_myotherapp]

так далее..

Шаг 5. Разверните на Heroku

вступление

Эта часть вызвала у меня настоящую головную боль. Я просто не знал, почему PhantomJS не работает после того, как я добавил мой проект на Heroku и написал свою команду в планировщике для выполнения моих задач. Я много гуглил, но мне как-то удавалось всегда открывать не тот вопрос на StackOverflow 😅

Причина заключалась в том, что мне нужно было добавить веб-пакет, чтобы сделать исполняемый файл PhantomJS доступным для Heroku, поскольку я установил его только на свой компьютер, а Heroku понятия не имел, как к нему добраться!

Как только я его получил, реализация была более чем простой.

Резюме

Шаг за шагом:

  • Зайдите в Heroku и авторизуйтесь.
  • Щелкните apps и создайте новый
  • Подключите ваше новое приложение к репозиторию GitHub
  • Щелкните Overwiew и установите надстройку Heroku под названием «Планировщик».

С rakefile:

  • Зайдите в Планировщик и добавьте bundle exec rake -f tests/rakefile.rb или любой другой путь к вашему rakefile из корня вашего проекта.

Без rakefile:

  • Я сам этого не делал, но думаю, вам нужно будет добавить новое задание для каждого тестового файла, а затем runruby tests/test-file.rb вместо rake.

Потом:

  • Зайдите в свой терминал и установите Heroku CLI
  • Подключитесь к своему приложению Heroku и добавьте веб-пакет PhantomJS, набрав в терминале:

$ heroku buildpacks:add https://github.com/stomita/heroku-buildpack-phantomjs -a your-project-name

А теперь развернитесь и будьте счастливы! Ваши тесты должны запускаться в соответствии с планировщиком (каждые 10 минут, ежечасно или по вашему выбору), и вы увидите сообщения в журналах Heroku!

Удачного пинга! ❤