company_banner

Как мы тестируем поиск в Яндексе. Screenshot-based тестирование блоков результатов

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

    Чаще всего для автоматизации тестирования веб-сервисов применяется Selenium WebDriver. Как правило, с его помощью пишут функциональные тесты. Но, как всем хорошо известно, функциональные тесты не могут решить задачу тестирования верстки сервиса, что требует проведения дополнительных ручных, зачастую кроссбраузерных, проверок. Как тест может оценить корректность верстки? Чтобы обнаружить регрессионные ошибки верстки, тесту потребуется некоторый эталон, в качестве которого может выступать изображение корректной верстки, взятой, например, с продакшен-версии сервиса. Этот подход носит название screenshot-based testing. Подход этот применяется достаточно редко, и чаще всего верстку все же тестируют вручную. Причина этому – ряд достаточно строгих требований к сервису, к среде выполнения тестов и к самим тестам.

    Расширенные ответы сервисов Яндекса в результатах поиска — мы у себя внутри по старой традиции называем их «колдунщиками» — дополнительное звено, в котором что-то может сломаться.

    На примере тестирования колдунщиков в поиске мы расскажем, какими особенностями должен обладать тестируемый сервис, какие проблемы возникают у нас при использовании screenshot-based testing, и как мы их решаем.

    image



    Тестирование колдунщиков в поиске

    На проверки колдунщиков уходит большая часть времени, отведенного на регрессионное тестирование десктопного поиска. Важно убедиться в корректном отображении колдунщиков во всех основных браузерах (Firefox, Chrome, Opera, IE9+). Какие бы качественные функциональные тесты мы не написали, значительно сократить время регрессии нам не удавалось. К счастью, благодаря некоторым особенностям колдунщики вполне походят для screenshot-based testing:

    1. Колдунщик – довольно обособленная функциональность страницы, он слабо зависит от соседних элементов.
    2. Большая часть колдунщиков статична.
    3. Изменения в колдунщики вносятся относительно редко, так что в большинстве случаев в качестве эталона можно использовать продакшен-версию поиска.

    Чтобы тестирование было эффективным, в Selenium Grid должно быть как можно больше браузеров различных версий. Выгода от каждого теста умножается на количество браузеров, в котором он выполняется. На создание screenshot-based тестов уходит много времени и ресурсов, поэтому нужно стараться проводить их с максимальной степенью эффективности. Иначе выигрыш во времени по сравнению с ручным тестированием может оказаться совсем незначительным. Для нужд автоматизации тестирования мы развернули Selenium Grid, предоставляющий тысячи браузеров нужных нам типов.
    Другая проблема, о которой нужно подумать «на берегу» – стабильность сервиса в целом. Когда сервис бурно живет и развивается (значительно меняется дизайн, функциональность), борьба с таким уровнем шума потребует поддержки и может не окупиться от обновления до обновления сервиса. Как было отмечено выше, колдунщики достаточно стабильны.

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

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

    На пути к полной кроссбраузерности тестов было решено много проблем, вызванных прежде всего особенностями OperaDriver и IEDriver (описание которых выходит за рамки данной статьи).

    Но, несмотря на все усилия, в значительном проценте случаев тесты давали ложные срабатывания по случайным причинам: лаг сети, задержки при выполнении JavaScript и AJAX. И хотя подобные ошибки случаются и с функциональными тестами, в screenshot-based тестах их влияние выше: если функциональный тест проверяет элемент A, а проблема возникла в элементе B, то ложного срабатывания может и не возникнуть, чего нельзя сказать о screenshot-based тесте.

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

    image

    Тогда как в продакшене у скрипта проблем не возникло и колдунщик выглядит иначе:

    image

    Чтобы исключить элемент случайности, мы перезапускаем тесты несколько раз, пока не убедимся в стабильном воспроизведении проблемы. Это приводит к еще одному требованию к Selenium Grid: у вас должно быть много браузеров каждого типа. Потому что только параллельный запуск сможет дать приемлемую продолжительность выполнения тестов. В нашем случае более трех часов при последовательном запуске превратились в 12-15 минут после распараллеливания. Еще мы рекомендуем длинные сценарии разбивать на независимые короткие: вероятность случайных срабатываний снизится, а анализировать отчет станет проще.

    К упомянутому отчету также предъявляются особые требования: когда тест возвращает много скриншотов, важно правильно их представить. Бесконечные клики по подстраницам отчета займут едва ли не столько же времени, что и ручная проверка сервиса. Универсального рецепта отчета нет, мы остановились на следующем:

    1. Отчет состоит из одной html-страницы.
    2. Колдунщики сгруппированы в блоки. Содержимое блоков можно сворачивать. Сначала идут блоки с ошибками.
    3. Внутри блока колдунщика отображаются сценарии. Успешные сценарии свернуты.
    4. Доступны логи сценария: с какими элементами производилось взаимодействие, чтобы можно было воспроизвести проблему.
    5. При перемещении указателя мыши по скриншоту, попеременно показываются изображения с беты и продакшена, чтобы человек мог быстро обнаружить отличие.

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

    Примеры найденных багов

    Сравнивая изображения-состояния колдунщиков, мы смогли обнаружить баги различных типов (далее первый скриншот – бета, второй – продакшен):

    • Съехавший текст (колдунщик почтового индекса);

    image

    • Изменение масштабирования изображения (колдунщик афиша-событие);

    image

    • Регрессия в css (черная рамка у полей ввода математического колдунщика);

    image

    • Регрессия в данных (колдунщик переводов).

    image

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

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

    30 ноября в Санкт-Петербурге мы проведём Тестовую среду — своё первое мероприятие специально для тестировщиков. Там мы расскажем, как у нас устроено тестирование, что мы сделали для его автоматизации, как работаем с ошибками, данными и графиками и о многом другом. Участие бесплатное, но мест всего 100, поэтому надо успеть зарегистрироваться.
    Яндекс
    628.68
    Как мы делаем Яндекс
    Share post

    Comments 17

      +3
      Спасибо за статью.

      Каким образом вы перезапускаете тесты, чтоб исключить случайности? Если автоматически, то как с этим работает CI? Если автоматически, то как отслеживаете, какие тесты часто падают случайно и что с ними делаете?

      Кто первый работает с результатами screenshot-based тестов: разработчики, тестировщики, автотестеры?

      Какова вероятность ложного срабатывания отдельного теста? Сколько тестов всего? Сколько тестов ложно срабатывают в каждой сборке? Сколько времени ежедневно тратится на поддержку системы в контексте ложных срабатываний?
        +5
        Каким образом вы перезапускаете тесты, чтоб исключить случайности? Если автоматически, то как с этим работает CI? Если автоматически, то как отслеживаете, какие тесты часто падают случайно и что с ними делаете?

        После выполнения сценария понятно, есть ошибка или нет. Если есть ошибка, не завершая теста, мы выполняем сценарий заново с помощью механизма рул в junit. Отчет содержит ошибку, если она воспроизвелась заданное нами число раз. Соответственно, CI про это ничего не знает. Через некоторое время использования таких тестов приходит знание, какие колдунщики стабильны, а какие нет. Могу привести примеры нестабильных колдунщиков: время [который час], панорамы [панорама москвы], игры [игры онлайн]. Это либо анимация, либо сильно случайные данные. Срабатывания этих тестов однотипны и легко отличимы от реальных проблем.
        Кто первый работает с результатами screenshot-based тестов: разработчики, тестировщики, автотестеры?

        Удалось передать эксплуатацию тестов ручным тестировщикам (в большей степени) и разработчикам (в меньшей степени). Есть довольно прозрачный механизм запуска тестов и получения отчета в понятном стороннему от автоматизации человеку виде. От автоматизаторов теперь зависит добавление новой функциональности и поддержка тестовых сценариев (локаторы изменились, запросы протухли) — но и тут большая помощь идет от ручных тестировщиков. Мы дали им возможность редактировать и добавлять сценарии отдельно от кода.
        Какова вероятность ложного срабатывания отдельного теста? Сколько тестов всего? Сколько тестов ложно срабатывают в каждой сборке? Сколько времени ежедневно тратится на поддержку системы в контексте ложных срабатываний?

        Вероятность распределена неравномерно по тесткейсам. Есть тесткейсы, которые никогда не давали ложного срабатывания. Есть тесткейсы, которые почти всегда дают срабатывание (писал об этом выше, про нестабильные колдунщики). Для домена ru сейчас используетсяя около 700 тесткейсов. Скажем так, «срабатывает» около 10% тестов из запуска в нормальных условиях. Нормальные условия — это когда не меняют глобальные библиотеки стилей.

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

        Есть наша статистика, которую посчитали при запуске тестов в эксплуатацию: после появления тестов, время тестирования поисковой выдачи в одном браузере/домене сократилось с 90 минут до 46 (из которых 8 уходило на анализ отчета автотестов). Экономию в 44 минуты на каждый браузер/домен нужно умножить на число поддерживаемых конфигураций.
      • UFO just landed and posted this here
          +2
          Не совсем честно, но, оглядываясь на долю этого браузера и несовершенство его реализации Selenium Webdriver, мы говорим «это тоже webkit, нам хватит Chrome».
          0
          Очень удивился, почему тестовую среду проводите в субботу. Я думал это традиция такая будет: «тестовые среды с Яндексом».

          p.s. Конечно, понятно, что удобство для людей важнее игры слов в названии мероприятия и календаре ;)
            0
            О я такую же штуку замутил, когда надо было большой и отвественный модуль полностью переписать. Скриншоты генерил в phantom.js Командой написали кучу тестов, которые охватывают всю функциональность, включая драг-дроп. На питоне написал сравнивалку скриншотов. Скрипт находил разные файлы, подсвечивал разницу и складывал в отдельную папку. В результате прогона создавалось несколько сотен скриншотов. После рефакторинга скриншоты с подсвеченой разницей отлично помогли найти регрессии и ручное тестирование выявило минимум ошибок.
              0
              А в опенсорс не хотите выложить?
                0
                Легко, только надо немного времени, чтоб адекватную инструкцию написать.
                  0
                  Да выкладывайте, там разберемся :)
                    0
                    Хорошо что на Python!
                    Можно прикрутить к Robot Framework. У него есть встроенная библиотека ScreenshotLibrary, которая позволяет по ходу выполнения теста делать скриншоты.
                    Так что ждем ссылочку с нетерпением, а то утомились уже вручную скриншоты просматривать и анализировать.
                    0
                    Присоединяюсь :)
                      0
                      Написал пост на тему своей реализации. Таки извиняюсь, что дезинформировал вас — Питон был использован в другом проекте, а тут я обошелся готовыми средствами.
                      0
                      Интересно, может быть использовали какой-то умный алгоритм сравнения скриншотов? Понятно, что реальный браузер — зачастую самое медленное звено тестов, но и оптимизация сравнения больших скриншотов видится полезной.
                      –1
                      извините за выражение, но sikuli
                        0
                        А у вас получилось использовать Сикули с пользой?
                          0
                          да, оно и с вебдрайвером работает
                          0
                          Если вы предлагаете использовать Sikuli IDE, то это видится неприемлемым. Как и популярная в свое время Selenium IDE.

                          Если использовать обвязку для webdriver, то я не совсем понимаю, как подружить sikuli с Selenium Grid, ведь фактически машина, на которой выполняется тест, и машина, на которой запущен используемый браузер, — это разные машины. А без грида мы получим неприемлемое время выполнения полного набора тестов.

                          В общем, хочется больше подробностей, как вы видите sikuli в качестве альтернативы описанному решению.

                        Only users with full accounts can post comments. Log in, please.