tgoop.com/cxx95/106
Last Update:
#compiler
Простые тесты для C++ кода на Python
Часто хочется покрыть тестами код на C++ в проекте - не логику, которую описывает код, а сам исходный код. Сейчас для этого есть приличное количество чекеров в clang-tidy. Можно написать свой чекер, который все равно будут ревьюить много месяцев и КПД всего этого занятия близок к нулю. Для специфических проверок надо что-то колхозить самому.
Примерных проверок может быть много:typeid(x).name()
, потому что он дает mangled имя, с советом использовать костыль, который отдаст demangled имя.
Можно придумать проверку на примере лямбд
int counter = 15;В этом примере лямбда использует внешнюю переменную, которая влияет на логику.
const auto addEvent = [&counter](int number) {
if (counter > 0) {
// do something...
--counter;
}
};
// ... call the lambda
addEvent(1337);
Если переменная используется только внутри лямбды, то ее можно вкостылить прямо в capture list. Тогда вместо двух верхних строк примера будет такая строка, дающая аналогичный результат:
auto addEvent = [counter = 15](int number) mutable {Такой же подход работает для переменных любых типов. Если интересно, что происходит внутри лямбд, то можно почитать целую книгу про них.
Попробуем сделать тест на такие кейсы
LambdaExpr
.VarDecl
.DeclRefExpr
.LambdaExpr
, а "объявление переменной" находится вне этого LambdaExpr
, то тест должен упасть, потому что данную переменную можно всунуть в capture list лямбды.Этот тест можно сделать на
Поддерживается libclang в Python, и после просмотра примеров можно поставить его себе:
pip install pytestи сделать такой простой тест, где реализуется описанная проверка для лямбд. Можно в директории рядом сохранить тестовый файл source.cpp и проверить, что тест падает:
pip install clang
pip install libclang
python3 -m pytest test.pyВывод:
E Failed: These variables can be declared in lambda capture:libclang на Python выглядит нормально, но неприятно то, что для понятия "нода AST" не к месту придумали новый термин "курсор".
E "counter" (at source.cpp:3:44), to lambda at source.cpp:4:88
Также не хватает некоторых очевидных фичей, например получения родительской ноды: в курсорах есть пара ссылок на другие курсоры (типа родительские, двух видов), но они работают неправильно.
Кроме тестов можно писать другие тулзы, например "кодогенераторы" - которые сгенерируют какой-нибудь исходник на основе существующего кода. Про кодогенераторы можно почитать лонгрид.
Еще можно делать "исправляторы" исходников - которые берут AST, что-то туда дописывают и сохраняют в другой файл, а компилятор имеет дело с уже поправленным AST (то есть с этим другим файлом).