Voglio testare le funzioni in C che manipolano un array. Ma le soluzioni che trovo mi fanno sentire un po 'a disagio.
Parliamo prima delle limitazioni: sto usando una struttura dichiarata in avanti che è un puntatore a un tipo di struttura di cui il mio test non dovrebbe essere a conoscenza (solo la mia implementazione conosce i dettagli reali della struttura). Questo è per assicurarsi che gli utenti, io oi miei test interagiscano solo con la lista usando le funzioni da programmare.
Il motivo per cui mi sento a disagio per la mia soluzione è il seguente:
Creo un primo test che verifica che l'elenco sia vuoto durante la creazione. Ho una funzione TaskList_Create (). "Abbastanza male" la memoria è già inizializzata con 0. Quindi non posso davvero fare la differenza tra la memoria così com'era e inizializzata 0 da TaskList_Create ().
Tutto ciò mi porta a creare un'altra funzione senza testarla. Vale a dire TaskList_AddTask ().
#include "TaskList.h"
TEST_GROUP(TaskList)
{
TaskList tl;
void setUp(void)
{
tl = TaskList_Create(4); /* 4 elements in size */
}
void tearDown(void)
{
TaskList_Destroy(tl);
}
}
TEST(TaskList, Create_willInitializeListEmpty_v1)
{
TaskList_AddTask(tl); /* returns non-zero value (PID) */
TaskList_AddTask(tl); /* ... */
TaskList_AddTask(tl);
CHECK_EQUAL(4, TaskList_AddTask(tl));
CHECK_EQUAL(0, TaskList_AddTask(tl));
}
TEST(TaskList, Create_willInitializeListEmpty_v2)
{
CHECK_EQUAL(1, TaskList_IsEmpty(tl));
}
TEST(TaskList, Create_willInitializeListEmpty_v3)
{
CHECK_EQUAL(0, TaskList_TasksInstalled(tl));
}
Uso TaskList_AddTask () sull'elenco creato N + 1 volte, dove N è la dimensione della lista. Questo mi permetterebbe di verificare che l'elenco sia vuoto dopo TaskList_Create (), poiché l'ultima chiamata a TaskList_AddTask () restituirebbe un qualche tipo di errore (per il quale non ho ancora un test ... urg!).
Il modello che si presenta durante questo tipo di sviluppo è che dovrò sempre creare una funzione non testata che mi aiuterà a testare la funzione effettiva che volevo testare in primo luogo.
Creo TaskList_AddTask () per testare effettivamente TaskList_Create () o scrivo TaskList_IsEmpty ().
Un altro problema: voglio testare TaskList_DeleteTask (), che mi fa scrivere TaskList_AddTask ().
TEST(TaskList, DeleteTask)
{
uint8_t pid;
TaskList_AddTask(tl);
TaskList_AddTask(tl);
TaskList_AddTask(tl);
pid = TaskList_AddTask(tl);
TaskList_DeleteTask(tl, pid);
CHECK_EQUAL(4, TaskList_AddTask(tl));
}
Oppure: Voglio testare che TaskList_Add () trovi e ricicla gli slot nell'elenco che sono stati precedentemente cancellati, il che mi costringe a scrivere TaskList_DeleteTask ().
In breve: non mi sento a mio agio a dover scrivere una seconda funzione che non è stata testata per testare un'altra funzione.
Non sono proprio sicuro che fingere / beffarsi l'aiuterebbe. Diciamo, per testare TaskList_DeleteTask () senza avere o usando TaskList_AddTask () avrei un FakeTaskList_Create () che potrei passare un numero che specifichi il numero di elementi che dovrebbero già essere contenuti nella lista, solo in ordine per testare la mia funzione TaskList_DeleteTask ().
Non ne so molto degli anti-pattern di TDD, ma quello che sto facendo in questo momento mi sembra sicuro.
Qualsiasi consiglio davvero benvenuto!
FYI (ma non dovrebbe essere importante):
typedef struct TaskStruct {
void (*fp)(void);
uint16_t periode;
uint16_t delay;
uint8_t run;
} TaskStruct;
typedef TaskList TaskStruct *;