Как тестировать GMail

Вышла Selenide 4.4.3

Блог

Как тестировать GMail

Привет!

Вы когда-нибудь задумывались, а как бы вы стали тестировать 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. Тесты содержат только логику. Тесты хорошо читаемые.


Простых вам тестов!

Андрей Солнцев
ru.selenide.org


blog comments powered by Disqus

The project is maintained by