Русский
Русский
English
Статистика
Реклама

Xcresult

ZERG что за зверь?

19.02.2021 14:12:20 | Автор: admin


Когда мы говорим о CI&CD, мы часто углубляемся в базовые инструменты автоматизации сборки, тестирования и доставки приложения фокусируемся на инструментах, но забываем осветить процессы, которые протекают во время отрезания и стабилизации релизов. Однако, не все готовые инструменты одинаково полезны, а какие-то кастомные процессы не укладываются в их покрытие. Приходится исследовать процессы и находить пути автоматизации для их оптимизации.

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

У нас есть ночные прогоны, когда гоняются полные наборы тестов. Но на самой заре освоения Zephyr, нашим тестировщикам во время регресса приходилось скачивать xcresult, или ещё ранее plist, или junit xml, а затем проставлять соответствия зелёных и красных тестов в зефире руками. Это довольно рутинная операция, да и занимает она много времени, чтобы руками пройти 500-600 тестов. Такие вещи хочется отдать на откуп бездушной машине. Так родился ZERG.


Рождение зерга


Zephyr Enterprise Report Generator небольшая утилита, которая изначально умела только искать соответствия в отчёте тестов и отправлять в Zephyr их актуальные статусы. Позже утилита получила новые функции, но сегодня мы остановимся на поиске и отправке отчётов.
В Zephyr нам предлагается оперировать версиями, циклами и проходами (execution) тест кейсов. Каждая версия содержит произвольное количество циклов, а каждый цикл содержит в себе проходы кейсов. Такие проходы содержат в себе информацию о задаче (zephyr прекрасно интегрируется с jira и тест кейс это, по сути, задачка в jira), авторе, о статусе кейса, а также о том, кто занимается этим кейсом и о других необходимых деталях.
Для автоматизации проблемы, которую мы обозначили выше, нам важно разобраться в проставлении статуса кейса.

Работа с кодом


Но как соотнести тест в коде и тест в зефире? Здесь мы выбрали довольно простой и прямолинейный подход: для каждого теста мы добавляем в секцию комментариев ссылки на задачи в jira.


В комментариях также могут размещаться дополнительные параметры, но об этом позже.
Так, один тест в коде может покрывать несколько задач. Но работает и обратная логика. Для одной задачи может быть написано несколько тестов в коде. Их статусы будут учитываться при составлении отчёта.
Нам надо пройти по исходникам, извлечь все тест-классы и тесты, слинковать задачи с методами и соотнести это с отчётом о прохождении тестов ( xcresult или junit ).
Работать с самим кодом можно разными путями:
просто читать файлы и через регулярные выражения извлекать информацию
использовать SourceKit

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



Нам надо получить тесты. Для этого опишем структуры:



Затем нам надо прочитать отчёт о прохождении тестов. ZERG был рождён ещё до переезда на xcresult, и поэтому умеет парсить plist и junit. Детали в этой статье нас всё ещё не интересуют, они будут приложены в коде. Поэтому отгородимся протоколам



Остается только слинковать тесты в коде с результатами тестов из отчетов.



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

Работаем с зефиром


Теперь, когда мы прочитали отчёты о тестировании, нам надо их перевести в контекст zephyr. Для этого надо получить список версий проекта, соотнести с версией приложения (чтобы это так работало, необходимо, чтобы версия в зефире совпадала с версией в Info.plist вашего приложения, например, 2.56), выкачать циклы и проходы. А дальше соотнести проходы с нашими уже имеющимися отчётами.
Для этого нам надо реализовать в ZephyrAPI следующие методы:



Cпецификацию можно увидеть здесь: getzephyr.docs.apiary.io, а реализацию клиента в нашем репозитории.
Общий алгоритм довольно простой:



На этапе сопоставления проходов с отчётами есть тонкий момент, который необходимо учитывать: в zephyr api обновление execution отправлять удобнее всего пачками, где передаётся общий статус и список идентификаторов проходов. Нам нужно развернуть наши отчёты относительно тикетов и учесть n-m соотношение. Для одного кейса в зефире может быть несколько тестов в коде. Один тест в коде может покрывать несколько кейсов. Если для одного кейса есть n тестов в коде и один из них красный, то для такого кейса общий статус красный, однако если один из таких тестов покрывает m кейсов и он зелёный, то остальные кейсы не должны стать красными.
Поэтому мы оперируем сетами и ищем пересечение красных и зелёных. Всё, что попадает в пересечение, мы отнимаем из зелёных результатов и отправляем отредактированные сведения в zephyr.



Здесь ещё нужно отметить, что внутри команды мы договорились, что zerg не будет менять статус прохода, если:
1. Текущий статус blocked или failed (раньше для failed мы меняли статус, но сейчас отказались от практики, потому что хотим, чтобы тестировщики обращали внимание на красные автотесты во время регресса).
2. Если текущий статус pass и его поставил человек, а не zerg.
3. Если тест помечен как флакающий.

Интересности Zephyr API


