Как я писал на Groovy и что за зверь такой GEB… (часть 1)

Tymur Kubai
4 min readJun 16, 2017

--

Очередное тестовое.

Вышли на меня через LinkedIn выслали тестовое, про его эстимацию я уже писал(и всеравно я занизил сроки, рукалицо). Вакансия от конторы agileengine, на случай если ссылка помрет приведу ниже описание.

Необходимые навыки

● 2+ year of experience as a Software Quality Assurance Engineer;
● At least 1 year experience with Java or Groovy/Grails and some Automation framework like Selenium Web Driver / Geb / Geb and Spock, Page Object Model;
● Experience in analyzing business requirements, recommending test strategies, and writing test plans and/or requirements;
● The ability to analyze business needs and conceive, design, and develop innovative and automated test solutions;
● Excellent verbal and written communication skills

Будет плюсом

● Knowledge of BDD test practices

Анализ тестового

Нужно было покрыть тестами несколько api запросов у twitter и после этого покрыть аналогичную функциональность через ui.

Сразу даю ссылку на готовое тестовое задание на github. И последняя стока из ТЗ:

Tests should be written using Java + Selenium WebDriver (ideally to be done with Geb)

Судя по вакансии чувакам нужен не Java Automation, а Groovy. Темболее Geb как раз обертка над селениумом написанная на Groovy. А джавистов они расматривают только как альтернартиву ибо грувистов мало. Выгодней всего писать все тесты(api + ui) на groovy, а для ui использовать тот самый Geb.

Почему выгодно?

Всегда выбирайте самый трудный путь — там вы не встретите конкурентов. Шарль де Голль.

Заодно groovy и spock подучу.

API тесты

Изначально мысль была покрывать апи твиттера использую связку rest-assured и десериализация json через jackson.

Но погуглив я гашел просто отличную либу для работы с twitter которая делает все хорошие вещи за меня. Особенно избавляет от гемора OAuth.

В итоге тесты получились очень короткими и удобочитаемыми.

Отдельно няшная штука это SPOCK.

Особенно доставило, то как реализован отлов ожидаемых exception в тесте.

Если в jUnit/TestNG это делается через параметр анотации.

@Test(expectedExceptions = WebDriverException.class)

Что позволяет только нормально проверить класс исключения. А если хочешь узнать текст или еще какие штуки которые в исключении прилетели, то нужно делать try-catch, в блоке try реализовывать asserts, a после еще и throw это же исключения что бы на уровне метода его словило и завилидировало как правильно поведение.

В spock же с этим красота:

then:

def e = thrown(TwitterException)

e.getStatusCode() == errCode

e.getErrorMessage() == errMs

в блоке then(а он у нас отвечает за валидацию) ты ловишь исключение и делаешь что с ним хочешь.

Зависимые тесты:

В тестовом задание прослеживается цепочка действий.

Добавить твит -> Попытаться продублировать твит -> Удалить твит.

Поэтому пришлось сделать тесты взаимозависимыми.

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

Вот тут немного хитрее ситуация. Если в TestNG через аннотацию можно зависить от методов/групп(перечисленных через запятую):

@Test(dependsOnMethods = “test1, test2”)

@Test(dependsOnGroups = “group1, group2”)

В spock то есть похожая возможность, можно пометить что тесты зависят друг от друга. Но в данному случае ты ставишь аннотацию @Stepwise над всем классом и тесты зависят друг по их расположения в коде. Что впринципе ведет к более независимому тестовому дизайну. Тесты которые идут в одну цепочу должны лежать в одном отдельном классе.

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

Под “независимым тестовым дизайном” я иммел ввиду что Spock располагает к тому что бы под конкретную фичу выделялся пакет и внутри него уже класс/классы ее покрывающие. Что обычно стоит делать и jUnit/TestNG

Короче палка о двух концах с аннотацией @Stepwise. Пример можно посмотреть либо в моём репозитории указано выше либо в офф примерах спока. Но хорошо что такая возможность есть :)

Параметризация(DDT — Data Driven Testing)

Начну пожалуй с TestNG. В основном тесты которые раняться несколько раз будут раниться с помощью @DataProvider. Этой аннотацией помечаються методы которые будут обеспечивать тест данными. В параметре аннотации @Test указывается какой DataProvider будет использован.

@DataProvider
public static Object[][] multiLetter() {
return new Object[][]{
{5, "Z"},
{15, "Z"},
};
}

@Test(dataProvider = "multiLetter")
public void test1(int count, String letter){

Для spock же аналогие датапровайдеру служит блок where:

where — ответсвенен за данные поставляемые в тест. И может быть реализован в виде таблицы:

where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0

Либо в виде data pipes:

a << [1, 7, 0]
b << [3, 4, 0]
c << [3, 7, 0]

Таблицы менее гибки, так как они статичны, а вот с data pipes можно добиться той же динамики которую можно получить от DataProvider.

Я какраз так использовал data pipes для написания api тестов для твиттера.

where:
st << twitter.getHomeTimeline()
epochExp << epoch
retweetExp << retweetCount
textExp << textOfTweets

Список твитов в ленте я получаю посредлством запроса twitter.getHomeTimeline(), а теоретически он может вернуть коллекцию любого размера. Ну я то знаю что коллекция будет состоять из двух эллементов, но таблице это объяснить трудно, а вот data pipe такую штуку хавает свободно.

Где epoch, retweetCount, textOfTweets являються просто коллекциями из двух элементов с ожидаемыми результатами.

Погуглил оказывается для jUnit есть кастомный раннер аналогичный DataProvider аки TestNG

На этом пока все, перегруз инфы в одной статье то же не круто.

Про Geb будет в следующей части.

--

--

No responses yet