Всё, что вам нужно знать о форматах отчётов в тестировании ПО
Каждый раз, когда я встречаюсь с проектом, в котором без причины изобрели свой новый формат отчётов мне хочется сделать что-то ещё для популяризации существующих форматов. За последнее время таких случаев было несколько. В первый раз я добавил поддержку подсветки синтаксиса TAP в библиотеку highlight.js, потом добавил поддержку синтаксиса формата SubUnit. Ну и в последний раз после встречи с одним из таких проектов я собрал воедино всю информацию по этим форматам в одном месте и получилась небольшая книжка. Таким образом, этот текст — мой крестовый поход против разножопицы с тестовыми результатами в разработке ПО :)
В наше время ни один серьёзный программный проект не обходится без тестирования. Тестирование может быть ручное и автоматизированное, компонентное и системное, регулярное и не очень, но оно должно быть. А если тестирование регулярное, то вместе с ним появляются отчёты о результатах тестирования. И чем больше ваш проект, тем больше у вас данных о проведенном тестировании. В современных проектах темп разработки ПО настолько высокий, что некоторые продукты успевают релизиться несколько раз в неделю, а некоторые и несколько раз в день. При правильном подходе отчёты о тестировании могут принести много пользы при разработке. Из этой статьи вы узнаете, какая польза от отчётов о результатах тестирования, какие форматы отчётов существуют и как навести порядок с хранением и анализом таких отчётов в вашем проекте.
Больше об этой теме, а также других вопросах, связанных с тестированием ПО, читайте в моем блоге.
Зачем вообще нужны отчёты?
В каких случаях вам может потребоваться хранение отчёта о выполненном тестировании:
- оценка текущего качества проекта на основе покрытия тестами и получение ответов на вопросы: Закончено ли тестирование? Готов ли продукт к релизу? С какой скоростью разработка сходится к релизу?
- получение статистики о частоте воспроизведения дефекта;
- оценка эффективности тестов (насколько полезен тест и находит ли дефекты?);
- обмен данными между командами, если роли в команде разделены (например, разработчики и тестировщики);
- стабильность тестов и функциональности в продукте (PASS/FAIL rate) с течением времени.
К тому же данные о тестировании можно использовать для постоянного улучшения самого тестирования.
Обзор существующих форматов
Зачастую разработчики даже не задумываются о том, в каком формате тесты сохраняют отчёты. Если это простые тесты, то достаточно вывода в формате PASS/FAIL. Если это функциональные тесты, то такой информации становится недостаточно, потому что нужно сохранять логи, тайминги и другие данные о выполнении теста. Хорошо, если используется тестовый фреймворк, в котором есть поддержка одного из распространённых форматов. А если нет, то в мире появляется ещё один формат для хранения результатов тестирования.
Благодаря изобретательности инженеров в мире разработки ПО существует множество форматов отчётов. Но одни получили большее распространение, чем другие. Все форматы можно поделить на две категории:
- закрытые форматы, изобретённые компаниями для своих коммерческих продуктов;
- открытые форматы.
Это может показаться удивительным, но открытость поспособствовала распространению форматов из второй категории. Как это получилось выяснить? Я проанализировал полсотни наиболее распространённых открытых проектов и получил следующие данные: 24 проекта хранят тестовые результаты и эти данные доступны публично, половина проектов если и использует какой-то формат для тестовых отчётов, то это один из трёх форматов: TAP, JUnit и SubUnit.
Формат | Кол-во проектов |
TAP | 19 |
JUnit | 8 |
SubUnit | 3 |
Собственный | 29 |
А что с популярностью этих же форматов в коммерческих проектах? Результаты опроса об использовании форматов тестовых данных в разработке коммерческого ПО (36 голосов):
- TAP — 3%;
- JUnit — 58%;
- SubUnit — 3%;
- Другой формат — 36%.
Вообще в природе помимо форматов TAP, JUnit, SubUnit существуют и другие форматы, но я их не буду здесь рассматривать и приведу список только в качестве информационной справки: DejaGnu, Selenium, TAPOUT, Microsoft Test, HP QuickTest Professional, IBM Rational Functional Tester, Gallio Test Report, Parasoft C/C++test, Ranorex, TestRail.
Теперь подробнее о каждом из трёх форматов.
Test Anything Protocol (TAP)
Самый старый формат для представления результатов тестирования. По сути lingua franca для тестирования. Формат был создан для тестирования первой версии интерпретатора Perl в 1987 году. Позднее Tim Bunce и Andreas König написали модуль Test::Harness, что позволило использовать формат для тестирования модулей Perl. Сейчас формат имеет поддержку не только в Perl, но и в других языках программирования и фреймворках для тестирования. В 2008 году на конференции YAPC::Europe была предпринята попытка разработать IETF стандарт для TAP, но эта попытка не увенчалась успехом. Но есть текстовое описание формата на сайте testanything.org, а модули TAP::Spec::Parser и TAP::Parser::Grammar считаются референсной реализацией TAP.
Пример вывода результатов теста в формате TAP:
# Hardware architecture: x86_64 # Timestamp: 2016-06-16 06:23 (GMT+1) # TAP version 13 1..258 ok 1 - zdtm/static/conntracks # SKIP manual run only ok 2 - zdtm/static/maps03 # SKIP manual run only ok 3 - zdtm/static/mlock_setuid ok 4 - zdtm/static/groups ok 5 - zdtm/static/maps05 ok 6 - zdtm/static/pdeath_sig ok 7 - zdtm/static/xids00 ok 8 - zdtm/static/proc-self ok 9 - zdtm/static/file_fown ok 10 - zdtm/static/eventfs00 ok 11 - zdtm/static/uptime_grow # SKIP manual run only ok 12 - zdtm/static/signalfd00 ok 13 - zdtm/static/inotify_irmap ok 14 - zdtm/static/fanotify00 ok 15 - zdtm/static/session00 ok 16 - zdtm/static/rlimits00 ok 17 - zdtm/static/maps04 ok 18 - zdtm/static/pty03 ok 19 - zdtm/static/pty02 ...
Пример отчёта с дополнительными полями:
1..1 not ok 1 Wrong length --- wanted: 5 found: 4 time: 2011-02-01 00:09:01-07 extensions: files: 1.txt: name: 1.txt file-type: text/plain file-size: 43 content: c2FtcGxl ...
SubUnit
SubUnit является потоковым форматом. Изначально был разработан в 2005 году Робертом Коллинсом для юнит-тестирования. Для SubUnit доступны утилиты для анализа результатов (subunit-stats, subunit-ls и т. д.) и библиотеки для Python, C, C++ и Shell. Формат активно используется в тестировании компонентов проекта OpenStack, Linux дистрибутива Ubuntu и Samba. Есть две версии формата: первая версия хранит результаты в текстовом представлении, вторая — в двоичном. Для обоих версий доступна подробная спецификация формата.
Пример вывода результатов теста в формате SubUnit:
time: 2011-05-23 22:49:38.856075Z test: mytest.SampleTestCase.runTest failure: mytest.SampleTestCase.runTest [ Traceback (most recent call last): File "/media/windows/dev/java/qaworkspace/pythonnosetests/src/mytest.py", line 11, in runTest self.assertEqual(len(s), 4, 'Wrong length') AssertionError: Wrong length ] time: 2011-05-2322:49:38.858163Z
JUnit
xUnit — это собирательное название семейства фреймворков для модульного тестирования, структура и функциональность которых основана на SUnit, предназначавшегося для языка программирования Smalltalk. SUnit, разработанный Кентом Беком в 1998 году, получил широкую популярность и был адаптирован для множества других языков. Названия фреймворков этого семейства образованы аналогично «SUnit», обычно заменяется буква «S» на первую букву (или несколько первых) в названии предполагаемого языка («JUnit» для Java, «NUnit» для программной платформы .NET и т. д.). Несмотря на общие корни, форматы для всех фреймворков основаны на XML, но структура может отличаться (см. xunit-plugin).
Пример вывода результатов теста в формате JUnit:
<testsuites> <testsuite time="0.239100933074951" failures="10" name="access_t" tests="14" errors="1"> <testcase name="(init)" time="0.180249929428101" /> <testcase time="0.00193119049072266" name="1 - inet allow all"> <failure type="TestFailed" message="not ok 1 - inet allow all"><![CDATA[not ok 1 - inet allow all]]></failure> </testcase> <testcase name="2 - inet allow unix" time="0.00225496292114258"> <failure type="TestFailed" message="not ok 2 - inet allow unix"><![CDATA[not ok 2 - inet allow unix]]></failure> </testcase> <testcase time="0.00211286544799805" name="3 - inet deny all"></testcase> <testcase name="4 - inet deny unix" time="0.00119209289550781"> <failure type="TestFailed" message="not ok 4 - inet deny unix"><![CDATA[not ok 4 - inet deny unix]]></failure> </testcase>
Плюсы и минусы разных форматов
Несмотря на то, что все три формата создавались для одной цели — юнит-тестирования, они имеют различия. В таблице ниже проводится сравнение этих форматов.
Параметр | TAP | SubUnit | JUnit |
Человекочитаемый формат | Да | v1 — да, v2 — нет | Да? |
Независимость от языка программирования | Да | Да | Нет (несмотря на то, что форматы тестовых отчётов всех фреймворков JUnit похожи друг на друга, эти форматы имеют отличия) |
Поддерживаемые языки программирования | Perl, Python, PHP, Java, C, C++, C#, Lua, Shell, Ruby, Javascript, Pascal, PostgreSQL, Haskell, Lisp, Forth и другие | Python, C/C++, Shell | Java, .NET, C/C++, Fortran, Haskell, Perl, PHP, Python, Ruby |
Начало использования | 1988 | 2006 | 1994? |
Возможность группирования тестов по категориям или тегам | Нет (в состоянии обсуждения) | Да | Да |
Возможность расширения | Да, есть возможность добавить YAML в отчёт | Нет? | Нет? |
Документация | Cпецификация | Несколько примеров использования | Нет |
Описание спецификации | Есть референсная реализация формата в Perl модуле Test::Harness, также была попытка разработать IETF стандарт для формата TAP | Описание обоих версий формата есть в Python Package Index | Официального описания стандарта не существует, но есть XML схема для JUnit |
Поле со временем выполнения теста | Да, в YAML | Да | Да |
Поддержка расширенных статусов тестов | Нет | Нет | Нет? |
Возможность прикрепления файлов к тестовым отчётам | Да, файлы закодированные в Base64, можно добавлять в YAML | Да, можно добавлять файлы, закодированные в Base64 | Да? |
Однозначно можно сказать, что даже если у вас сейчас не стоит цель анализа результатов и разделения ролей в разработке, то имеет смысл не изобретать колесо и использовать существующие форматы для отчётов. В большинстве случаев их более чем достаточно, а поддержка каждого из них есть во всех популярных языках программирования и добавление их поддержки не потребует много времени. Тем, кому нужен анализ результатов и в чьих проектах разделяются роли, предлагаю перейти к следующей части статьи.
Инструменты для хранения и анализа результатов в тестировании ПО
Зачастую тестирование встраивают в процесс разработки с помощью инструментов непрерывной интеграции (Jenkins CI, BuildBot, Travis CI, Teamcity и т. д.) и их же используют для анализа результатов. Мой опыт показывает, что отдельные сервисы хранения и анализа результатов с возможностью интеграции с системами CI удобнее, чем плагин в одной из них. Другие опытные тестировщики это подтверждают. Хотя я понимаю, что эти два случая не показательны :)
В таблице перечислены системы для анализа отчётов о тестировании в одном из трёх стандартных форматов.
Инструмент | Пользователи | Комментарий |
Subunit2SQL | OpenStack | Формат: SubUnit. Видео, слайды, Using SubUnit2SQL with the gate |
Badger | 2ГИС | Форматы: JUnit. Видео: CodeFest, SQAdays |
Allure | Яндекс и другие | Форматы: JUnit. Расширение для Jenkins CI. |
Tapper | Амазон | Формат: TAP (Test Anything Protocol). Разработка приостановлена. |
Jenkins: Test Results Analyzer Plugin | ? | Форматы: JUnit, TAP (Test Anything Protocol). Расширение для Jenkins CI. |
testrepository | ? | Форматы: SubUnit. |
Полезные ссылки
- Список тестовых фреймворков с поддержкой xUnit и TAP
- «Because of TAP’s simplicity, it can function as a lingua franca for testing»
- Поддержка TAP в языках программирования
- История формата Test Anything Protocol
- XML vs TAP
- История формата xUnit
- Обсуждение на StackOverflow спецификации формата JUnit XML
- SubUnit vs JUnit
- Software Engineering Radio Episode 167: The History of JUnit and the Future of Testing with Kent Beck
- Выпуск 19 подкаста «Python Testing» — Python unittest with Robert Collins
- What We Learned about Continuous Integration from Analyzing 2+ Million Travis Builds
- «Первую версию JUnit в самолете во время перелёта из Цюриха в Атланту в 1997 году»
Список библиотек и инструментов с подсветкой синтаксиса стандартных тестовых форматов:
- highlight.js: SubUnit, TAP и JUnit (как XML);
- Pygments (Python syntax highlighter): TAP;
- Rouge (Ruby syntax highlighter): TAP, JUnit;
- Vim: SubUnit и JUnit (как XML);
- Emacs: TAP.