Привет!
Вы когда-нибудь задумывались, а как бы вы стали тестировать GMail, если б были разработчиком Google? Это отличное упражнение для тестировщика, непременно попробуйте!
Тестирование GMail нетривиально, т.к. в нём на каждый чих используется Ajax, грузится долго, всё генерируется динамически и нет разумных селекторов/айдишек. Замучаешься везде проставлять wait!
Проект GMail test
Но счастье возможно! В серии Selenide Examples мы представляем проект на гитхабе, в котором написан тест для GMail. Он проверяет содержимое инбокса и пишет новое письмо. Причём ещё и делает “Undo”, редактирует и снова посылает. И в конце ждёт, пока кнопка “Undo” пропадёт.
Видео
И тут даже есть короткое видео, демонстрирующее, как это работает:
Вскрытие покажет
Вот сам проект на гитхабе: https://github.com/selenide-examples/gmail
Давайте рассмотрим некоторые моменты подробнее.
Настройка
Перед запуском тестов надо увеличить таймаут, т.к. в GMail часто элементы грузятся дольше 4 секунд, которые прописаны в Selenide по умолчанию. Поставим 10 секунд. Хотя на некоторых конференциях, где интернет слабенький, мне и этого не хватало.
@BeforeClass
public static void openInbox() {
timeout = 10000;
baseUrl = "http://gmail.com";
open("/");
$(byText("Loading")).should(disappear);
login();
}
Обратили внимание, как мы ждём окончания загрузки страницы? В этом вся мощь Selenide: элемент легко найти по тексту, и легко дождаться, пока он пропадёт.
Логин
Логин происходит очень просто:
private static void login() {
$("#Email").val(System.getProperty("gmail.username", "enter-your-gmail-username"));
$("#Passwd").val(System.getProperty("gmail.password", "enter-your-gmail-password"));
$("#signIn").click();
$(".error-msg").waitUntil(disappears, 2000);
}
Последняя строчка нужна для того, чтобы тест быстро упал, если вы ввели неверный пароль.
Количество непрочитанных писем
В реальной жизни я бы запускал тесты с определённым набором тестовых данных со, скажем, 4 непрочитанными письмами. И тогда я бы в тесте проверил наличие надписи “Inbox (4)”:
@Test
public void showsNumberOfUnreadMessages() {
$(By.xpath("//div[@role='navigation']")).find(withText("Inbox (4)")).shouldBe(visible);
}
(Но тут у нас случай сложнее, нам приходится тестировать с реальными данными, которые непостоянны. Поэтому ограничимся просто проверкой наличия слова “Inbox”.)
Проверка содержимого инбокса
Увы, у GMail все локаторы тщательно заобфускированы. Использовать ID или другие селекторы не представляется возможным. Поэтому ограничимся просто проверкой наличия на странице определённых текстов - мы знаем, что такие письма точно должны быть в моём инбоксе:
@Test
public void inboxShowsUnreadMessages() {
$$(byText("Gmail Team")).filter(visible).shouldHave(size(1));
$$(byText("LastPass")).filter(visible).shouldHave(size(3));
$$(byText("Pivotal Tracker")).filter(visible).shouldHave(size(3));
}
Обновление инбокса
В интерфейсе GMail есть кнопка обновления “Refresh”. Ищем её по атрибуту title
=Refresh
- другого способа я не нашёл.
@Test
public void userCanRefreshMessages() {
// В реальной жизни: INSERT INTO messages ...
$(by("title", "Refresh")).click();
// В реальной жизни: проверить, что новое письмо появилось в инбоксе
}
В настоящих тестах я до нажатия добавил бы новое письмо в базу данных, и после нажатия “Refresh” проверил бы, что оно появилось в инбоксе.
Новое письмо
Для составления нового письма нажимаем кнопку “COMPOSE”:
$(byText("COMPOSE")).click();
И вбиваем адрес, тему и текст:
$(By.name("to")).val("andrei.solntsev@gmail.com").pressTab();
$(by("placeholder", "Subject")).val("ConfetQA demo!").pressTab();
$(".editable").val("Hello braza!").pressEnter();
$(byText("Send")).click();
В общем-то, совсем ничего сложного.
И в конце проверяем, что письмо отправилось:
$(withText("Your message has been sent.")).shouldBe(visible);
Undo - redo
В моём почтовом ящике включена экспериментальная фича - “Undo”. После отсылки письма в течение 10 секунд горит кнопка “Undo”, нажав на которую, я могу отменить отсылку последнего письма и вернуться к редактированию. Очень удобно, когда, нажав “Send”, обнаруживаешь, что случайно послал письмо не тому человеку.
Итак, попробуем это протестировать. В конце предыдущего теста добавляем:
$(byText("Undo")).click();
highlight($(byText("Sending has been undone.")).should(appear));
Подправляем текст письма:
$(".editable").should(appear).append("Hello from ConfetQA Selen").pressEnter().pressEnter();
$(byText("Send")).click();
И ждём 10 секунд, пока кнопка “Undo” пропадёт:
highlight($(withText("Your message has been sent.")).should(appear));
highlight($(byText("Undo")).should(appear)).waitUntil(disappears, 12000);
$(byText("Sent Mail")).click();
Письмо окончательно отослано адресату.
Вот теперь GMail протестирован, гугл может спать спокойно.
Выводы
Как видите, интерфейсы без хороших ID тоже можно тестировать. Долгие запросы и ajax не являются помехой. Динамический контент не препятствие. Вот простые рецепты, позволяющие бороться с этими трудностями:
- Поиск элементов по тексту.
Это максимально приближено к поведению пользователя и минимально зависит от реализации веб-приложения. - Тестировать только важное
В приложении GMail ещё куча вещей осталась непротестированными. В данных условиях их, кажется, и невозможно протестировать (невозможность подсунуть тестовые данные, отсутствие статических локаторов). Но это не так уж и важно - главное, что критичные функции мы протестировали: показ писем в инбоксе и отсылка нового письма. Всегда начинайте с тестирования критичной функциональности, а остальное успеете оценить позже. - Используйте правильные инструменты
Selenide автоматически решает проблемы с таймаутами, аяксом, динамическим контентом, поиском по тексту. Тесты не загрязнены длинными страшными XPath. Тесты содержат только логику. Тесты хорошо читаемые.
Простых вам тестов!
28.12.14