Di recente mi sono imbattuto in alcuni nuovi codici scritti intervallati da molti Debug.Assert (C #).
Dovremmo comunque utilizzarlo ampiamente nonostante l'uso di TDD, BDD e Unit Test in generale?
Di recente mi sono imbattuto in alcuni nuovi codici scritti intervallati da molti Debug.Assert (C #).
Dovremmo comunque utilizzarlo ampiamente nonostante l'uso di TDD, BDD e Unit Test in generale?
Risposte:
Non vedo alcun motivo per cui non dovresti usare Assert. In questo modo hai già riconosciuto la necessità di guardie, come precondizioni e invarianti, e stai facendo un passo verso la progettazione per contratto . Assert è solo un modo per raggiungere questo ...
// Precondition using Asert
void SomeMethod(Foo someParameter)
{
Debug.Assert(someParameter != null)
}
// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
if (someParameter == null)
throw new ArgumentNullException("someParameter");
}
// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
Contract.Requires(someParameter != null);
}
// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
Require.ArgumentNotNull(() => someParameter);
}
Tutti sono modi per ottenere la stessa cosa: solidità nel codice. Dipende solo dalla scelta di un'opzione, di cui Assert è una scelta valida.
Si noti che non ho menzionato affatto test di unità finora, in quanto realizzano qualcosa di molto diverso. Un unit test dimostra formalmente la solidità del codice esercitando una guardia:
[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
delegate call = () => someObject.SomeMethod(null);
Assert.That(call).Throws<ArgumentNullException>();
}
Questo è un tipo completamente diverso di affermazione ...
** Si noti che in alcuni framework è in realtà abbastanza difficile testare l'unità per un errore di asserzione, in quanto un errore di asserzione può ridurre l'intero runtime, quindi una delle altre opzioni potrebbe essere preferita ... *
Considero affermazioni e unit test come due strumenti diversi nella mia cassetta degli attrezzi. Alcune cose sono più adatte all'una e altre sono più adatte all'altra.
Ad esempio, in questi giorni utilizzo principalmente assert per validare parametri per metodi non pubblici.
Oggi considero Debug.Assert come ottimizzazione prematura. A meno che tu non abbia davvero bisogno delle prestazioni, la soppressione di Assert in modalità di rilascio può nascondere i bug più a lungo.
Come sottolinea MattDavey, i contratti di codice possono essere superiori, fornendo controlli statici invece di controlli dinamici, e se non disponibili preferirei Trace.Assert o un semplice vecchioif(x) throw SomeException;
Debug
classe vengano saltate dalla compilazione ... quindi sopprimere le chiamate a Assert
semplicemente per prestazioni non è solo un'ottimizzazione prematura, è una semplice assurdità.