Снова в школу: как обучить ручных тестировщиков разбираться с автотестами

Четыре из пяти соискателей-QA хотят научиться работать с автотестами. Не все компании могут осуществить такие желания ручных тестировщиков в рабочее время. Wrike провёл школу автоматизации для сотрудников и реализовал это желание для многих. Я в этой школе участвовал именно как ученик-QA.

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

Опыт Wrike в организации школы


Когда необходимость в школе автоматизации стала ясна, её организация легла на Стаса Давыдова, технического лида автоматизации. Кто как не он может объяснить, зачем придумали эту инициативу, достигли ли результатов и не жалеют ли о потраченном времени? Дадим ему слово:

— В 2016 году мы написали новый фреймворк для автотестов и сделали его таким, что тесты стало писать легко: появились нормальные степы, структура стала в разы более понятной. У нас появилась идея: нужно привлечь к написанию новых тестов всех, кто пожелает, а чтобы проще было вникнуть, создали серию лекций. Мы коллективно придумали план тем, каждый из будущих лекторов взял себе одну и подготовил по ней доклад.

— Каковы были сложности у учеников?

— В основном, конечно, архитектура. Было много вопросов по структуре наших тестов. В фидбеке много писали на эту тему и нам пришлось проводить дополнительные лекции, чтобы объяснить подробнее.

— Окупилась ли школа?

— Да, однозначно. Благодаря ей к написанию тестов привлекли кучу людей, и, в среднем по больнице, все стали лучше понимать, что такое автотесты, как их пишут и как они запускаются. Также снизилась нагрузка на автоматизаторов: нам теперь поступает в разы меньше запросов на помощь с разбором тестов, так как тестировщики и разработчики стали с этим справляться сами практически во всех ситуациях. Ну и несколько внутренних плюсов для отдела: приобрели опыт в презентациях и лекциях, благодаря чему некоторые автоматизаторы уже успели сделать доклады на конференциях, а также получили мощный набор видео и презентаций для онбординга новичков.

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

В общем, влияние на работу команд — однозначно положительное. Быть может, коллеги читающих эту статью тоже задумываются о проведении чего-то подобного? Тогда совет будет простой: оно того стоит, если автотесты для вас в приоритете. Далее поговорим про более сложный вопрос: как это всё организовать максимально правильно, чтобы затраты всех сторон были минимальны, а выхлоп — максимален.

Советы по организации


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

Шаг 0. Создаём словарь


Конечно, этот шаг нужен не только для QA. Тем не менее, я хочу его проговорить в явном виде: кодовая база автоматизации должна храниться в читаемом виде. Языки программирования — не в последнюю очередь именно языки, и с этого можно будет начинать погружение.



Перед вами скриншот тасквью с названиями элементов. Представим, что вы занимаетесь тестированием тасквью как чёрного ящика и в жизни не видели Selenium. Что делает этот код?



(Спойлер — через рест удаляется таск от имени админа, а потом мы смотрим, что в стриме осталась об этом запись.)

Уже один этот шаг позволяет сблизить языки QAA и QA. Автоматизаторам проще объяснять итог прогона, ручным тестировщикам приходится тратить меньше сил на составление кейсов: их можно делать менее подробными. Все же друг друга понимают. Мы получили выигрыш ещё до того, как началось непосредственно обучение.

Шаг 1. Повторяем фразы


Продолжим параллель с языком. Когда мы учимся говорить в детском возрасте, мы не идём от этимологии и семантики. Мы повторяем «мама», «купи игрушку», но не лезем сразу в праиндоевропейские корни этих слов. Так и тут: нет смысла нырять в самую глубину технических особенностей работы автотестов, не попробовав написать что-то рабочее.
Звучит несколько контринтуитивно, но зато работает.

На первом занятии стоит дать базис по тому, как писать непосредственно автотесты. Помогаем настроить среду разработки (в моём случае — Intellij IDEA), объясняем тот минимум правил языка, который необходим для написания ещё одного метода в существующем классе с использованием имеющихся шагов. Пишем с ними один-два теста и даём домашнее задание, которое я бы оформил так: ветка, отведённая от мастера, но в ней удалено несколько тестов. Остались только их описания. Просим тестировщиков восстановить эти тесты (не через show diff, конечно же).

По итогам тот, кто всё послушал и сделал, сможет:

  1. научиться работать с интерфейсом среды разработки: создание веток, хоткеи, коммиты и пуши;
  2. освоить азы структуры языка и классов: куда вставлять инжекты, а куда импорты, зачем нужны аннотации и что вообще там встречаются за символы, кроме шагов;
  3. понять разницу между действием, ожиданием и проверкой, где что использовать;
  4. заметить отличие автотестов и ручных проверок: в автотестах можно дёрнуть тот или иной хендлер вместо выполнения действий через интерфейс. Например, отправить комментарий напрямую на бекенд вместо открытия тасквью, выделения инпута, набора текста и нажатия кнопки Send;
  5. сформулировать вопросы, на которые будут даны ответы на следующем шаге.

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

