Написание сложного макроса препроцессора для модульного тестирования - PullRequest
1 голос
/ 25 марта 2010

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

Для нормальной компоновки требуется один блок кода модульного тестирования для каждого ожидаемого значения.

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

Вот блок тестового кода, который мне нужно продублировать X раз:

START_TEST("test_CallbackFn");

EXPECTED_CALLS("{{function1(param_type)#default}{function2(param_type)#default}}");

CallbackFn();

END_CALLS();
END_TEST();

Теперь вот что я хотел бы представить

for (int i = 0; i < 10; i++)
{
  RUN_TEST(i)
}

Теперь я хотел бы определить RUN_TEST с кодом, который я упоминал выше, за исключением того, что мне нужно заменить строку default на текущее значение i . Что меня отталкивает, так это кавычки и #, которые присутствуют в существующем макросе EXPECTED_CALLS.

Ответы [ 4 ]

2 голосов
/ 25 марта 2010

Я думаю, что я хотел бы взглянуть на использование отдельного макропроцессора, а не пытаться превратить препроцессор C в представление. Классический пример, на который указывают люди, - m4, но для этого вам лучше использовать awk, perl, python или что-то подобное.

1 голос
/ 25 марта 2010

По моему опыту, "сложный" + "макрос" = "не делай этого!"

Препроцессор C не был разработан, чтобы делать что-то настолько мощное. Хотя вы можете выполнять кунг-фу и взламывать что-то вместе, что работает, было бы намного проще использовать язык сценариев для генерации кода на C (также легче отлаживать, так как вы можете читать сгенерированный код и убедитесь, что это правильно). Лично я использовал Ruby для этого несколько раз, но Python, Perl, bash (и т. Д.) Также должны работать.

0 голосов
/ 25 марта 2010

Возможно, это возможно: Boost.Preprocessor впечатляет.

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

Проблема генеративного подхода с использованием внешних сценариев заключается в том, что может потребоваться экстернализировать не только тесты. Если вы не планируете реализовать синтаксический анализатор C ++, который, как известно, является хитрым в лучшие времена ...

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

0 голосов
/ 25 марта 2010

Я не уверен, что полностью понимаю вопрос, но если вы хотите, чтобы EXPECTED_CALLS получил строку, где default заменяется на строковое значение любого значения по умолчанию, вам нужно удалить #default из строки. т.е.

EXPECTED_CALLS("{{function1(param_type)#default}{function2(param_type)#default}}"); 

должно быть

EXPECTED_CALLS("{{function1(param_type)"#default"}{function2(param_type)"#default"}}"); 
...