Регрессионное тестирование вёрстки. Идея автоматизации

    Когда мы верстаем новые фичи, либо фиксим баги в небольшом проекте, нет проблем проверить, не поломали ли мы что-то работающее. Для этого достаточно просто его прокликать. Но так бывает не всегда: наш текущий проект насчитывает около 200 уникальных страниц и мы столкнулись с проблемой автоматизации регрессионного тестирования вёрстки. И если у программистов всё всем давно известно, методы тривиальны, да и ПО соответствующее написано, то нам, front end разработчикам, приходится ломать голову. Но мысли некоторые есть.

    В контексте этого документа, я буду условно разделять все ошибки вёрстки на ошибки раскладки (связаные с позицией блока в документе) и оформления (как то цвет текста, фона и др.) Далее мы будем рассматривать ошибки раскладки.

    Из-за чего весь сыр-бор


    При вёрстке мы используем подход вроде Object Oriented CSS. Таким образом, наша страница состоит из блоков, блоки могут быть как простые, не содержащие других блоков, так и составные, имеющие внутри себя простые блоки. Мы сделали свой код максимально некаскадным (за исключением некоторых наследуемых значений, вроде цвета ссылки, текста и шрифта), и, казалось бы, если мы аккуратно делаем девтест того самого блока, который подвергается изменениям, сломаться ничего не должно. Как бы ни так! Потому что:



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


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

    Идея алгоритма


    Она простая. По большому счёту, единственным объективным машинодоступным критерием изменения раскладки документа является изменение положения неких контрольных точек. Т.е. шаги выглядят так:
    1. В документах (исходниках простых блоков, составных блоков, страниц на dev сервере) мы расставляем некие контрольные точки
    2. Программа-валидатор определяет координаты этих точек относительно системы координат (например, левая верхняя точка рабочей области браузера с горизонтальной и вертикальной осями) и записывает их значения в базу
    3. Программа-валидатор сравнивает предыдущее координаты точек с текущими и приводит список несоответствий вида «адрес страницы — id точки — старые координаты — новые координаты»
    4. В ручном режиме разработчик просматривает данные страницы и отмечает новые значения как корректные (в случае если это соответствует ожидаемому результату внесённых изменений) или некорректные

    Таким образом, подобный метод мы можем использовать как в процессе разработки, так и багфиксинга.

    Программа-валидатор и контрольные точки


    В моём понимании в физическом смысле точки выглядят как HTML комментарии некоторого шаблона в коде документа, например <!-- ###testing:id1### -->. Посредством JS утилиты, внедрённой в каждую страницу и HTML исходник, они заменяются на пустой блок с нулевой высотой. Затем рассчитывается положение этого блока, также посредством JS.

    Точки предполагается расставлять руководствуясь следующей логикой:
    • После кода одного блока в исходниках блоков
    • В коде блока в характерных местах (зависит от каждого конкретного случая)
    • В коде страницы в характерных местах, и в местах условных направляющих сетки документа.

    Программа-валидатор состоит из клиентской и серверной частей. Клиентская преобразует комментарии в блоки, определяет их кооринаты и передаёт значения параметров серверной части. Серверная часть сравнивает значения точек, добавляет новые точки в базу, обрабатывает выбор правильных точек разработчиком.

    Резюме


    Я не знаю, существуют ли в принципе методы автоматизации тестирования вёрстки. Гугление не дало никаких результатов, поэтому я попытался придумать свой метод. Если вы знаете готовый инструментарий, пожалуйста, поделитесь им в комментариях.
    Я попытался оформить свои мысли на абсолютно универсальную систему тестирования, которая была бы абстрагирована от методов реализации вёрстки, а значит применимой для любого проекта. Пока это только первые наброски на сам алгоритм, по работе ПО у меня есть только общие соображения, описанные выше. Я не претендую на исключительную верность и эффективность такого подхода. Первые выводы можно будет сделать только после первых результатов работы.
    И, самое главное, я призываю широкие массы обсудить в комментариях всё, что я описал, сделать замечания и предложения, а также энтузиастов помочь в реализации ПО.
    Буду благодарен каждому, кто поставит ссылку на этот пост, разместит анонс у себя в блогах, твитнет и вообще всячески поможет широкому обсуждению данной темы тут или на моём блоге.

    Similar posts

    Ads

    Comments 30

      0
      Чем не устраивают winrunner и другие подобные продукты? Они для того и созданы, чтобы гуи тестировать.
      Почему они не подошли?
        +1
        Извините, что вопросом на вопрос, но в нём и содержится ответ:
        А вы пробовали решить поставленную задачу с помощью winrunner и других продуктов тестирования GUI?
          0
          Нет, не сталкивался с такой задачей. Но мне очень интересно, почему пришлось изобретать свое средство, чего не хватает уже существующим решениям. Как бы в дополнение к вашей статье. :)
        0
        Тоже както думали над автоматизацией/упрощением тестирования верстки, как по мне эта идея супер
        только можно не маркеры добавлять, а например class=js_test для ключевых элементов и потом на сервер отсылать не только положение но и ширину/высоту элемента
          +1
          Решение с маркерами более отказоустойчивое: классы могут заменяться JS сценариями. Кроме того, перед выкладкой, как показала практика нашего проекта, удалять комментарии вполне безопасно. Удалять же регуляркой классы я бы не стал, как потенциально багоопасный момент (вырезания лишнего), который мы не контролируем. Да, я понимаю, что можно написать правильную регулярку, но тут в самом методе модержится погрешность.
          Что касается необходимости вычисления ширины (маркеры — суть определение высоты, только в неявном виде), теоретически это может быть полезно. На практике, надо проверять.
            0
            добавление экстракода это потенциальные баги, лучше его избегать, как и внедрение дополнительного js на страницу.
              0
              пара лишних классов большой роли не сыграет

              … зато появляется возможность живого тестирования :)
              на пару часов в месяц включаем юзерам этот JS, логируем версию браузера, и получаем самую живую статистику )))
            +2
            А почему бы не вставлять дополнительный код, а написать парсер, который бы брал координаты классов, для примера.
              0
              Несколько вопросов:
                0
                — Как вы собрались определять координаты точек для разных разрешений экрана, для разных браузеров, и это все сапортить в дальнейшем?
                — Как вы однозначно определяете по полученным координатам что блок находиться в ошибочном месте

                Приведу пример: У вас каскад из трёх вложенных блоков, ошибка сдвига по некой координате по первому (который включает остальные) блоку -1px, такая же ошибка для второго блока +2px, ошибка для третьего блока -1px. Маркер в третьем блоке — его координаты относительно окна верны и безошибочны (-1 +2-1=0). Но на самом деле как мы видим ошибки раскладки во всех трех блоках.
                  0
                  на самом деле макет выглядит так, как и должен, визуальной ошибки нет, клиент увидит то, что и должен, повода для паники — нет
                  проблема может править себя в дальнейшем, тогда и будет исправлена
                  +3
                  не велосипедте. возьмите селениум.

                  verifyElementPositionLeft
                  verifyElementPositionТоп
                  verifyElementHeight
                  verifyElementWidth
                  и тд.

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

                      И на верстку ему в данном конкретном случае будет наплевать, ему надо только ID изучаемого элемента знать.

                      >> В ручном режиме разработчик просматривает данные страницы
                      вот от этого можно будет избавиться.
                      Конечно на внедрение и на «разобраться» (+ на поддержку естественно) понадобится некоторое время, но на больших проектах оно окупается.
                        0
                        Негибкость конфига заключается в необходимости привязки к конкретным классам (id не используем). Это не тот уровень абстракции, который хотелось бы достичь. В моём понимании, если мы ставим задачу тестировать «картинку», то не должны завязываться на коде. Мне кажется более правильным подход в установке уровней (как направляющие в фотошопе), нежели метрики конкретных элементов (сегодня элемент такой, завтра другой).
                        Возможно, я что-то недопонимаю или толкую неверно. Но я не хотел бы спорить на сей счёт, пока изучаю возможность применения селениума для данной проблемы, иначе у нас получится разговор слепого с глухим )
                          0
                          ага, понятно. Но если уж вы добавляете в код , то наверно можно вместо него добавить определенные классы или id к определенным элементам.

                          У селениума довольно гибкая система локаторов, reqexp в xpath, можно выполнять js на клиенте(без изменения кода) и прочие интересные вещи. Например:
                          Number n = selenium.getXpathCount("//td[@width>50]");

                    +5
                    Мы для тестирования верстки в наших проектах используем другой, более «тупой», но, возможно, более эффективный подход. Робот запускает браузер, устанавливает ему заданный размер и начинает прокликивать указанные в тестовом скрипте страницы. В том же скрипте указано какие страницы (и какую область) нужно сфотографировать (сделать скриншот) и какое имя дать скриншоту. Робот фотографирует и смотрит наличие на диске существующего скриншота с таким же именем. Если такой скриншот найден, то он считается эталонным и происходит попиксельное сравнение двух скриншотов. Если скриншоты совпадают, тест считается пройденным. Если скриншот не найден, то он создается на диске. Процедура создания эталонных скриншотов проста, запускаем все скрипты, просматриваем все полученные картинки один раз глазами, чтобы убедиться что все выглядит правильно, далее робот все делает за вас. Если тест упал, открываем невалидную картинку (робот делает diff, и подсвечивает различающиеся области красным) проверяем глазами была ли разметка сломана или это плановое изменение. Если поломано — чиним, если все нормально, удаляем «плохой» эталон и запускаем тест еще раз, чтобы создать новый.
                      +1
                      Хм… прекрасная идея! Благодарен.
                        0
                        Если вдруг надумаете реализовать, хочу еще сделать одну ремарку. Рендеринг UI может включать в себя недетерминированные алгоритмы (у нас, например, это хорошо заметно на антиалиасинге шрифтов, которым видимо занимается графическая система), поэтому при сравнении успехом считается совпадение двух картинок с определенной заранее заданной максимальной погрешностью. В прочем, алгоритм расчета этой погрешности может быть индивидуальным.
                        +1
                        Согласен, прекрасная идея! А чем попиксельно сравниваете картинки?
                          0
                          Робот написан на C#/.Net, включая модуль который картинки сравнивает.
                          0
                          А если страница сайта в экран целиком не попадает?
                            0
                            К счастью, нам удалось научить робота скроллировать ;)
                            0
                              0
                              Спасибо за ссылку, насколько я понял, пробежавшись по сайту, sikuli все-таки заточено под функциональное тестирование, несмотря на то что, технически позволяет искать шаблонную картинку на экране. Плюс, если Вы намеренно изменили внешний вид, то Вам придется менять сами тесты, в нашей системе в 99% случаев тесты остаются неизменными. Но замечу, что наш робот тоже изначально занимался лишь функциональным тестированием, модуль тестирования скриншотов появился позже и достаточно хорошо вписался в существующую архитектуру.
                              +1
                              Трудолюбивый у вас робот однако.
                                0
                                Поясни, пожалуйста, чем OperaDriver может помочь в тестировании вёрстки? Насколько я понимаю, это сделает чего-то, что не может Selenium без OperaDriver.
                                0
                                рекомендую по теме доклад Артема Ерошенко и Ильи Кацева на YaC 2011: yac2011.yandex.ru/archive2011/video2/ (в самом низу)
                                  0
                                  На видео не весь доклад, а только половина. Интересующая часть в запись не вошла, видимо. В любом случае, спасибо за ссылку.

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