Questo è un problema che ho cercato di riprendere da un paio di mesi. È apparso di nuovo in un progetto di apprendimento a cui stavo lavorando ieri sera, quindi lo userò come esempio.
Sto costruendo un sistema di componenti di entità e un sistema di movimento che controlla il movimento di ogni entità in ogni turno.
class MovementSystem {
private:
vector<PositionComp> positions;
vector<MoveAIComp> moveAIs;
vector<vector<bool> > generateMap()
{
// Cycle through all positions and generates a 2D array
// detailing whether each map space is occupied or not
}
void updateComps(vector<vector<bool> > map)
{
// For each entity generates a 3x3 array from map, centered
// at that entity's position, passes it to
// moveAI.getMove(surroundings), then updates the position
}
public:
void update(Turn turn)
{
map = this->generateMap();
this->updateComps(map);
}
};
Ora il collaudo di alcune di queste funzionalità è abbastanza facile. Aggiungo una posizione e sposta il componente AI nel sistema. Il componente moveAI è un oggetto fittizio che restituisce una specifica mossa che ho specificato nel test, quindi richiama l'aggiornamento sul sistema e mi assicuro che la posizione modificata nel modo in cui si supponeva fosse.
Il problema con questo è che ho saltato l'intera chiamata a generateMap()
e la prima parte di updateComps
che crea l'array 3x3. Certo, ho verificato che la posizione sia correttamente aggiornata in base alla decisione presa da moveAI, ma non ho verificato che moveI abbia le informazioni corrette per prendere questa decisione.
Finora ho trovato alcuni modi per ovviare a questo:
- Cambia il mio mock
MoveAIComponent
per memorizzare gli input ingetMove
, così posso verificarli anche nel test. - Il mio
MovementSystem
potrebbe fare troppo, quindi dovrei dividerlo in due, unMapSystem
che genera la mappa e aggiorna un nuovoSurroundingsComponent
, quindi cambiareMovementSystem
per usare i dintorni, la posizione e moveAI, consentendo test suMapSystem
per coprire tale funzionalità. - Lascia il test di quella funzionalità per i test di integrazione, quando userò oggetti
MoveAIComponent
reali che si preoccupano dell'ambiente.
Nessuna di queste opzioni mi piace particolarmente. 1. aumenta notevolmente la complessità sia dei miei test che della mia classe mock in quanto ho bisogno di aggiungere degli asserzioni per garantire che l'input sia corretto e mettere in cache ogni chiamata agli oggetti mock. 2. si sente come l'interfaccia gonfia. Poiché surroundings
è utilizzato solo all'interno di MovementComponent
, perché dovrei creare componenti extra longevi per tracciare quelli che sono dati temporanei, transitori e di uso singolo? E infine 3. Non mi piace per lo stesso motivo di 1, tranne peggio. I test potrebbero ora fallire per due motivi: il surroundings
non è corretto quando viene passato a moveAI
o il moveAI
sta prendendo una decisione inaspettata.
Quindi, più in generale, quando si ha una classe che genera dati che vengono passati solo più in profondità nello stack e non viene mai restituita verso l'alto, quale miglior modo per testare tale funzionalità. Ovviamente sono aperto a suggerimenti / ridisegni a cui non ho pensato.