Как мы тестируем взаимодействие с Facebook

60f6f6103d384160ad9f007dfb77456a.png

Вступление

Привет, хаброжитель! Уже довольно давно я хотел написать статью о том, как у нас в Badoo устроена автоматизация тестирования. Хотелось написать о чем-то интересном и, в то же время, полезном. Поделиться опытом, который можно было бы легко интегрировать почти в любую систему. И вот, такая тема назрела…

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

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

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

Сегодня я расскажу о том, как на Badoo устроена регистрация и верификация через Facebook и о том, как мы научили selenium-тесты ее проверять.

6e755913c5b14d5582b2f6d021de6acf.png

Итак, представим, что вы — новый пользователь сервиса Badoo. Вы заходите на сайт и видите вот такую форму регистрации. Заполнять все эти поля или кликнуть по кнопочке регистрации через Facebook? Для меня это — никогда не вопрос. Я бы заполнил все поля вручную и не стал бы привязывать свой аккаунт. Почему? Потому что я немного параноик, надеюсь, это не заразно. :)

На самом деле Badoo никогда не разместит какую-либо информацию из стороннего источника без согласия пользователя, так что спокойно кликаем по темно-синей кнопке и регистрируемся на сайте. Один клик, 10–15 секунд, и у нас есть свой верифицированный профиль на Badoo. Ура!

080319c6863741b3a37144ed61b1eacd.png

Как бы поступил настоящий QA-инженер после того, как создал профиль на сервисе так просто и быстро? Правильно, попробовал бы создать еще один. Как отреагирует сервис, если на тот же FB-аккаунт попробовать зарегистрировать еще один профиль?

Снова открываем страничку регистрации и кликаем по иконке FB. Ничего неожиданного не произошло, Badoo «узнало» FB-аккаунт и вместо регистрации сразу авторизовало. Все в порядке.

Первый selenium-тест на регистрацию

Теперь представим, что вы — QA-инженер в компании Badoo. Перед вами стоит задача — автоматизировать флоу регистрации и авторизации через FB аккаунт. На первый взгляд задача простая, вот что вам понадобится:

  • аккаунт FB;
  • локатор кнопочки FB на странице регистрации;
  • метод, который ждет авторизационную cookie (чтобы убедиться, что тест залогинился на сайте);
  • локатор sign out кнопочки, чтобы разлогиниться;
  • метод, который ждет, когда авторизационная cookie пропадет.

После того, как были написаны необходимые методы, составляем сценарий:

  • Открыть стартовую страницу;
  • Кликнуть иконку Facebook«а;
  • В открывшейся вкладке авторизоваться на Facebook;
  • Дождаться авторизации на Badoo;
  • Получить id пользователя (пусть будет first_user_id);
  • Разлогиниться;
  • Открыть стартовую страницу;
  • Кликнуть иконку Facebook«a;
  • Дождаться авторизации на Badoo;
  • Получить id пользователя (пусть будет second_user_id);
  • Убедиться, что first_user_id и second_user_id совпадают.

Итак, сценарий готов, вы запустили тест и он прошел. Все прекрасно. Самое время вставить котика в статью:

f29b395f6f1f4b55904d4d2489a24ec1.png

Коммитим код теста в ветку, кидаем задачу на ревью и идем пить кофе. Однако, не успели вы дойти до кухни, как приходит уведомление — задача не прошла ревью, тест не работает. Что-то пошло не так…

После перезапуска теста становится ясно, что проблема в следующем — у данного FB-аккаунта уже существует профиль на Badoo. Вместо регистрации тест сразу авторизовался. Делать нечего, надо удалять профиль по завершению теста. Слава Богу, у нас есть потрясающая штука — QaApi!

Несколько лет назад я рассказывал, как она интегрирована с нашими автотестами. Доклад назывался «Selenium тесты. От RC и одного пользователя к WebDriver, Page Object и пулу пользователей», найти его можно тут — habrahabr.ru/company/badoo/blog/216255.

Если коротко, это внутренний api, на который из теста можно отправить запрос и совершить некоторые манипуляции на стороне приложения. Вызывается он довольно просто:

QaApiHelper::deleteUser(user_id);

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

Когда тест научился удалять пользователя за собой, он стал работать стабильно и прекрасно. Но так было не долго.

Этапы тестирования Badoo

О том, какие этапы тестирования существуют в нашей компании, мы рассказываем практически на каждой конференции. Здесь я перечислю коротко те, которые интересны с точки зрения selenium-тестов:

  • Тестирование на девел-окружении. Девел — это копия продакшена со своими базами и внутренними сервисами.
  • Тестирование на шоте. Шот — это продакшен-окружение, доступное из внутренней сети по определенному урлу и являющееся мержем кода мастера и тестируемой задачи.
  • Тестирование на стейджинге. Стейджинг, традиционно — это результат мержа ветки релиза и мастера.
  • Тестирование на продакшене.

Изначально мы гоняли тесты на девел-окружении и стейджинге. Однако, со временем, пришли в выводу, что тесты нужно уметь гонять и на шотах. Причина довольно простая — девел не всегда идеально копирует продакшен, а ловить баг на стейджинге и откатывать задачу из релиза — плохо. Это значит, что задача в этот релиз уже не попадет и уедет позже запланированного.

Второй selenium-тест на регистрацию

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

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

f52dd523f0f94e5bb84b0e9e45c70c8b.png

Как решить нашу проблему? Как сделать так, чтобы у теста всегда был свежий пользователь FB?

