Quanto bene sto scrivendo i miei test?

6

Ho iniziato a lavorare come codificatore per circa 2 anni, ma sto scrivendo i miei primi "veri" test per un'applicazione non banale. Ho cercato di seguire le best practice che ho raccolto da internet qua e là, ma vorrei un feedback sul fatto che sto andando nella giusta direzione con quello che sto facendo e che cosa posso fare per correggere / migliorare il mio processo.

L'applicazione è un'API headless che vedrà pubblico (alias i client che desiderano integrarsi con la nostra API, non completamente pubblico) in pochi mesi.

Dall'alto verso il basso, lo stack e i livelli hanno questo aspetto:

  • API RESTful (JSON)
  • Autenticazione Oauth 2.0
  • (Principalmente) controller CRUD (PHP, Laravel 5 )
  • Doctrine ORM per DAL
  • DB MySQL

Volevo progettare i miei test per essere il più semplice ma accurato possibile. Tuttavia non ho l'eternità e un giorno per scrivere test davvero fondamentali (test unitari, immagino) per tutti i controller e tutte le logiche di business, quindi ho deciso di approfittare di laravel ha creato mocking per i percorsi e testa tutti gli endpoint per la nostra API.

La mia linea di pensiero è che, dal momento che abbiamo strutture dati e formati standard per richiesta / risposta (JSON, schemi json definiti per oggetti, ecc.) potrei emulare richieste sapendo quale dovrebbe essere la risposta e confrontare le due.

EX. GET api/user/1 dovrebbe restituire user 1 come un oggetto json che posso confrontare per uguaglianza con il json serializzato che l'oggetto reale mi dà.

Quindi il test attuale è simile a questo (usando PHPunit):

  1. All'avvio dell'applicazione Laravel imposta l'ambiente dell'app su "testing" che cambia la connessione DB predefinita a un file SQLite
  2. All'avvio di PHPunit Doctrine ottiene i metadati del modello e crea le tabelle per il mio dominio nel DB, alcuni script aggiuntivi per cose extra-dominio (tabelle oauth) creano anche quelli
  3. Alice , un generatore di oggetti per la dottrina, crea un insieme decentemente diversificato di entità di dominio con dati casuali da Faker e idrata il DB SQLite. Tutte le entità create vengono restituite e le memorizzo in una variabile globale per uso futuro.
  4. Realizzo una copia del DB idratato e intatto da utilizzare nei test che coinvolgono le operazioni di scrittura in modo da poter ripristinare il db dopo ogni test.
  5. I client Oauth vengono generati per gli utenti con ruoli diversi, quindi posso testare oauth scope e permessi tra utenti diversi per ogni test
  6. Uso Laravel's route mocking per chiamare ciascun endpoint dell'API e
  7. Per i test di sola lettura (GET) uso la forma serializzata di json degli oggetti memorizzati in precedenza (fase 3) per testare l'uguaglianza delle risposte,
  8. Per i test di scrittura costruisco richieste dal nostro oggetto json schemi, quindi costruisco un oggetto reale che dovrebbe uguagliarlo, formulare la richiesta e quindi controllare la risposta per l'uguaglianza con la forma serializzata dell'oggetto (come il punto 7). Dopo ciascun test di scrittura, il DB viene sovrascritto con il DB idratato originale del passaggio 4 per il test successivo.

Quindi questo è il senso. L'utilizzo di questo approccio mi ha dato prestazioni fantastiche: eseguire 26 test con 87 asserzioni richiede ~ 12 secondi.

Le mie domande / dubbi

  • Non sto prendendo in giro niente. Mi sento come se stavo facendo qualcosa di sbagliato a causa di questo, ma allo stesso tempo sto fornendo un ambiente "reale" per l'intera applicazione, quindi niente sembra che debba essere deriso. Va bene?
  • Sto provando a fare troppo con ogni test? Ho letto articoli che mettono in guardia dall'avere troppe dipendenze in un test perché rende il test fragile e meno efficace, ma tutte le "dipendenze" nei miei test sono codice reale, quindi se un test si interrompe significa il mio codice reale è rotto, cosa che vorrei sapere.

Cos'altro puoi dirmi? Suggerimenti? Come posso migliorare questo? Grazie!

    
posta Matt Foxx Duncan 04.05.2015 - 19:12
fonte

2 risposte

4

Il concetto è abbastanza buono!

Ora, devi decidere cosa hai costruito - test di integrazione o accettazione e supporto / miglioramento per un solo scopo. Ecco la differenza:

I test di integrazione sono utilizzati dagli sviluppatori per verificare che l'applicazione funzioni e funzioni spesso dalla macchina di sviluppo. Test TDD e test di riproduzione dei bug vanno in questo modo. I test di integrazione dovrebbero essere abbastanza veloci da non annoiare gli sviluppatori.

I test di accettazione vengono utilizzati principalmente dal controllo qualità per garantire che la build dell'applicazione sia pronta per la produzione. Coprono tutte le funzionalità dell'applicazione incluse le condizioni di errore e tendono a funzionare per un po 'a causa del numero elevato di test

Inoltre, dovresti automatizzarli il più possibile in modo che possano essere eseguiti con un solo clic, incluso l'installazione / ripristino del database.

Quindi puoi aggiungerli allo strumento di integrazione continua in modo che possano essere eseguiti dopo ogni commit e si divertano!

Riguardo alle tue preoccupazioni.

In realtà preoccupati - che stai testando troppo in un singolo test. Hai qualcosa di abbastanza complesso da essere testato in isolamento? Il DAL è un buon candidato poiché i test rapidi su DAL possono davvero aiutare quando lo schema db cambia. La regola generale quando si scrivono dei test con scope viene scritta quando si ritiene che questo codice possa essere interrotto / interrotto. Di solito ciò rientra in singole funzioni o in un grande modulo isolato. I test saranno grandi quantità di mock tendono ad essere a) fragili b) costosi da scrivere ec) testare il codice della colla che non ha complessità e nessun valore

    
risposta data 04.05.2015 - 20:04
fonte
0

Se ti piace il rendimento dei tuoi test e scopri che ti aiutano a cogliere i tuoi errori nel codice di produzione, questo è letteralmente tutto ciò che è necessario (al di fuori dei domini specializzati in cui potresti avere responsabilità o problemi normativi). Se fanno queste cose, bene. Se non lo fanno, buttali fuori e prova una nuova metodologia.

Se non sei sicuro, ti incoraggio a "testare A / B" i tuoi test (yo dawg, ti ho sentito come test ...)! Scrivi a modo tuo e scrivi 1+ (probabilmente diversi) nel modo in cui pensi che dovrebbe essere un test unitario. Se avere molti collaboratori è un problema, il problema sarà la difficoltà di indovinare la posizione di un errore nel codice di produzione. Prova a eseguire entrambi i test prima di eseguire il debug di entrambi gli errori e di indovinare in base al messaggio di errore, quindi vedi quale ti ha aiutato a indovinare più vicino al problema reale più rapidamente con il senno di poi.

Ma sempre: misura i test di utilità , non la loro adesione ad alcuni standard!

    
risposta data 29.08.2018 - 03:34
fonte

Leggi altre domande sui tag