Идеально будет, если в это время автоматизатор из команды QA повесит на него задачу с написанием парочки тестов на бою и разрешит подкоммититься в свою ветку.

Чего давать не стоит:

  1. более углублённые знания функционала среды разработки и самого языка программирования, которые будут нужны лишь при самостоятельной работе с ветками. Не запомнится, придётся объяснять дважды-трижды, а мы дорожим временем автоматизаторов, так? Примеры: решение конфликтов, добавление файлов в гит, создание классов с нуля, работа с зависимостями;
  2. всё, что связано с xpath. Серьёзно. Про него надо рассказывать отдельно, один раз и очень концентрированно.

Шаг 2. Присматриваемся к грамматике


Давайте вспомним скриншот с тасквью из шага №0. У нас есть степ с названием checkCommentWithTextExists. Наш тестировщик уже понимает, что этот степ делает и можно заглянуть внутрь шага и немного его декомпозировать.

А внутри у нас следующее:

onCommentBlock(userName).comment(expectedText).should(displayed());

Где onCommentBlock — это

onCommonStreamPanel().commentBlock(userName);

Теперь учим говорить не «купи игрушку», а «купи игрушку из магазина Детский мир, стоящую в синем шкафу на третьей полке сверху». Нужно объяснить, что мы указываем на элемент последовательно, от более крупных элементов (стрим -> блок с комментариями от определённого человека -> та часть этого блока, где сидит заданный текст).

Нет, всё ещё не время рассказывать про xpath. Только упомянуть вкратце, что все эти указания ими описываются и наследование идёт через них. Зато нужно рассказать про все эти метчеры и вейтеры, они относятся именно к этому шагу и необходимы для понимания происходящего. Но не перегружайте: более сложные ассёрты ваш студент сможет изучить сам и позднее. Скорее всего, должно хватить should, waitUntil, displayed();, exist();, not();.

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

Дополнительно, если у команды тестировщика в работе есть не только новые фичи, но и некоторые багфиксы, можно попросить его написать сразу же тесты на эти баги и зарелизить. Скорее всего, все элементы уже описаны, может не хватать лишь пары-тройки степов. Это будет идеальной тренировкой.

Шаг 3. Полное погружение


Настолько полное, насколько это возможно для тестировщика, который собирается продолжать выполнять свои прямые обязанности. Наконец-то нужно рассказать про xpath.

Сначала даём понять, что все эти onCommentBlock и comment описываются именно ими.



Итого:

"//div[contains(@class, ‘stream-panel’)]//a[contains(@class,'author') and text()='{{ userName }}’]//div[contains(@class,'change-wrapper') and contains(.,'{{ text }}’)]"

Порядок рассказа очень важен. Сначала берём любой существующий xpath и показываем, как во вкладке elements находится один и только один элемент. Далее, рассказываем про структуру: когда нужно использовать WebElement, а когда нужно создать отдельный файл для нового элемента. Это позволит лучше понять наследование.

Нужно явно проговорить, что отдельный элемент — это всё тасквью, он содержит дочерний элемент — весь стрим, который содержит дочерний элемент — отдельный комментарий, и т.д. Дочерние элементы — внутри родительских как на странице, так и в структуре фреймворка автотестов.

На этом моменте аудитория должна была уже твёрдо понять, как они наследуются и что можно ввести после точки у onCommentBlock. В этот момент объясняем все операторы: /, //, ., [] и прочее. В нагрузку докидываем знания про использование @class и прочих необходимых вещей.



Слушатели должны понять как переводить xpath подобным образом. Чтобы закрепить — правильно, домашка. Удаляем описания элементов, пусть восстановят работу тестов.

Почему именно такой путь?


Мы не должны перегрузить человека сложными знаниями, но должны объяснить всё и сразу, а это непростая дилемма. Данный путь позволит нам сначала заставить слушателей задаваться вопросами и не понимать что-то и отвечать на них уже в следующий момент. Если рассказать про всю архитектуру, то к моменту разбора темы степов или xpath важнейшие части оной уже забудутся из-за своей непонятности.

Тем не менее, кто-то из вас наверняка сможет поделиться опытом, как можно оптимизировать процесс ещё сильнее. С удовольствием прочту в комментариях подобные предложения!
Wrike
138,93
Wrike делает совместную работу над проектами проще
Поделиться публикацией

