Команда ya test
предназначена для тестирования программных проектов.
Она позволяет запускать тесты, проверять корректность кода, соответствие стандартам оформления, устойчивость к ошибкам и другие аспекты.
Основные возможности команды ya test
:
- Запуск тестов — выполняет тесты, указанные в проекте.
- Описание тестов — тесты описываются в файле
ya.make
, где можно указать зависимости, параметры, теги и требования к ресурсам. - Вывод результатов — сохраняет результаты тестов, предоставляет информацию о пройденных и неудачных тестах.
- Отладка — включает режимы отладки для детального анализа проблем.
- Фильтрация тестов — позволяет запускать только выбранные тесты по имени, тегам, размеру и типу.
Команда ya test -h
или --help
выводит справочную информацию.
Используйте -hh
для отображения дополнительных опций и -hhh
для получения еще более детальной информации.
Общий синтаксис команды
ya test [OPTION]… [TARGET]…
Параметры:
[OPTION]
— параметры, уточняющие, как должны быть выполнены тесты (выбор конкретных тестов, вывод результатов и т.д.). Можно указывать несколько опций через пробел.[TARGET]
— аргументы, определяющие конкретные цели тестирования (имена тестовых наборов или индивидуальных тестов). Можно указать несколько целей через пробел.
Основные понятия
Test
— индивидуальная проверка кода на корректность, стандарты оформления и устойчивость к ошибкам.Chunk
— группа тестов, выполняемых как единственный узел в графе команд сборки.Suite
— коллекция тестов одного типа с общими зависимостями и параметрами.
Взаимосвязь между понятиями
- Тесты объединяются в
Chunk
на основе общей логики и последовательности выполнения. Chunks
группируются вSuite
, который предоставляет контексты и параметры для всех входящих в него тестов.Suite
является основной единицей для запуска и фильтрации тестов, а также отслеживания зависимостей и ошибок.
Тесты описываются в файле ya.make
.
Можно использовать макросы и опции для задания параметров и зависимостей:
DEPENDS(path1 [path2...])
— указывает зависимости проекта, которые необходимы для запуска тестов.SIZE(SMALL | MEDIUM | LARGE)
— определяет размер теста, что помогает в управлении временем выполнения и ресурсами (значения: SMALL, MEDIUM, LARGE).TIMEOUT(time)
— устанавливает максимальное время выполнения теста.TAG(tag1 [tag2...])
— добавляет теги к тестам, что помогает в их категоризации и фильтрации.REQUIREMENTS()
— указывает требования к ресурсам для выполнения тестов, такие как количество процессоров, объем памяти, использование диска и т.д.ENV(key=[value])
— устанавливает переменные окружения, нужные для выполнения тестов.SKIP_TEST(Reason)
— отключает все тесты в модульной сборке. ПараметрReason
указывает причину отключения.
В настоящее время поддерживаются два основных тестовых фреймворка для тестирования на языке C++:
unittest
— собственная разработка.gtest
— популярное решение от Google.
В дополнение к этим фреймворкам, имеется отдельная библиотека library/cpp/testing/common
, содержащая полезные утилиты, которые не зависят от конкретного фреймворка.
Для бенчмаркинга используется библиотека google benchmark
и модуль G_BENCHMARK
.
Помимо метрик от бенчмарков, можно также сообщать числовые метрики из тестов, написанных с помощью UNITTEST()
и GTEST()
. Для добавления метрик используйте функцию testing::Test::RecordProperty
, если работаете с gtest
, или макрос UNIT_ADD_METRIC
, если работаете с unittest
.
Пример объявления метрик в gtest
:
TEST(Solver, TrivialCase) {
// ...
RecordProperty("num_iterations", 10);
RecordProperty("score", "0.93");
}
Пример объявления метрик в unittest
:
Y_UNIT_TEST_SUITE(Solver) {
Y_UNIT_TEST(TrivialCase) {
// ...
UNIT_ADD_METRIC("num_iterations", 10);
UNIT_ADD_METRIC("score", 0.93);
}
}
Для написания тестов вам потребуется создать ya.make
файл с минимальной конфигурацией:
UNITTEST() | GTEST() | G_BENCHMARK()
SRCS(tests.cpp)
END()
Основным фреймворком для написания тестов на Python является pytest.
Поддерживаемые версии Python:
- Python 2 (используется макрос
PY2TEST
, но считается устаревшим). - Python 3 (используется макрос
PY3TEST
). - Python 2/3 совместимые тесты (используется макрос
PY23_TEST
).
Все тестовые файлы перечисляются в макросе TEST_SRCS()
.
Пример конфигурационного файла ya.make
:
PY3TEST() # Используем pytest для Python 3 (PY2TEST будет означать Python 2)
PY_SRCS( # Зависимости тестов, например, абстрактный базовый класс теста
base.py
)
TEST_SRCS( # Перечисление всех файлов с тестами
test.py
)
SIZE(MEDIUM)
END()
Чтобы сообщить метрики из теста, необходимо использовать funcarg metrics
.
def test(metrics):
metrics.set("name1", 12)
metrics.set("name2", 12.5)
Для программ, собранных с использованием макросов PY2_PROGRAM
, PY3_PROGRAM
, PY2TEST
, PY3TEST
, PY23_TEST
, автоматически выполняется импорт-тест:
- Проверка корректности импортов позволяет выявить конфликты и отсутствующие зависимости.
- Импорт-тест может быть отключен с помощью макроса
NO_CHECK_IMPORTS()
.
Пример отключения проверки:
PY3TEST()
PY_SRCS(
base.py
)
TEST_SRCS(
test.py
)
SIZE(MEDIUM)
NO_CHECK_IMPORTS() # Отключить проверку импортируемости библиотек из PY_SRCS
NO_CHECK_IMPORTS( # Отключить проверку импортируемости только в указанных модулях
devtools.pylibrary.*
)
END()
Бывает, что в библиотеках есть импорты, которые происходят по какому-то условию:
if sys.platform.startswith("win32"):
import psutil._psmswindows as _psplatform
Если импорт-тест падает в таком месте, можно отключить его следующим образом:
NO_CHECK_IMPORTS( # Отключить проверку
psutil._psmswindows
)
Для тестирования проектов на Java в данной системе используются фреймворки JUnit
версий 4.x
и 5.x
.
Тестовый модуль для JUnit4
описывается модулем JTEST()
или JTEST_FOR(path/to/testing/module)
.
JTEST()
— система сборки будет искать тесты вJAVA_SRCS()
данного модуля.JTEST_FOR(path/to/testing/module)
— система сборки будет искать тесты в тестируемом модуле.
Для включения JUnit5
вместо JTEST()
необходимо использовать JUNIT5()
.
Настройка тестирования осуществляется посредством ya.make
файлов.
Минимальный ya.make
файл выглядит так:
- JUnit4
JTEST() JAVA_SRCS(FileTest.java) PEERDIR( # Сюда же необходимо добавить зависимости от исходных кодов вашего проекта contrib/java/junit/junit/4.12 # Сам фреймворк JUnit 4 contrib/java/org/hamcrest/hamcrest-all # Можно подключить набор Hamcrest матчеров ) END()
- JUnit5
JUNIT5() JAVE_SRCS(FileTest.java) PEERDIR( # Сюда же необходимо добавить зависимости от исходных кодов вашего проекта contrib/java/org/junit/jupiter/junit-jupiter # Сам фреймворк JUnit 5 contrib/java/org/hamcrest/hamcrest-all # Набор Hamcrest матчеров ) END()
Тестирование в Go базируется на стандартном инструментарии для Go. Для работы с зависимостями теста рекомендуется использовать библиотеку library/go/test/yatest
.
Все тестовые файлы должны иметь суффикс _test.go
. Они указываются в макросе GO_TEST_SRCS
.
Тестовый модуль описывается модулем GO_TEST()
или GO_TEST_FOR(path/to/testing/module)
.
GO_TEST()
— система сборки будет искать тесты вGO_TEST_SRCS()
данного модуля.GO_TEST_FOR(path/to/testing/module)
— система сборки будет искать тесты вGO_TEST_SRCS
в тестируемом модуле.
Минимальные ya.make
файлы выглядят так:
-
GO_TEST()
GO_TEST() GO_TEST_SRCS(file_test.go) END()
-
GO_TEST_FOR()
В
project/ya.make
в макросеGO_TEST_SRCS
перечисляются тестовые файлы:GO_LIBRARY() | GO_PROGRAM() SRCS(file.go) GO_TEST_SRCS(file_test.go) END() RECURSE(tests)
При запуске тестов в локальной среде разработки необходимо учитывать несколько ключевых моментов.
- Все тесты запускаются в режиме отладки (
debug
). - Таймаут выполнения тестов зависит от их размеров: SMALL, MEDIUM или LARGE.
- Результаты тестов сохраняются в директорию
test-results
. Внутри нее находятся поддиректории с логами и файлами, порожденными тестами. - Если тесты завершились неуспешно, в консоль выводится информация о путях к результатам.
Кроме того, для корректной работы некоторых тестов необходимо наладить их взаимодействие с тестовым окружением.
Для простого запуска тестов есть следующие ключи командной строки:
-t
— запустить только SMALL тесты.-tt
— запустить SMALL и MEDIUM тесты.-ttt
,-A
,--run-all-tests
— запустить тесты всех размеров.--test-param=TEST_PARAM
— параметризовать тесты значениями из командной строки.TEST_PARAM
имеет видname=val
, доступ к параметрам зависит от используемого фреймворка.--retest
— принудительный перезапуск тестов без использования кеша.
Пример
$ ya test -t devtools/examples/tutorials/python
Запустит все тесты, которые найдет по RECURSE
/RECURSE_FOR_TESTS
от devtools/examples/tutorials/python
, включая тесты стиля и тесты импорта для Python.
Использует следующие умолчания для сборки:
- Платформа будет определена по реальной платформе, на которой запущена команда
ya test
. - Тесты будут собраны в режиме
debug
— он используется по умолчанию. - Кроме тестов будут собраны все остальные цели (библиотеки и программы), достижимые по
RECURSE
/RECURSE_FOR_TESTS
отdevtools/examples/tutorials/python
. Это включает сборку всех необходимых зависимостей.
По умолчанию система сборки выполнит все запрошенные тесты. После их завершения для всех упавших тестов будет предоставлена краткая информация о провалах, включая ссылки на подробные данные. Для успешных и проигнорированных тестов будет выведен только общий статус с указанием их количества.
Команда ya test
предоставляет несколько опций для управления выводом результатов тестирования.
Эти опции позволяют контролировать объем информации, которые возвращаются после запуска тестов, и помогают быстрее находить и исправлять ошибки:
-L
,--list-tests
— выводит список тестов, которые будут выполнены.
ya test -tL
--fail-fast
— завершает выполнение тестов при первой неудаче.
ya test -t --fail-fast
-P
,--show-passed-tests
— показать пройденные тесты.
ya test -t --show-passed-tests
--show-skipped-tests
— показать пропущенные тесты.--show-metrics
— показать метрики тестов.
В конце выполнения тестов для всех упавших тестов будет выдана краткая информация о невыполнении (включая ссылки на более полную информацию). Для прошедших и проигнорированных (отфильтрованных) тестов будет выдан только общий короткий статус с количеством тех и других тестов.
Примеры полного отчета при использовании различных опций:
ya test -t --show-passed-tests --show-skipped-tests --show-metrics
В этом примере выводится информация обо всех успешно пройденных тестах, отфильтрованных тестах, а также метрики тестирования, что дает полный обзор выполненных действий и результатов тестирования.
Пример
# Список всех пользовательских тестов (без тестов стиля, импортов и подобных проверок)
ya test -AL --regular-tests devtools/examples/tutorials/python
Команда ya test
поддерживает параллельный запуск тестов.
Команда ya test
предлагает несколько опций для отладки:
--test-debug
— включить режим отладки тестов (PID, дополнительные параметры).--pdb
,--gdb
,--dlv
— запустить тесты с интеграцией в различные отладчики (для Python, C++, Go).
Команда ya test
поддерживает большое количество опций для фильтрации и выборочного запуска тестов.
Фильтрация тестов:
-F=TESTS_FILTERS
,--test-filter=TESTS_FILTERS
— запуск только определенных тестов по имени, шаблону или фильтру.
ya test -A -F "subname"
В фильтрах можно использовать символы подстановки, такие как *
, который соответствует любому количеству символов.
Каждый последующий фильтр расширяет множество тестов для запуска.
$ ya test -t -F <file>.py::<ClassName>::*
--test-tag=TEST_TAGS_FILTER
— запуск тестов, помеченных определенными тегами.
ya test -A --test-tag tag1+tag2-tag3
Эта команда запустит все тесты, у которых есть теги tag1
и tag2
и нет тега tag3
.
--test-size=TEST_SIZE_FILTERS
— запуск тестов определенного размера (SMALL, MEDIUM, LARGE).
ya test -A --test-size=MEDIUM
--test-type=TEST_TYPE_FILTERS
— запуск тестов определенного типа (например,UNITTEST
,PYTEST
).
ya test -tt --test-type unittest+gtest
Эта команда запустит только тесты типов unittest
и gtest
.
--test-filename=TEST_FILES_FILTER
— запуск тестов из указанного исходного файла.
ya test -A --test-filename=test_example.py
-X
,--last-failed-tests
— запустить только тесты, упавшие в предыдущем запуске.--regular-tests
— запустить только пользовательские тесты.--style
— запустить только тесты стиля.
В системе сборки имеются разнообразные инструменты для проверки кода и данных, которые гарантируют соответствие стандартам качества, стиля и безопасности. Эти инструменты включают линтеры, статический анализ и другие средства, предназначенные для различных языков программирования.
Для языка Python, flake8
автоматически проверяет стиль кода для всех подключенных через ya.make
файлов
в секциях PY_SRCS
и TEST_SRCS
, включая плагины для проверки длины строки до 200 символов
и игнорирование ошибок с помощью комментариев # noqa
или # noqa: E101
.
Ошибку F401
можно подавить в файле __init__.py
с помощью # flake8 noqa: F401
.
Для директории contrib
можно отключить проверку стиля через макрос NO_LINT()
.
Для проектов на Python 3 линтер black
подключается с помощью макроса STYLE_PYTHON()
, который генерирует тесты для проверки стиля кода.
Запустить тесты black
можно командой:
ya test -t --test-type black.
Импорт-тесты проверяют импортируемость программ Python, собранных из модулей, обнаруживая конфликты и отсутствующие файлы.
Эти проверки называются import_test
, они не являются style-тестами
, так как такие тесты требуют сборку.
Отключить проверку стиля можно с помощью NO_CHECK_IMPORTS
, указав конкретные исключения.
Для исходных файлов на Java, стиль кода проверяется утилитой checkstyle
на обычном и строгом уровнях, последний включается макросом LINT(strict)
, а конфигурационные файлы хранятся в директории resource
.
Опционально можно проверить наличие дублирующихся классов в classpath
с помощью макроса CHECK_JAVA_DEPS(yes)
.
Проекты на Kotlin
автоматически проверяются утилитой ktlint
для стиля кода.
Проверку можно отключить через макрос NO_LINT(ktlint)
в файле сборки, а исключения можно добавить через макрос KTLINT_BASELINE_FILE
.
Для проектов на Go используются инструменты gofmt
для проверки стиля кода и govet
для статического анализа подозрительных конструкций и антипаттернов.
Для кода на C++ применяется clang-tidy
, который используется для статического анализа.
Его можно запустить с флагом ya test -t -DTIDY
.
Пример ya.make
файла с проверками стиля может выглядеть так:
PY3_LIBRARY()
PY_SRCS(
src/init.py
src/module.py
)
STYLE_PYTHON()
NO_CHECK_IMPORTS(
devtools.pylibrary.
)
END()
Для некоторых типов тестов в системе сборки поддерживается механизм сравнения с эталонными (каноническими) данными.
- Канонические данные — эталонные данные, с которыми сравниваются результаты теста.
- Канонизация — процесс обновления эталонных данных для соответствия текущим результатам тестов.
- Переканонизация — повторная канонизация, проводимая для обновления эталонных данных после изменения тестов или их окружения.
Если данные нужно обновить, воспользуйтесь опцией
-Z
(--canonize-tests
).
При локальном запуске эталонные данные будут сохраняться в подкаталог canondata
рядом с тестом.
Система позволяет собирать инструментированные программы с санитайзерами.
Поддерживаются санитайзеры AddressSanitizer
, MemorySanitizer
, ThreadSanitizer
, UndefinedBehaviorSanitizer
и LeakSanitizer
.
Запуск с санитайзером:
ya test -t --sanitize=address
Для правильной работы санитайзеров можно зафиксировать опции для конкретных тестов через макрос ENV()
.
Фаззинг позволяет передавать приложению на вход неправильные, неожиданные или случайные данные.
Автоматический фаззинг поддерживается через libFuzzer
.
Пример запуска фаззинга:
ya test -r --sanitize=address --sanitize-coverage=trace-div,trace-gep -A --fuzzing
Во время фаззинга записываются различные метрики, такие как размер корпуса, количество проверенных кейсов, пиковое потребление памяти и другие.
Exec-тесты предоставляют возможность выполнять произвольные команды и проверять их успешное завершение, которое считается таковым при коде возврата 0
.
Эти тесты особенно полезны для проверки отдельных скриптов, командной строки или сложных сценариев, которые трудно реализовать с помощью стандартных тестовых фреймворков.
Описание таких тестов также осуществляется в файле ya.make
.
EXECTEST() # Объявление Exec-теста
RUN( # Команда, которую хотим выполнить
cat input.txt
)
DATA( # Тестовые данные, которые необходимы для выполнения команды (здесь лежит input.txt)
PROJECT/devtools/ya/test/tests/exectest/data
)
DEPENDS( # Зависимость от других проектов (например, исходные коды cat)
devtools/dummy_PROJECT/cat
)
# Текущий каталог для теста (каталог с input.txt)
TEST_CWD(devtools/ya/test/tests/exectest/data)
END()
Типом теста называется выполнение проверок с использованием одного конкретного инструмента, например, фреймворка pytest
для Python или утилиты проверки форматирования кода go fmt
для Golang.
Полный список типов тестов приведен в таблице:
Тип | Описание |
---|---|
black |
Проверка форматирования кода на Python 3 утилитой black . |
classpath.clash |
Проверка наличия дублирующихся классов в classpath при компиляции Java-проекта. |
eslint |
Проверка стиля и типичных ошибок кода на TypeScript с использованием утилиты ESLint . |
exectest |
Выполнение произвольной команды и проверка ее кода возврата. |
flake8.py2 |
Проверка стиля кода на Python 2 c использованием утилиты Flake8 . |
flake8.py3 |
Проверка стиля кода на Python 3 c использованием утилиты Flake8 . |
fuzz |
Fuzzing тест. |
g_benchmark |
Выполнение бенчмарков на C++ библиотекой Google Benchmark. |
go_bench |
Выполнение бенчмарков на Go утилитой go bench . |
gofmt |
Проверка форматирования кода на Go утилитой go fmt . |
go_test |
Выполнение тестов на Go утилитой go test . |
govet |
Выполнение статического анализатора кода на Go утилитой go vet . |
gtest |
Выполнение тестов на С++ с использованием фреймворка Google Test. |
java |
Выполнение тестов на Java с использованием фреймворка JUnit. |
java.style |
Проверка форматирования кода на Java утилитой checkstyle. |
ktlint |
Проверка стиля Kotlin кода с использованием утилиты ktlint. |
py2test |
Тесты на Python 2 с использованием фреймворка pytest. |
py3test |
Тесты на Python 3 с использованием фреймворка pytest. |
pytest |
Тесты на Python любой версии с использованием фреймворка pytest. |
unittest |
Тесты на C++ с использованием фреймворка unittest . |