При запросе циклов нам приходит json, который с первого взгляда невозможно систематизировать для десериализации. Всё дело в том, что запрос на получение циклов для версии, хотя по смыслу и должен возвращать массив циклов, на самом деле возвращает один объект, где каждое поле уникально и называется идентификатором цикла, который лежит в значении. Чтобы такое обработать, мы применяем несложные хаки:



Статусы прохождения тестов приходят в одном из запросов рядом с объектом запроса. Но их можно вынести заранее в enum:



При запросе циклов нужно передавать в параметры запроса версию и целочисленный идентификатор проекта. Но в запросе проходов для цикла надо этот же идентификатор проекта передавать в формате строки.



Вместо заключения


Если есть много рутинной работы, то, скорее всего, что-то можно автоматизировать. Синхронизация прохождения автотестов с системой ведения тестов один из таких кейсов.
Таким образом, каждую ночь у нас проходит полный прогон тестов, а во время регресса отчёт отправляется QA-инженерам. Это снижает время регресса и даёт время на исследовательское тестирование.
Если правильно реализовать парсер андроид-исходников, то его можно с тем же успехом применять и для второй платформы.
Наш Zerg помимо сопоставления тестов ещё умеет в начальный импакт анализ, но об этом, возможно, в следующий раз.
Подробнее..

XCResult как и зачем читать

04.03.2021 16:23:55 | Автор: admin


В 2018 году Apple в очередной (третий) раз обновили формат, в котором выдаётся информация о прогоне тестов. Если раньше это был plist файл, который представлял из себя большой xml, то теперь это большой файл с расширением xcresult, который открывается через Xcode и содержит в себе кучу полезной информации, начиная c результатов тестов с логами, скриншотами и заканчивая покрытием таргетов, диагностической информацией о сборке и многим другим. Большинство разработчиков не работает каждый день с этим, но инфраструктурщики в данной статье могут найти что-то полезное.

Разложим по полочкам плюсы и минусы обновления формата


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

Чем удобен новый xcresult?
Открывается нативными средствами через Xcode.
Можно передавать коллегам из QA и разработки, даже если у них нет локально проекта. Все откроется и покажет нужную информацию.
Содержит исчерпывающую информацию о прогоне тестов.
Можно читать не только через Xcode.

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

Зачем читать XCResult не через Xcode?


Если у вас в компании настроены процессы CI&CD, то наверняка вы собираете метрики по сборкам проекта, по стабильности и количеству тестов, и, конечно, данные по тестовому покрытию. Скорее всего, где-нибудь на Bamboo, Jenkins, Github у вас рисуются упавшие тесты или статус CI, или процент покрытия. Такие операции принято автоматизировать и отдавать на откуп бездушным машинам. Какие инструменты есть у нас для этого?
Apple, вместе с релизом нового формата, выпустили и инструменты xcresulttool и xccov, с которыми можно работать из терминала.

Что мы можем достать, используя xccov?


xcrun xccov view --report --json /path/to/your/TestScheme.xcresult

Запрос вернёт исчерпывающую информацию о том, каким покрытием обладают все таргеты, какие методы и каких классов покрыты, сколько раз они были выполнены и какие строчки выполнялись. Объекты обладают схожей структурой. Всего там 4 уровня: корень, таргет, файл, функция. Все уровни, кроме корневого, имеют поле name. Во всех уровнях есть поля coveredLines и lineCoverage. Важно отметить, что объекты имеют какой-то собственный контекст. Всю структуру можно описать в несколько протоколов.



Помимо протоколов выделим следующие структуры: CoverageReport агрегатор всего и корень. Он содержит в себе массив объектов Target. Каждый Target содержит в себе массив File, которые, в свою очередь, содержат массив Function. Эти объекты будут реализовывать протоколы, которые описаны выше.
Нас интересует поле lineCoverage. Для составления красивого отчета (как в fastlane) обратимся к полю lineCoverage и пройдем по всем объектам нехитрой функцией:



Получим что-то похожее на:

Coverage Report Summary:

Utils.framework: 51,04 %

NavigationAssistantKit.framework: 0,0 %

NavigationKit.framework: 35,85 %

Logger.framework: 20,32 %

FTCCardData.framework: 78,21 %

FTCFeeSDK.framework: 25,25 %

ErrorPresenter.framework: 2,8 %

MTUIKit.framework: 0,24 %

AnalyticsKit.framework: 47,52 %

EdaSDK.framework: 1,18 %

Alerts.framework: 85,19 %

Resources.framework: 39,16 %

QpayApiTests.xctest: 88,37 %

FTCFeeSDKTests.xctest: 97,91 %


P.S. Для того, чтобы coverage собирался, необходимо добавить в вашу команду тестирования параметр -enableCodeCoverage YES или включить в настройках схемы в Xcode.

Какие возможности даст xcresulttool?


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

Для начала неплохо ознакомиться с самим интерфейсом:

xcrun xcresulttool --help

OVERVIEW: Xcode Result Bundle Tool (version 16015)

USAGE: xcresulttool subcommand [options] ...

SUBCOMMANDS:

export Export File or Directory from Result Bundle

formatDescription Result Bundle Format Description

get Get Result Bundle Object

graph Print Result Bundle Object Graph

merge Merge Result Bundles

metadata Result Bundle Metadata