Комментарии 14

    +1
    У нас тесты разделены по уровням:
    1. Тестовый уровень
    2. Бизнес логика
    3. Низкий уровень

    Соответственно верхний уровень отвечает только за тестовый сценарий (тестовые данные, последовательность шагов, проверки). Этот уровень вызывает готовые блоки бизнес логики. Начинающие тестировщики автоматизаторы работают здесь.

    Бизнес уровень — реализует продуктовую логику (например логин, добавление комментария, получение списка комментариев). Те кто хорошо разобрался с тестовым уровнем продолжают работать здесь. Этот уровень вызывает низкий уровень оберток.

    Низкий уровень — обертки над Selenium, RestClient и прочее — необходимое для тестов. Здесь соответственно уже работают эксперты.

    За счет такого разделения получается довольно быстро обучить тестировщиков автоматизации. Само собой на Confluence имеются подробные статьи по типовым задачам.
      0
      Зачем нужны эти *Steps в именовании PO(page object)? Имхо loginPage, commonStreamPage или вообще без Page было бы намного понятней.
      .should(displayed()); можно заменить .shouldBe(displayed()); — будет намного приятней при чтении кода.
      onCommonStreamPanel().commentBlock(userName); — незнакомому человеку(мне в данном случае) вообще непонятно что здесь просиходит. Может commentBlockAs(userName)? Туда же loginByEntity — попробуй объясни мануальщику что за сущность. loginaAs() мне кажется более понятным.
      Xpath — зачем грузить мануальщиков такими громоздкими конструкциями? Насколько я знаю вы используете Selenide, а там есть намного удобные методы поиска элементов вроде .closest(), parent(), filter(), поиск внутри коллекции $$, chaining и прочие. Ну и опять же — почему просто не добавить уникальные id для элементов на странице?
      У нас в компании гораздо проще — у нас нет мануальщиков вообще.
      P.S. Видел что Wrike открыл офис в Праге — так что vítejte v Praze :)
        0
        Xpath — зачем грузить мануальщиков такими громоздкими конструкциями?.. намного удобные методы поиска элементов вроде .closest(), parent(), filter(), поиск внутри коллекции $$, chaining и прочие

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

        почему просто не добавить уникальные id для элементов на странице?

        Если это не нужно для работы приложения, адекватна ли польза зашиванию тесто-специфичного контента? Не говоря уже о растущей сложности логики по генерации id для динамических элементов.
          +1
          Если это не нужно для работы приложения, адекватна ли польза зашиванию тесто-специфичного контента? Не говоря уже о растущей сложности логики по генерации id для динамических элементов.

          Но ведь это одна из первых best practices так сказать. И не нужно городить эти километровые xpath. Особо умные тестировщики даже сами могут ходить в репозиторий с кодом фронтэнда и добавлять себе ID типа data-test-id. Ну и потом можно одним из плагинов для Babel, например, выпилить эти айди перед деплоем на продакшн сервер.
            0
            Бест практис в современном фронт-енде — избегать id.
            Внедрять тестовую оснастку в основной код приложения — это плохая практика. Больше бессмысленного шума в коде!
            Делать это ниндзя-коммитами от тестеров — тоже плохая практика. Нужно больше конфликтов и тестов, прибитых id-гвоздями, за консистентностью и непротиворечивостью которых нужно отдльно следить!
            Выпиливать тестовую оснастку на этапе сборки — это вообще чудесно!
              0
              То-есть вы за то чтобы автоматизаторы страдали и писали километровые хрупкие xpath тратя уйму времени на починку упавших тестов(добавили кнопочку на форму и вот тот xpath из статьи стал невалиден)? Может вам хотя бы классы по душе, раз ID это плохо?
                0
                Представте БЭМ, где под каждый блок свой PageObject, тогда навигация будет максимум трехступенчатой (родитель-блок-элемент), а тесты будут обваливаться только при серьезном рефакторинге блока, что закономерно и не больно.

                добавили кнопочку на форму и вот тот xpath из статьи стал невалиден

                Просто добавление кнопки рядом не сломает селектор.

                Может вам хотя бы классы по душе, раз ID это плохо?

                Ну куда ж без классов?) Главное, чтобы не автотестеры их расставляли.
                  0
                  А можно поинтересоваться — вы как-то связаны с автоматизацией тестирования UI или просто «мимокрокодил»?
                    0
                    Вы хотите перейти на личности или познакомиться?
                      0
                      Скорее понять откуда растут корни ваших умозаключений.
                        0
                        Я бы предпочел обсуждать проблемы и решения в IT, а не прикладную психологию.
                        Хорошего вам дня!
                          0
                          Это и есть обсуждение проблем и их решений. Проблема в том что вы явно далеки от автоматизации тестирования. Ну да ладно, хорошего и вам дня.
          0
          Приходите поболтать www.meetup.com/WrikeTechClub/events/265526316
            +1
            Обязательно приду, спасибо за приглашение.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое