19 декабря 2017

Эволюция тестировщика-автоматизатора

Статья Станислава Башкирцева будет интересной как уже практикующим тестировщикам, так и тем, кто только-только входит в профессию. Предлагаем вашему вниманию перевод нашего тестировщика Анастасии.

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

Homo habilis: смешанные тест-кейсы и инструменты

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

public void clickSignUpLinkTest(String appURL) {
  driver.get(appURL);
  driver.findElement(By.xpath("//a[@href='/jcommune/user/new']")).click();
  driver.findElement(By.id("password")).clear();
  driver.findElement(By.id("passwordConfirm")).clear();
  driver.findElement(By.id("password")).sendKeys(acceptedPassword);
  driver.findElement(By.id("passwordConfirm")).sendKeys(acceptedPassword);
  driver.findElement(By.xpath("//button[@type='submit']")).click();
  assertEquals(driver.getCurrentUrl(), appURL);
}

Обычно будущие автоматизаторы задерживаются на этом этапе не более нескольких месяцев, потому что он, очевидно, довольно скучен.

Плюсы:

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

Минусы:

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

Homo erectus: использование Page Object’ов

Мы начинаем понимать, что селекторы следует рассматривать как отдельные объекты, чтобы больше не допустить беспорядка, созданного на предыдущем этапе. Теперь у нас появился класс Page,

public class SignInPage {
  @FindBy(id = "j_username")
  WebElement usernameField;

  public WebElement getUsernameField() { return usernameField; }
}

который мы используем при написании тест-кейсов:

public void usernameValidationTest(String username) {
  signInPage.getUsernameField().sendKeys(username);
  signInPage.getSubmitButton().click();
  assertExistBySelector(driver, signInPage.errorMessageSel);
}

Теперь наши тест-кейсы не засоряются мелочами вроде селекторов. Некоторые действия, например, click(), также могут быть перенесены в Page Object.

Плюсы:

  • теперь стало понятнее, что именно проверяет тест-кейс на каждом шаге;
  • если внесены какие-то изменения в селекторы, нам не придется переписывать сами тест-кейсы.

Минусы:

  • тесты всё ещё ориентированы на конкретную страницу, а значит, уязвимы к изменениям в ней. Что, если раньше мы переходили на страницу Б со страницы А, но после нескольких изменений стали переходить на страницу Б со страницы В? Нам придётся редактировать и тесты, и Page Object, в то время как тесты, валидирующие то или иное поле на странице, по сути, не меняются;
  • нам придётся писать несколько тестов для одного результата, достигнутого разными способами. Представим, что страницы сайта разработаны адаптивно: в таком случае одни и те же объекты будут выглядеть по-разному на больших и маленьких экранах. Мы будем создавать несколько тестов, учитывая разные размеры экрана, в то время как сами действия и проверяемый функционал остаются неизменными (привет, лишняя работа!);
  • тесты по-прежнему могут быть громоздкими (это напрямую зависит от сложности сценария использования, проверяемого ими).

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

Homo antecessor: бизнес-ориентированные тест-кейсы

Так как теперь мы выяснили, что можно улучшить в тест-кейсах, ориентированных на страницу, попробуем применить это на практике. Нам всё ещё понадобится Page Object’ы:

public class SignInPage {
  @FindBy(id = "j_username")
  WebElement usernameField;

  public WebElement getUsernameField() { return usernameField; }
}

Но теперь в тест-кейсах мы будем использовать бизнес-логику, не привязанную к конкретной странице:

public void usernameAsSpace_shouldFail() throws Exception {
  UserForRegistration user = UserForRegistration.withUsername(" ");
  Users.signUp(user);
}

Теперь добавим ещё один слой, внедряющий бизнес-операции в тесты:

public static User signUp(UserForRegistration userForRegistration) throws ValidationException {
  mainPage.logOutIfLoggedIn(driver);
  openAndFillSignUpDialog(userForRegistration);
  checkFormValidation(signUpPage.getErrorFormElements());
  signUpPage.closeRegistrationWasSuccessfulDialog();
  return userForRegistration;
}

Плюсы:

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

Минусы:

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

  • прохождение тестов занимает много времени. После того, как мы оптимизировали и запустили некоторые тесты для JTalks, они по-прежнему выполнялись около 5 часов. Обычно это не проблема, потому что постоянно появляются новые задачи, и тестировщикам хватает работы, однако это может доставить неудобства в некоторых ситуациях (например, когда надо срочно протестировать и отдать в релиз хотфикс);
  • из-за большого количества тестов в рамках одного прогона (у нас есть по 100 тестов в 4 браузерах и 300 тестов без привязки к окружению = 700 тестов итого), часть из них будет падать в любом случае. В примере с JTalks это происходило нечасто, но на несколько дюжин успешных тестов всё же приходился один “fail”. Прежде чем мы поделили их на тесты для конкретных браузеров и тесты без привязки к окружению, они падали намного чаще, но даже после оптимизации “фейлы” не исчезли насовсем. Я спрашивал одного из разработчиков Selenium, случалось ли у них, что автотесты (особенно те, что проверяют корректность работы Selenium) падали без причин, и, как выяснилось, это происходило, пусть и довольно редко. Кроме того, я уверен, что небольшое количество упавших тестов обусловлено тем, что страницы, использованные командой при тестировании, были достаточно простыми с точки зрения логики. В реальной жизни ситуация была бы несколько хуже.

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

Testing automation translation by Noveo

Homo sapiens: пишем компонентные тесты

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

  • системных тестов должно быть немного;
  • профит!

Что я имею в виду:

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

Плюсы:

  • компонентные тесты намного быстрее системных. Как только мы снизим количество системных тестов, суммарное время выполнения всех сценариев станет на порядок меньше;
  • разработчики могут запускать компонентные тесты локально на своих устройствах и давать очень быстрый фидбек;
  • нам не придётся сильно заморачиваться со стабильностью: так как системных тестов будет мало, количество спонтанных “фейлов” значительно снизится.

Как внедрять в работу компонентные тесты?

Разные фреймворки могут потребовать разных программных средств. Вот несколько примеров:

  • приложения, написанные с помощью фреймворка Spring MVC, могут использовать фреймворк MockMvc для эмулирования запросов пользователей;
  • приложения, использующие протокол в рамках HTTP (например, REST/SOAP), могут использовать такие библиотеки, как REST-assured, Restito. Кроме того, фреймворки вроде RestEasy позволяют вызывать методы напрямую [doc]  (не используя HTTP);
  • те, кто используют такие системы как IBM MQ, Tibco EMS, Solace, могут использовать ActiveMQ как альтернативу компонентным тестам. В любом случае разработчики, использующие эти системы, пишут компонентные тесты, так что они знают, как это делать. При использовании фреймворков Apache Camel или Spring Integration мы также можем воспользоваться их возможностями для тестирования.

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

Для таких тестов предпочтительно использовать базы данных с технологией  In-Memory. Существуют инструменты, помогающие работать с ними: объектно-реляционные отображения и базы данных, имитирующие другие БД (HSQLDB, TimesTen).

Должны ли тестировщики-автоматизаторы принимать участие в процессе?

Моя точка зрения такова: все тесты на любом уровне должны управляться разработчиками. Ручные тестировщики могут помочь придумывать тест-кейсы и обозревать существующие тесты (для этого нам необходимо писать их так, чтобы другой человек мог их прочесть) или даже сами писать тест-кейсы, если разработчики могут предоставить лёгкий в использовании бизнес-ориентированный фреймворк для работы. Автоматизаторы стоят компании дороже, но зачастую не могут внедрить бизнес-слои тестов без помощи разработчиков.

Тестировщики-автоматизаторы могут работать с инструментами вроде Selenium, но результаты их работы должны внимательно проверяться разработчиками.

Подводя итоги

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

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

Testing automation Translation by Noveo

 

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Читайте в нашем блоге

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: