c++ elettrotecnica - Come testare l'unità errori di compilazione deliberata del codice del modello




domande risposte (4)

Si noti che questo NON è un duplicato di Come scrivere un test unitario per verificare l'errore di compilazione? dato che non mi interessa testare la correttezza delle librerie esterne o del compilatore stesso.

È tipico del C ++, in particolare quando si tratta di modelli, di impiegare tecniche che impediscono la compilazione di un particolare pezzo di codice. Poiché questi possono essere contorti, qual è il modo migliore per garantire che determinate parti di codice generino effettivamente errori del compilatore?

Dato che il test non dovrebbe nemmeno essere compilato, non puoi fare affidamento su cose come il boost-test , quindi suppongo che dovrebbe essere integrato nel sistema di build? In che modo vengono generalmente affrontati questi problemi?


Answers

Dovresti fare affidamento su un framework esterno per eseguire una serie di test di compilazione, ad esempio makefile o lavori hudson, e verificare l'output del compilatore o gli artefatti del compilatore. Se la compilazione dovesse fallire, non ci dovrebbe essere un file oggetto per il file in compilazione. Sto indovinando che potresti scrivere un plugin per Hudson per farlo o un semplice script batch che esegue un makefile che compila tutti i file di test che dovrebbero fallire o avere successo e segnalare i successi o gli errori di conseguenza.

Nel caso più semplice verificherebbe solo l'esistenza del file '.o' per vedere se il test ha avuto successo, in casi più complessi potresti voler guardare l'output del compilatore e verificare che l'errore prodotto sia compatibile con l'errore che ti aspetti Dipenderà dal compilatore che stai usando.

Andare di un livello più in profondità significherebbe probabilmente scrivere un'estensione del compilatore per farlo (LLVM potrebbe essere in grado di gestire ciò che stai chiedendo)


Fallo nello stesso modo in cui vengono scritti i test del compilatore. Avrai un po 'di codice di test in qualche linguaggio di scripting (shell, perl, tcl ecc.) Che eseguirà il compilatore su determinati frammenti di codice e controllerà se quelli giusti sono stati compilati e quelli giusti no.

  • gcc usa DejaGnu , che è costruito sopra expect , che è esso stesso costruito su Tcl.
  • Se usi lo script di shell (probabilmente più facile, DejaGnu è probabilmente eccessivo), potresti voler dare un'occhiata a shUnit2 .
  • Perl's Test::Harness sistema Test::Harness dovrebbe essere per lo più facile da usare così com'è.
  • Dopotutto, non è molto più lavoro per eseguire il processo da C ++, quindi scrivere una funzione per provare a chiamare il compilatore su una determinata stringa e controllare se emette un errore per la riga dove ci si aspetterebbe che non sarebbe così difficile e che si possa integrare negli altri test basati su boost.test.


Di recente mi sono imbattuto nella seguente convenzione per nominare i miei test, le loro classi e i progetti contenenti al fine di massimizzare i loro descrittivi:

Diciamo che sto testando la classe Settings in un progetto nello spazio dei nomi MyApp.Serialization .

Innanzitutto creerò un progetto di test con lo spazio dei nomi MyApp.Serialization.Tests .

All'interno di questo progetto e naturalmente dello spazio dei nomi creerò una classe chiamata IfSettings (salvata come IfSettings.cs).

Diciamo che sto testando il metodo SaveStrings () . -> Chiamerò il test CanSaveStrings () .

Quando eseguo questo test mostrerà la seguente intestazione:

MyApp.Serialization.Tests.IfSettings.CanSaveStrings

Penso che questo mi dice molto bene, cosa sta testando.

Ovviamente è utile che in inglese il nome "Test" sia lo stesso del verbo "test".

Non c'è limite alla tua creatività nel nominare i test, in modo da ottenere intestazioni complete delle frasi per loro.

Di solito i Testnames devono iniziare con un verbo.

Esempi inclusi:

  • Rileva (ad esempio, DetectsInvalidUserInput)
  • Getta (es. ThrowsOnNotFound)
  • Will (ad es. WillCloseTheDatabaseAfterTheTransaction)

eccetera.

Un'altra opzione è usare "that" invece di "if".

Quest'ultimo mi salva comunque i tasti e descrive più esattamente quello che sto facendo, dal momento che non lo so, che il comportamento testato è presente, ma sto verificando se lo è.

[ Modifica ]

Dopo aver usato la convenzione di denominazione sopra per un po 'più a lungo, ho trovato che il prefisso If può essere fonte di confusione quando si lavora con le interfacce. Accade solo che la classe di test IfSerializer.cs sia molto simile all'interfaccia ISerializer.cs nella "scheda Apri file". Questo può diventare molto fastidioso quando si passa avanti e indietro tra i test, la classe in fase di test e la sua interfaccia. Di conseguenza, ora sceglierei Se sopra come prefisso.

Inoltre ora uso - solo per i metodi nelle mie classi di test poiché non è considerato la migliore pratica da nessun'altra parte - il "_" per separare le parole nei miei nomi dei metodi di prova come in:

  • [Test] public void detects_invalid_User_Input () *

Trovo che questo sia più facile da leggere.

[ Fine modifica ]

Spero che questo generi alcune idee in più, dal momento che considero i test di denominazione di grande importanza in quanto possono far risparmiare un sacco di tempo che altrimenti sarebbero stati spesi cercando di capire cosa stanno facendo i test (ad esempio dopo aver ripreso un progetto dopo un'interruzione prolungata) .







c++ unit-testing templates