Визуализация результатов веб-тестирования вообще и на дотнете в частности

Всем привет! Хочу рассказать о результатах своих исследований по мотивам выступления Артёма Ерошенко на конференции Гейзенбаг в 2019 году (тогда еще был оффлайн, вкусная еда в отеле, крутые и не очень выступления и так далее)

О чём собственно речь?

Если текстом вкрации, то Артём предложил решение проблемы доверия к автотестам; применительно к апи-тестам:

  • берем инфу о запросах из тестов
  • генерируем из набора информации swagger.json
  • сравниваем его с боевым
  • видим, что уже покрыто
  • видим, что не покрыто

Если говорить о ui-ных тестах, то суть примерно такая же:

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

В принципе, это всё можно назвать поговоркой “как мёртвому припарки”, ибо если на проекте доверяют автотестам, то всё круто, а если нет – то и суда нет; но, возможно, кому-то эта статья поможет улучшить процесс тестирования.

Итак, начнём.

Если вы умеете в джаву, то вам, первым делом, надо ознакомиться с вот этим репозиторием самого Артёма, где в issues описаны действия по получению нужного нам файла (идти надо снизу вверх), который вы будете отдавать в расширение браузера.

Я же пишу на шарпе, потому прошу ознакомиться с моими действиями по получению gif-ки в спойлере выше:

  1. Сначала нужно понять, каким образом сохранить инфу об элементе, чтобы потом эту инфу аттачить в аллюр.

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

  1. Дальше возник вопрос: как получить локатор элемента?

В репозитории Артёма Используется какой-то кастомный листенер, а к элементу можно применить метод ToString(), который возвращает путь к элементу String[]
Есть ли такая библиотечка на дотнете, я понять не смог, потому прогуглил, что в селениуме есть дефолтный обработчик до и после действия с элементом. С этими обработчиками надо быть аккуратным, особенно с теми, которые работают ПОСЛЕ, например, клика или ввода текста, потому что клик может вызвать полную перерисовку интерфейса, и элемент, с которым мы хотим работать в обработчике, уже перестанет существовать. Можно, конечно, всё обвешать try-catch, но по моему опыту бойлерплейта в тестах всегда достаточно, чтоб туда еще нагружать лишнего (потому мой совет – применять только before event listener, чтоб гарантированно всё работало).

Но и это не главное, что лично меня оттолкнуло от использования event listener-ов:

Вот так выглядит элемент page-object-а

То есть из page-object-а мы можем рефлексией вытащить локатор и сохранить его в отчёт, и он будет гарантированно работать (ведь если он работает в тесте и находит то, что нам нужно, то и потом на странице нам подсветится то, что мы хотим)

А вот что за элемент в обработчике

То есть в обработчике каждый раз появляется некий нонейм IWebElement, о котором мы не знаем ничего, потому мне приходится юзать метод, который получает полный xpath до этого элемента