Сначала я попытался решить проблему минимально просто. Создал mysql-табличку, в которую внес несколько созданных руками FB-пользователей и проставил им статусы — свободны. Тест брал пользователя из этой таблички, меняя ему статус на «занят». Если свободного пользователя не было, тест падал с соответствующим сообщением.

У этой системы было несколько очевидных минусов. Прежде всего, если одновременно запускалось слишком много инстансов теста, аккаунтов не хватало и взять их было неоткуда. Также тест мог по какой-то причине не освободить пользователя в конце (например если он был остановлен нажатием «Ctrl+C»). Ничто из этого не радовало по утрам, когда до релиза оставалось меньше часа.

7700c1756fc943fa82a59d5cd4bd573c.jpeg

Довольно быстро устав от нестабильных падений и неконтролируемых состояний FB-аккаунтов, я начал искать решение получше…

The Graph API

У Facebook есть замечательный api, который позволяет создавать тестовых пользователей и манипулировать ими — developers.facebook.com/docs/graph-api. Организована она довольно просто: мы формируем необходимый запрос и посылаем его на сервер FB, ответ возвращается в формате json.

Пример запроса, который зарегистрирует тестового пользователя с именем Alex:

https://graph.facebook.com/{APP_ID}/accounts/test-users?name=Alex&access_token={APP_ID}|{SECRET}

Application id и secret мы получаем, регистрируя наше приложение на FB (подробнее тут — developers.facebook.com/docs/facebook-login/overview).

Настоящий пул Facebook пользователей

Что ж, давайте создавать пользователей! :)

d7d485c1fa714a8cb7284eae5720cf89.png

Внимательно изучив graph-api и его особенности, мы составили список нюансов:

  • Количество регистраций на одно приложение ограничено. Цитата: «Для каждого приложения можно создать не более 2000 тестовых пользователей.».
    Вывод: нужно вести учет созданных пользователей.
  • Только что созданный тестовый пользователь может взаимодействовать только с единственным приложением. В данном случае приложение — это домен, на котором разместился сервис. В Badoo стейджинг и шоты находятся на разных доменах.
    Вывод: ведя учет пользователей, необходимо их разделять по app id.
  • Пользователь регистрируется довольно медленно. В среднем от 2 до 5 секунд.
    Вывод: удобнее иметь заранее созданного пользователя FB, чтобы тест не тратил время на его создание.
  • Тест должен иметь дело с тем аккаунтом, который наверняка не используется в каком-то еще тесте, чтобы избежать флуктуационных race condition.
    Данный пункт важен в рамках описываемого здесь теста.

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

  • Id пользователя;
  • Email;
  • Password;
  • App id;
  • App Secret;
  • Состояние пользователя — занят тестом или нет;
  • Timestamp создания пользователя.

В дополнение к этой табличке нам понадобилось несколько скриптов.

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

Второй решает проблему долгого создания пользователя на стороне facebook. Выглядит это следующим образом:

fefa2726468346788d3826665036658f.png

Получение FB-пользователя мы обернули в специальный QaApi метод. Тест обращается к нему за свободным пользователем. Если такого нет, создается специальное задание. В рамках этого задания скрипт посылает curl-запрос к graph-api, дожидается ответа и записывает в табличку нового пользователя. Тест же получает ответ — «необходимо подождать», закрывает коннект и делает еще одну попытку спустя несколько секунд. Таким образом мы решили две проблемы. Во-первых, логика работы с graph-api отделена от логики тестов. Во-вторых, тесты не держат долгие коннекты к сторонним сервисам, что существенно облегчает дебаг любых проблем, связанных с увеличением времени прохождения тестов.

Далее мы переписали необходимые тесты на новую систему получения FB аккаунтов и оставили тесты гоняться на ночь с нашем CI-сервером (мы используем Teamcity). К утру результат был готов. Создалось ровно столько пользователей, сколько было необходимо для использования в тестах.

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

А есть ли такой удобный API у других социальных сетей?

Я интересовался у ребят из ВКонтакте:
770a838cc45f4ddbaaa43f891493e14d.png

И у ребят из Одноклассников:
35e8e71cf40e45f6b34610745b8ea3a5.png

Итог

На данный момент пул является неотъемлемой частью нашей системы. Вокруг него появились новые скрипты и новые методы. Благодаря гибкости и простоте систему удобно развивать и контролировать.

Немного о том, что получилось в итоге:

  • Удобный инструмент для ручного и автоматизированного взаимодействия Badoo с Facebook;
  • Более 20 уникальных тестов, использующих пул facebook-аккаунтов: регистрация/авторизация, верификация, загрузка фотографий с FB-аккаунта, поиск друзей на Badoo, шаринг наград и так далее;
  • В пуле 9 различных приложений, использующих в общей сложности примерно 1.5к активных пользователей;
  • QaApi-методы умеют создавать FB-аккаунты, делать их друзьями, заливать им фотографию, ассоциировать FB-аккаунты с нашими тестовыми пользователями;
  • Система сама поддерживает необходимое количество FB-аккаунтов и чаще всего не требует никакого ручного вмешательства.

За более чем год использования api работал стабильно. Всего раз возникла проблема с токенами пользователей, но разработчики facebook пофиксили ее довольно быстро. Кому интересно подробнее — developers.facebook.com/bugs/1662068220677444.

В завершение хотелось бы поблагодарить наших ребят из разработки за их неоценимую помощь в создании всей этой системы. Вы — молодцы!

Спасибо за внимание!

Котов Виталий, QA-инженер по автоматизации.

Комментарии (0)

© Habrahabr.ru