Funzioni per la gestione di elenchi di guida di prova

-2

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 *;
    
posta lazlo 26.06.2017 - 11:33
fonte

2 risposte

1

Bad enough the memory is already initialized with 0. So I can't really make a difference between memory as it was and it being initialized 0 by TaskList_Create().

In genere, ciò si verifica solo in una build di debug. Se esegui i test con ottimizzazione completa, la memoria verrà lasciata non inizializzata dopo l'allocazione.

The pattern that arises during this kind of development is that I will always have to create a untested function that will help me test the actual function I wanted to test in the first place.

Definire le condizioni pre e post per ciascuna funzione e quindi scrivere un test per ogni post-condizione. È quindi possibile prima testare le post-condizioni "base" di ciascuna funzione prima di testare la loro interazione.

    
risposta data 29.06.2017 - 07:33
fonte
0

Per come la vedo io, le funzioni del tuo compito eseguono cambiamenti sulle strutture in memoria. Idealmente vorrai "prendere in giro la memoria" (analogo al modo in cui potresti prendere in giro un database se le tue funzioni funzionassero su un database anziché su una memoria). Quindi potresti andare in due modi, a seconda di come sono costruiti i tuoi mock. Puoi controllare lo stato (ad esempio inizializzare la tua memoria mocked su 0xff e assicurarti dopo aver chiamato TaskList_CreateTask (), il primo segmento è 0x00 oppure controllare che le funzioni giuste vengano chiamate contro il mock (memset (0) ecc.) .

Vorrei poter inserire alcuni esempi di codice, ma non sono un esperto di C (C # è la mia lingua preferita). Il meglio che posso fare è indirizzarti a questo google ricerca. Potrebbero esserci alcuni framework di simulazione C che faranno esattamente quello che ti serve.

    
risposta data 27.06.2017 - 14:03
fonte

Leggi altre domande sui tag