version XCResultKit Version


Чтобы прочитать структуру, нам достаточно вызвать команду:

xcrun xcresulttool get --path /path/to/your/res.xcresult --format json

Здесь мы получим оглавление для нашего xcresult бандла. Что собиралось, какие тесты прогонялись, сколько времени заняло, где лежат скриншоты и логи, и какие были предупреждения компилятора. Для нас главное достать идентификаторы файлов, в которых лежит информация о тестах.

xcrun xcresulttool get --path /path/to/your/res.xcresult --format json --id {id}

Тогда мы получим объекты с тест-таргетами, типом тестов, которые разбиты по тест-классам и test suits с отчётами с логами, скриншотами, временем выполнения и прочей информацией по каждому тесту.
К сожалению, причину падения красных тестов не получится вытащить просто для этого придётся делать ещё один запрос на каждый упавший тест (а на самом деле даже не один! Если тест крэшнул, то крэшлоги вместе со стректрейсом лежат в другом месте и это ещё один запрос!

Для Failure Summary используется тот же запрос:

xcrun xcresulttool get --path /path/to/your/res.xcresult --format json --id {id}

А вот для крэшлогов нужно убрать --format json из запроса, т.к. там просто строка и при передаче форматтера инструмент выдаст ошибку.

Что делать с этими справочными знаниями дальше?


Автоматизировать, конечно же! Если вы попробуете выполнить эти команды, то увидите, что ответы гигантские и их тяжело читать. Как автоматизировать? Ruby, Python Или Swift?
Конечно же, swift. Его знает любой современный iOS разработчик. Проект открывается в Xcode, доступна отладка, подсветка синтаксиса, строгая типизация. Короче, мечта! Особенно при появлении Swift package manager.
Ни для кого не секрет, что с помощью swift мы легко можем запускать процессы, слушать ошибки и получать выходные данные. В самом простом случае мы можем обойтись такой конструкцией:



Нам остается теперь только исследовать формат XCResult через уже знакомые нам xcrun xcov и xcrun xcresulttool. Например, чтобы прочитать покрытие тестами, мы используем:



А чтоб получить оглавление XCResult нам нужно выполнить:



Но как нам получить наши заветные структуры CoverageReport и XCResult?
Получаем строку из Data, которую вернет нам первая Shell команда и помещаем содержимое сюда: quicktype.io.
Сервис сгенерирует нам что-то похожее на нужные свифтовые структуры. Правда использовать результат как есть не получится. Придётся пристальнее изучать структуру ответа и выбрасывать дубли. Тем не менее такая работа не составляет большого труда. Можно отбрасывать ненужные части, а можно заняться исследованием и выделить несколько основных кирпичиков:



На основании этого описать уже остальные структуры, например:



или даже такие сведения о компьютерах, на которых совершался прогон:



Ну а этим-то как пользоваться?


Есть два пути, как пользоваться нашим скраппером. Первый как executable, и здесь здорово помогает библиотека swift-argument-parser от Apple. До этого приходилось писать обработку аргументов самим, покрывать тестами, поддерживать. Сейчас эту работу взяла на себя популярная библиотека, меинтейнерам которой можно доверять.
Есть две команды: получить отчёт по покрытию тестами и сгенерировать junit отчёт о результатах тестирования. Нужно сбилдить проект и запускать бинарник, передавая необходимые аргументы:



Второй путь использовать этот проект как библиотеку. У нас есть большой CI проект, который отвечает за сборку, тестирование и доставку нашего продукта KoronaPay. Например, мы можем по результатам прохождения тестов извлекать все assertion failures и крэши в тестах приблизительно так:



Или получать красные тесты, анализировать флаки и перезапускать только их.
А как анализировать? Всё просто и непросто одновременно. Чтобы достать детали причины падения теста, надо сделать дополнительный запрос к xcresult по идентификатору failure summary. А затем из failure summary вытаскивать информацию. На сегодняшний момент мы научились искать крэши в тестах и lost connection случаи, а также вытаскивать причины. Понять, что произошел крэш несложно. Надо лишь найти в failureSummaries заветные слова crashed in.



Чуть сложнее вытащить причину крэша.
Здесь нам пригодится механизм рефлексии в swift, который хоть и несколько ограничен, но отлично подходит для решения этой задачи. Необходимо найти все объекты типа Attachment с именем kXCTAttachmentLegacyDiagnosticReportData.



В методе reflectProperties нет ничего магического, это простенький extension для Mirror:



Еще одна категория красных тестов ассерты. В отличие от крэшей здесь не получится просто поискать строку crashed in. Такие тесты могут маскироваться под lost connection случаи. Чтобы докопаться до причины, придется пройтись по нескольким массивам внутри объекта TestCase примерно так:



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



Вместо заключения


Как и все существующие в этой области решения, наш скраппер не является исчерпывающим инструментом для анализа xcresult. Чтобы получить всю информацию и посмотреть скриншоты, все еще надо открывать xcresult через Xcode. Однако если у вас настроен CI и вы хотите видеть результаты тестов быстро, то, скорее всего, сможете оценить связку junit и нашего xcscrapper по достоинству.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru