Unit test -- especially in C++ -- require from the code under test to add more seams that would be strictly called for for a given problem.
Solo se non consideri di testare una parte integrale del problem solving. Per qualsiasi problema non banale, dovrebbe essere, non solo nel mondo del software.
Nel mondo dell'hardware, questo è stato appreso molto tempo fa - nel modo più duro. I produttori di varie apparecchiature hanno imparato attraverso i secoli innumerevoli ponti che cadono, macchine che esplodono, CPU che fumano, ecc. Ecc. Cosa stiamo imparando ora nel mondo del software. Tutti loro costruiscono "cuciture extra" nei loro prodotti per renderli testabili. La maggior parte delle nuove auto al giorno d'oggi dispone di porte diagnostiche per i riparatori per ottenere dati su ciò che accade all'interno del motore. Una parte significativa dei transistor su ogni CPU serve a scopi diagnostici. Nel mondo dell'hardware, ogni parte dei costi "extra" della roba e quando un prodotto è prodotto da milioni, questi costi sicuramente sommano a ingenti somme di denaro. Tuttavia, i produttori sono disposti a spendere tutti questi soldi per la testabilità. Probabilmente hanno capito (o imparato nel modo più duro) che il rischio che il loro prodotto fallisca nelle mani (o sotto i barboni) degli utenti finali e la conseguente perdita di reputazione, cause legali, cattive pubbliche relazioni ecc. Ecc. Ecc. superiore al costo di progettare e rendere testabile il prodotto fin dall'inizio.
Tornando al mondo del software, il C ++ è in effetti più difficile da testare unitamente ai linguaggi successivi con caricamento dinamico delle classi, riflessioni, ecc. Tuttavia, la maggior parte dei problemi può essere almeno mitigata. Nell'unico progetto C ++ in cui ho utilizzato i test unitari finora, non abbiamo eseguito i test tutte le volte che avremmo fatto ad es. un progetto Java - ma ancora facevano parte della nostra build CI e li abbiamo trovati utili.
Is the way that Unit Tests require one to structure an application's code "only" beneficial for the unit tests or is it actually beneficial to the applications structure?
Nella mia esperienza, un design verificabile è benefico in generale, non "solo" per i test unitari stessi. Questi vantaggi si presentano su diversi livelli:
- Rendere testabile la tua progettazione ti obbliga a mettere la tua applicazione in parti piccole, più o meno indipendenti che possono influenzarsi a vicenda solo in modi limitati e ben definiti - questo è molto importante per la stabilità e la manutenzione a lungo termine del tuo programma. Senza questo, il codice tende a deteriorarsi in codice spaghetti in cui qualsiasi modifica apportata in qualsiasi parte della base di codice può causare effetti imprevisti in parti distinte del programma apparentemente non correlate. Il che è, inutile dirlo, l'incubo di ogni programmatore.
- Scrivere gli stessi test in modo TDD in realtà esercita le API, le classi e i metodi e serve come test molto efficace per rilevare se il tuo progetto ha un senso - se scrivere test contro e interfaccia risulta imbarazzante o difficile, ottieni preziosi feedback iniziali quando è ancora semplice modellare l'API. In altre parole, questo ti impedisce di pubblicare le tue API prematuramente.
- Il modello di sviluppo applicato da TDD ti aiuta a concentrarti sui compiti concreti da fare e ti tiene in mira, riducendo al minimo le possibilità che tu vada a risolvere altri problemi oltre a quello che dovresti, aggiungendo un extra non necessario caratteristiche e complessità, ecc.
- Il feedback rapido dei test unitari ti consente di essere audace nel refactoring del codice, permettendoti di adattare e evolvere costantemente il design per tutta la durata del codice, evitando così efficacemente l'entropia del codice.
I remember a rule of thumb that said don't generalize until you need to / until there's a second place that uses the code. With Unit Tests, there's always a second place that uses the code -- namely the unit test. So is this reason enough to generalize?
Se puoi dimostrare che il tuo software fa esattamente quello che dovrebbe fare - e dimostralo in un modo veloce, ripetibile, economico e deterministico per soddisfare i tuoi clienti - senza la generalizzazione o le cuciture "extra" forzate dai test unitari, provaci (e facci sapere come lo fai, perché sono sicuro che molte persone su questo forum sarebbero interessate come me: -)
Come suppongo per "generalizzazione" intendi cose come introdurre un'interfaccia (classe astratta) e polimorfismo invece di una singola classe concreta - se non, per favore chiarisci.