Замена определения на "тестовое" определение в CppUTest
Возможно ли и, если возможно, каким образом заменить определенное определение определением, которое находится под контролем тестовой структуры?
Например, скажем, встроенная система использует определение для доступа к порту следующим образом:
#define PORTA_CONFIG (*(volatile unsigned int*) (0x1000))
Теперь я хочу убедиться, что мой "модуль порта" может правильно читать / писать в указанный PORTA_CONFIG. Как мне пойти на замену PORTA_CONFIG
с чем-то вроде:
volatile unsigned int PORTA_CONFIG;
3 ответа
Для производственного кода вы используете:
//porta_config.h
...
#define PORTA_CONFIG (*(volatile unsigned int*) (0x1000))
В то время как в вашем тестовом проекте вы используете другой заголовок:
//porta_config_test.h
...
volatile unsigned int PORTA_CONFIG;
Как и в ответе AudioDroid, вы можете использовать разные заголовки, включенные в один "заголовок фасада":
Подход включения (Test double)
portconfig.h заголовок для включения данных - в зависимости от того, какая цель вам нужна (или если вы используете ее для тестирования)
#ifndef PORTCONFIG_H
#define PORTCONFIG_H
#ifdef TARGET_A
# include <portconfig_target_a.h> /* Use the config for target A */
#elif defined TARGET_B
# include <portconfig_target_b.h> /* Use the config for target B */
#elif defined TEST
# include <portconfig_testing.h> /* Use this instead for testing */
#else
# error "Not supported!" /* Just in case ... */
#endif
#endif /* PORTCONFIG_H */
Каждый из этих заголовочных файлов содержит эти "определения", так как они требуются целью, например.
portconfig_target_a.h
...
#define PORTA_CONFIG (*(volatile unsigned int*) (0x1000))
...
или же
portconfig_testing.h
...
volatile unsigned int PORTA_CONFIG;
...
Это требует #ifdef
только в одном центральном месте и поэтому требует меньших усилий по обслуживанию. Также нет никакой разницы в использовании целевого / тестового кода, #include <portconfig.h>
используется во всех случаях.
Абстракция подход
Вместо того, чтобы использовать PORTA_CONFIG
напрямую, вы также можете абстрагировать его в функцию / макрос. Для тестирования вы можете издеваться над этим.
typedef IOAddress ...
IOData IOData ...
void writePort(IOAddress addr, IOData data);
IOData readPort(IOAddress);
Это имеет преимущество абстракции и очень полезно для тестирования.
В этом репозитории есть реализация и несколько отличных примеров, особенно code
(MockIO, заголовок, реализация, пример теста) - с использованием CppUTest.
Смотрите также
- #include Test Double
- Разработка через тестирование для Embedded C (Джеймс Греннинг)
- Тестирование кода для встроенного приложения
Если я правильно понимаю ваши намерения, вы можете сделать что-то вроде:
#define TESTING
int main(){
#ifdef TESTING
volatile unsigned int PORTA_CONFIG;
#else
#define PORTA_CONFIG (*(volatile unsigned int*) (0x1000))
#endif