Потому я принял решение просто написать экстеншн-метод, который вытягивает с элемента локатор page-object-а, если он есть, либо уже берет полный xpath (если элемент получен из коллекции типо elements.Single(x => x.Text.Equals(“нужный текст”)
Метод там рассчитывает только на то, что локатор xpath, ибо экстеншен браузера понимает только его, но можно нагородить свой транслятор css → xpath (что куда проще, чем обратное преобразование)
Моя мысль такая: хочешь показать элемент? Пропиши это явно вызовом метода

  1. Дальше все просто. В конце теста массив локаторов сериализуем в json и пихаем в аллюр

  2. Качаем по ссылке аллюр cli с плагином, который умеет обрабатывать locators.json и делать один большой мета-файл

  3. путь до файла /allure-report/export/hotspot.json указываем в расширении браузера. Сам экстеншн получается скачиванием zip любой ветки из репозитория и подпихиванием его в хроме через
    image

Выводы:

  • Сложно ли это? Нет, один раз сделал, и оно работает
  • Нужно ли это? Скорее всего нет
  • Хорошо ли оно работает? Извините заранее, но через жопу: лейблы перекрывают друг друга, не работают в айфреймах и так далее – поделка очевидно сырая уже почти 2 года, и Артём сам просил контрибьютинга, чтоб довести всё это до ума (сами аллюровцы упарываются в свой аллюр-сервер, так что им не до этого точно). Мейби у них в загашниках есть нормально работающие версии, но я их не нашёл
  • Полезно ли это? Я узнал про event listener-ы и их ограничения, так что конкретно мне немношк пользы принесло. Если у вас несложный продукт, то там эта доработка может хорошо себя показать

Если хотите попробовать:

Еще одна гифка, экстеншен в браузер и исходник файла, чтоб его скормить в экстеншен

webdriver coverage 5

null в урлах это ссылка на отчет аллюр, чтоб попасть в результат теста по локатору, чтоб оно появилось, надо в allure-results складывать executors.json с ссылкой, где будет хоститься аллюр репорт (вот тут чуть подробнее)

[
    {
        "fullPath": "//div[@class = 'title']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    },
    {
        "fullPath": "//a[@href = 'https://testomat.io']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    },
    {
        "fullPath": "//*[@id = 'search-term']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    },
    {
        "fullPath": "//div[@class = 'topic-meta-data'] // span[@class = 'first username']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }, {
        "fullPath": "//div[@class = 'topic-meta-data'] // span[@class = 'second full-name']",
        "count": 1,
        "urls": ["https://automated-testing.info/t/xpath-v-web-testirovanii-napisanie-i-otladka/23808"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }, {
        "fullPath": "//a[@href = '/latest']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }, {
        "fullPath": "//section[3]/div[1]/div[1]/header[1]/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[3]/div[1]/div[1]/ul[1]/li[1]",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }, {
        "fullPath": "//*[@id = 'toggle-hamburger-menu']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }, {
        "fullPath": "//*[@id = 'search-button']",
        "count": 1,
        "urls": ["https://automated-testing.info/"],
        "tests": [
            {
                "uid": "662eaeda49b94d03",
                "name": "Поиск на форуме и генерация locators.json",
                "url": null,
                "status": "passed",
                "duration": 24705
            }
        ]
    }
]

и сам экстеншен можно скачать, кликнув сюда

3 лайка

Поделюсь своим опытом по поводу покрытия.
Проект написан на - РНР
Апи тесты - JS
Покрытие снимаем через - Codeception + Xdebug

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


2 лайка

@madvlaydin Спасибо, классная статья! Большую работу проделал! Я то же самое хотел сделать для Python. Когда понял, что работы там намного больше, чем я ожидал, а плагин сыроват, то пришлось отложить на время.
Может быть когда-то вернусь к этому. Мне такой отчет кажется очень полезным.

1 лайк

спасибо за обратную связь! в принципе, вся работа проведена изначально автором доклада и его знакомыми; я же просто в определенный момент упоролся, чтобы добиться того же результата на шарпе и оценить, надо ли оно вообще

это мягко говоря
у них в репозитории сейчас половина веток ждёт другого формата данных от allure-cli, который существует в единственном экземпляре
я думаю, надо лезть в слак или где сидят аллюровцы и конкретно Артем Ерошенко, и с ним договариваться насчёт доработок

но если вы уже пытались разобраться, то суть проста:

  • нужно либо написать прямой метод получения локатора
  • либо пользоваться листенерами
  • дальше просто напихивать локаторы в массив
  • сериализовать его в json

я по сути реализовал то, что сделано у автора доклада джавой, на шарпе
думаю, что на питоне это займет часа 4

Если у нас статичные страницы - ок, а если динамика? Имхо лучше делать скрин страницы, плюс сохранять координаты клика. Затем собирать похожие и делать heatmap. Тогда будет наглядно.

что такое динамические страницы? вы же пишете локаторы, значит ожидаете, что они будут на странице, значит их точно также можно потом показать из отчета. Это если о технологии

а если по существу, то я вас прошу посмотреть доклад; там суть такая, что получившийся файл, который вы цепляете плагином, является артефактом тестирования, условно

  • прогнали тесты вчера
  • сегодня нашли баг в кнопке или еще где-то
  • проверили, что вчера тесты не ходили через элемент
  • поставили задачу на допиливание тестов

либо

  • тесты ходили через сломанный элемент
  • ошибку не нашли
  • задача на проверку логики в тестах

ну и в догонку:
я был физически на этом докладе, заранее в программе увидел это выступление и очень сильно вдохновился тем, что услышал. Потом уже чуть подостыл, и когда руки добрались сделать это всё в реальном проекте, осознал, что по сути кроме меня это особо никому не понадобится

сама по себе идея просто брать xpath до элементов во время тестов и потом каким-то образом подсвечивать их мне кажется проще, чем составление “тепловой карты” тестов, но любой метод имеет право на жизнь, особенно если это нужно не только тестировщикам

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

Я и говорю, что лучше в тесте делать скрины, и записывать координаты элемента помимо локатора. Потом объединять похожие картинки, и на основании данных строить heat map’ы.
Можно так же как у вас с цифрами делать - тут варианты возможны.

я вас не ограничиваю, делайте так, как угодно вам