Это случилось давным-давно, когда небо было зеленее, трава чище, а я уже числился ведущим инженером по тестированию. Довелось мне побывать на выпускном вечере курсов QA в качестве приглашённого гостя. Свежеиспечённые джуны делились впечатлениями от спринтов, спрашивали о том, насколько реальная работа отличается от учебников «Яндекса», к чему им готовиться в дальнейшем и вообще — как корабли бороздят просторы Большого театра.
Один из вопросов, запомнился мне особенно: «Какой главный инструмент тестировщика?» Ещё до того, как я успел ответить, начинающие специалисты начали гадать:
— Postman!
— Идея!
— Да нет, DevTools же или логи!
— Аллюр!
Я же, прикинув последние свои рабочие будни, выдал:
— Главный инструмент тестировщика — Slack или другой корпоративный мессенджер. Вы и не представляете, сколько в этой профессии вам придётся разговаривать. С разработчиками, бизнесом, а возможно, даже с заказчиками и пользователями.
Все мы привыкли к общепринятым инструментам для тестирования. Думаю, список есть у каждого и он постоянно пополняется. Лично мой: Postman, IntelliJ IDEA и DataGrip от JetBrains, ShareX для скриншотов и его величество DevTools.
В этой статье я хотел бы отдать дань самоделкам нашего ремесла. Мелкие скрипты и утилиты или целые приложения, написанные для того, чтобы помочь в нелёгком деле создания продукта. На первый взгляд незначительные штуки, которые делают процесс работы таким удобным.
Дисклеймер: возможно, кому-то моя статья покажется очевидной. Но уверен, что будут и те, для кого этот текст станет отправной точкой, чтобы сделать свою жизнь комфортнее.
Зачем вообще тратить время и ресурсы на это?
Комфорт — это, конечно, хорошо и понятно (по крайней мере, чаще всего), но как понять, стоит ли игра свеч? Для этого я всегда задаю два главных вопроса — «Как?» и «Зачем?»
Хотя есть ещё третий: «Сколько стоит?» Но он слишком индивидуальный, а местами даже риторический. Поэтому я чаще предпочитаю ответить на другой вопрос: «Сколько это нам сэкономит?»
Экономить можно что угодно: время, деньги, силы, нервы, да хоть количество кликов или вообще всё сразу. Замечательно, если у нас есть ответ, если его нет — считаем, думаем, пробуем. В конце концов получится грубая оценка профита, и, если её сравнить с теоретическими затратами (понятное дело, что плюс-минус километр), вот и ответ на вопрос «Зачем?».
А давай на примерах?
В одном из моих прошлых проектов был довольно жёсткий регламент по заведению баг-репортов. Это была позиция заказчика и принятые в компании правила, отказаться — не вариант. Только соблюдение всех формальностей при заведении дефекта занимало более 30 минут.
Вишенкой на торте, докидывающей ещё 10—20 минут, было то, что после заведения задачи необходимо было отправить письмо. В нём были продублированы основные моменты дефекта.
Процесс такой: заголовок, ссылка на задачу, критичность, важность для бизнеса, выделить заголовок красным цветом или красным жирным и поставить флаг «Важное» на письмо, если выполнялось определённое условие. При этом список адресатов различался в зависимости от того, случилась ошибка в документации или в коде. Это давало огромную нагрузку на отдел тестирования.
Казалось бы, не нужно всё это. Но у системы был определённый плюс. Благодаря оперативности руководители узнавали о проблеме, мешающей дальнейшей разработке, сразу, как только отдел тестирования обнаруживал критические баги. В свою очередь, отдел разработки быстро разбирался, как починить проблему, и быстро выпускал фиксы.
На мой же вкус, это не только было муторно, но и повышало шанс ошибки из-за человеческого фактора. Чем больше нюансов, тем сложнее удержать их в голове. Через какое-то время эти ошибки начали появляться: кто-то забывал поставить флаг, кто-то не прикреплял ссылку, кто-то путал список адресатов, и начиналась суматоха в других отделах, а кто-то и вовсе «забывал» отправить письмо.
Я же устал составлять, проверять и отправлять такие письма уже на второй день после их введения. Мне казалось, что такую работу можно автоматизировать, ведь она максимально рутинная, и я начал искать способы.
Скрипт всему голова
Я обдумал задачу и понял, что нужен некий скрипт, который будет забирать нужные данные со страницы, красиво расставлять их в поля и составлять готовое письмо. Единственная работа человека — пробежаться глазами, убедиться, что всё в порядке, и нажать «Отправить».
Выбор пал на плагин для хрома Tampermonkey и JavaScript в качестве языка. Так как опыта программирования подобных вещей у меня ещё не было, я решил брать самый популярный вариант на тот момент. Как минимум информации и подсказок, как сделать те или иные вещи, было гораздо больше, чем по другим.
Четыре вечера по пять часов (±20 часов чистого времени), и вуаля — скрипт готов. Когда он был отлажен и проверен в бою, я понял, что это стоило каждой минуты, потраченной на работу. Формирование писем теперь вообще не занимало времени. Получается, что на каждом баге мы экономили 10—20 минут. А теперь посчитаем. Команда тестирования — девять человек. Допустим, каждый из них заводит хотя бы один баг-репорт в сутки. Выходит, мы забираем по 90—180 минут скучной работы (а скучная работа обычно ещё и морально разлагает).
Теоретически затраты на скрипт отбились уже через 6—13 рабочих дней. На практике, естественно быстрее, так как количество багов на старте проекта всегда «чуть больше» одного в день.
И это только экономия по времени. Сколько было сохранено нервных клеток у отдела QA — даже не представляю, как посчитать. Коллеги с большой радостью встретили инструмент и использовали его до самого завершения проекта.
Где взять такой скрипт
Если у вас тоже есть подобная проблема и нужно «переслать задачу по почте», прикладываю скрипт, который может облегчить вам жизнь. Естественно, он требует доработки напильником под конкретный проект и его кастомные поля. После установки на страницах Jira в контекстном меню правой кнопки мыши появляется кнопка скрипта. По клику на неë скрипт формирует объект с расширением .eml, который уже можно открывать в почтовике и отправлять.
Письмо с данными задачи из Jira.js
// ==UserScript==
// @name (Сюда вписываем название, выводимое в контекстное меню Tampermonkey)
// @namespace local
// @version 0.1
// @description (Описание действия)
// @author Vasilev Sergey
// @icon https://www.google.com/s2/favicons?domain=google.com
// @match https://(адрес вашей Jira)/*
// @run-at context-menu
// ==/UserScript==
(function sendemailBug() {
'use strict';
//Получаем значения полей из Jira и сразу приводим их к текстовому значению на всякий случай
//Ссылка на задачу
var issue_link = document.getElementById('key-val');
var text_issue_link = issue_link.toString();
//Номер задачи
var issue_number = document.getElementById('key-val').innerText;
var text_issue_number = issue_number.toString();
//Название задачи
var summary = document.getElementById('summary-val').innerText;
var text_summary = summary.toString();
//Кастомные поля, на случай если в вашем проекте они есть.
//Поле Severity
var severity = document.getElementById('customfield_10106-val').innerText;
var text_severity = severity.toString();
//Поле Absolute priority
var absolute_priority = document.getElementById('priority-val').innerText;
var text_absolute_priority = absolute_priority.toString();
//Поле Sprint
var sprint = document.getElementById('customfield_10105-val').innerText;
var text_sprint = sprint.toString();
// Указываем адресатов, кому посылаем письмо
let emailTo = 'test@test.ru';
//Указываем тех, кого ставим в копию
let emailToCopy = 'test1@test.ru; test2@test.ru; test3@test.ru;';
//Формируем тему письма
let emailSubject = "[Defect Notification]::"+ String(text_issue_number) + "::" + String(text_summary);
//Вычисляем какого цвета у нас будет приоритет
let severity_color = text_severity;
if (text_severity == "Minor") {severity_color = text_severity}
if (text_severity == "Average") {severity_color = text_severity}
if (text_severity == "Major") {severity_color = "<b>" + text_severity + "</b>"}
if (text_severity == "Critical") {severity_color = `<b><font color = "red">` + text_severity + "</font></b>"}
if (text_severity == "Blocker") {severity_color = `<b><font color = "red">` + text_severity.toUpperCase() + "</font></b>"}
//Собираем html объект для отрисовки таблицы в письме и подставляем в таблицу значения полей
let htmlDocument = `
<html
<head>
<style>
table {
border: 1px solid silver; /* Рамка вокруг таблицы */
border-collapse: collapse; /* Отображать только одинарные линии */
font-size: 12pt;
font-family: Segoe UI
}
th {
text-align: left; /* Выравнивание по левому краю */
border: 1px solid silver;
}
td {
padding: 8px; /* Поля вокруг содержимого ячеек */
border: 1px solid silver;
}
</style>
</head>
<body>
Здравствуйте, коллеги!
<table>
<tr>
<td><b>Severity</b></td>
<td>`+ severity_color +`</td>
</tr>
<tr>
<td><b>Absolute priority</b></td>
<td>` + text_absolute_priority + `</td>
</tr>
<tr>
<td><b>Issue link</b></td>
<td><a href="`+ issue_link +`">`+ text_issue_number +`</a></td>
</tr>
<tr>
<td><b>Summary</b></td>
<td>`+ text_summary +`</td>
</tr>
<tr>
<td><b>Sprint</b></td>
<td>`+ text_sprint +`</td>
</tr>
</table>
</body>
</html>`;
//Создаём само письмо, добавляя отправителей, тему письма, таблицу со значениями
let emlContent = "data:message/rfc822 eml;charset=UTF-8,";
emlContent += 'To: '+emailTo+'\n';
emlContent += 'Subject: '+emailSubject+'\n';
emlContent += 'CC: '+emailToCopy+'\n';
//Если абсолютный приоритет бага выше 850 - ставим высокий приоритет письму
if (absolute_priority >= 850) {emlContent += 'X-Priority: 1 (Highest)\n'};
emlContent += 'X-Unsent: 1 \n';
emlContent += 'Content-Type: text/html; charset=UTF-8 \n';
emlContent += '\n';
emlContent += htmlDocument;
//Создаём файл EML и скачиваем его
var encodedUri = encodeURI(emlContent); //декодируем URI
var a = document.createElement('a'); //создаём ссылку на документ
var linkText = document.createTextNode("fileLink");
a.appendChild(linkText);
a.href = encodedUri;
a.id = 'fileLink';
a.download = text_issue_number + '.eml';
a.style = "display:none;"; //делаем ссылку невидимой
document.body.appendChild(a);
document.getElementById('fileLink').click(); //кликаем по ссылке для скачивания
}
)();
Что насчёт «Как?»
Итак, в первой части статьи мы разобрались с ответом на вопрос: «Зачем?» И даже частично затронули «Как?»
Сейчас будет ода нашему внутреннему продукту, но это не реклама и не продажа инструмента. Просто хочу поделиться тем, какие инструменты могут упростить вам жизнь.
Перейдя работать в M2, с удивлением обнаружил, что здесь тоже используется решение, подобное тому, что я придумал в прошлом проекте.
Вместо того чтобы использовать сторонний плагин со вставленным кодом, коллеги сделали собственное клиент-серверное расширение для браузера Chrome, что позволило значительно расширить доступный функционал. А ещё его назвали очень дружественно — M2bro.
Одна из вкладок плагина — «Заполнение форм». Это позволяет быстрее и удобнее заводить задачи в трекере на страницах Jira: один клик — и в задаче появляется список пунктов, который нужно заполнить для user-story. В случае баг-репорта это отдельные рамки с тестовыми данными, шагами воспроизведения, ожидаемым и фактическим результатами. Вся эта прелесть выглядит вот так:
Ещё больше пользы эта вкладка приносит на самих окружениях разработки. Наша компания занимается недвижимостью, и пользовательский путь в продуктах состоит из большого количества полей и данных. Например, параметры объекта (адрес, кадастровый номер, площадь, собственники), данные об участниках (начиная с номера паспорта, заканчивая контактами и доверенностями). В общем, заполняется вообще всё, что может понадобиться при составлении договора.
Чтобы пройти этот тернистый путь при тестировании, приходится вводить крайне много тестовых данных. Даже если нужно всего лишь проверить, что кнопка в конце пути отработала нормально.
Вкладка автозаполнялки позволяет упростить этот процесс. Каждая команда сама пишет уникальные сценарии или учётные записи для вкладок своих продуктов. То есть не получится, на странице сделки ткнуть в кнопку «Заполнение объекта недвижимости» — кнопки просто не будет. При нажатии же на нужную кнопку в соответствующие поля вбиваются данные. Остаётся только нажать «Далее». Прохождение пользовательского пути сокращается в несколько раз, а перемещаться по продукту становится удобнее. Бонусом идёт то, что, если вдруг понадобилось пройти продукт другой команды, необязательно звать кого-то из коллег, чтобы узнать, как и что правильно заполнять.
Понятное дело, что валидация не даст ввести бред, но гораздо проще открыть M2bro и нажать одну кнопку, чтобы система ввела нужные данные в правильные поля, чем пытаться угадать, по какой логике заполняется очередная маска расчётного счёта у физического лица.
Ещё один мощный аспект M2bro — вкладка авторизации. Она позволяет зайти в систему под одной из пары десятков ролей, не заморачиваясь над вспоминанием пары «логин/пароль».
M2bro сам разлогинивает пользователя, определяет, какое окружение открыто на вкладке, и сам производит авторизацию под нужным аккаунтом. Попутно перезагружает страницу, оставаясь на ней, а не перекидывая на главную. Благодаря этому операция, обычно занимающая 30—60 секунд, сокращается до двух кликов. Если принять во внимание, что иногда при тестировании нужно посмотреть, как сделку видят не два человека, а, например, шесть (покупатель, продавец, риелтор, сотрудник банка, сотрудник поддержки M2 и бухгалтер), представьте, сколько времени бы заняло перезаходить за каждого из них и возвращаться к нужной странице системы.
Ещё эта функция позволяет быстрее погружать новых сотрудников или коллег из смежных команд. Вместо классического «скидывания» страницы с тестовыми учётными записями и попыток объяснить, какая из них нужна, всё сводится к фразе «Зайди в M2bro под бухгалтером, там появится нужная тебе кнопка». В общем, это стало настолько удобно, что я уже не представляю своей работы без этой функции.
Сейчас коллеги пошли дальше и добавили тестировщику ещё больше комфорта — кнопку «Сессия». При нажатии на неё в буфер обмена копируется url для имперсонализации.
Переход по этой ссылке переносит другого человека сразу на нужную страницу под нужной учёткой. Больше не нужно объяснять громоздкими фразами вроде: «Вот если зайти в меню „Конструктор сделки“ под сотрудником банка и перейти в раздел „Сервис безопасных расчётов“, то мы не увидим кнопки „Защита сделки“, хотя должны. И это баг». Теперь любой может сам прийти на место происшествия, взять ссылку с сессией и отправить коллеге с комментарием: «Здесь нет защиты сделки, а должна быть».
Круто, что в разработке расширения участвуют все желающие, а бизнес охотно берёт в спринт задачи по развитию M2bro — так наше расширение постоянно поддерживается в актуальном виде и пополняется новыми сценариями.
Вместо заключения
Конечно, это далеко не все инструменты, которые в нашей компании используются для удобства, но, пожалуй, один из самых часто используемых мной. Я даже представить не могу, сколько времени и нервов он позволил мне сохранить. Ведь даже очевидные решения не всегда приходят на ум сразу.
И я специально описал в статье два подхода к решению одной и той же задачи «Повысить качество и удобство работы».
Один — костыльно-прототипный. Быстро, дёшево, сердито. Его вы можете прямо сейчас взять и внедрить в свои будни. Второй — более профессиональный, мощный, но дорогой. На такой, конечно, нужно решиться.
Какой из них использовать, зависит от проекта и имеющихся ресурсов. Возможно, их можно комбинировать.
Если у вас на проекте есть подобные инструменты, расскажите о них в комментариях или дайте ссылку на статью. Мне всегда интересно, какие программы делают работу коллег комфортнее, с большим интересом почитаю комментарии и почерпну для себя что-то новое.
Обычно в самом конце принято подводить какие-то выводы и итоги. Но я бы хотел выразить благодарность. В первую очередь — авторам нашего расширения и идеи сделать работу комфортнее. Учебный проект превратился в незаменимого помощника, а огромная благодарность улетает техлиду Мише Березину и QA-инженеру Стасу Перепелкину!
Ребята, спасибо вам за M2bro!