Asserire l'uguaglianza in modo più semplice quando i tipi possono essere diversi

2

Ho lavorato su un'infrastruttura di test automatizzata MSTest, ovvero test di uno strumento che unisce i set di dati alle tabelle del database di SQL Server. La struttura di base del test è:

  1. Definisci il set di dati in arrivo usando i tipi anonimi
  2. Applica i dati utilizzando lo strumento di riconciliazione
  3. Leggi i record dalle tabelle di output
  4. Confronta le righe dei risultati per inserire i dati, colonna per colonna

Dati di input di esempio:

public class InputData : List<dynamic> {} // Inspired by Massive etc

InputData input = new InputData()
{
    new { ExternalID = 1, PropertyName = "hello", Agent = "test" },
    new { ExternalID = (Int64)2, PropertyName = "fred", Agent = "test" } // Fixes the problem with a cast
};

Il problema che ho a che fare è che il tipo inferito sui miei oggetti anonimi sarà un Int32, ma la colonna corrispondente nella mia tabella di destinazione è un bigint, e quindi il record avrà un valore Int64. Di conseguenza, quando utilizzo Assert.AreEqual su ogni colonna, fallisce su tutti i campi int:

Assert.AreEqual failed. Expected:<1 (System.Int32)>. Actual:<1 (System.Int64)>

Puoi vedere che ho lanciato l'int sul mio secondo oggetto anonimo, questo può essere usato per risolvere il problema. Lo scopo principale di questi test è di rendere i dati di esempio più snelli e facili da leggere / scrivere possibile, e preferirei evitare il rumore visivo di tutti quei tipi di calchi.

Sto pensando al modo migliore per gestire le asserzioni. Sembra che dovrei usare asserzioni dedicate basate sul tipo. Immagino che la vera domanda sia, quanto dovrei essere aggressivo nel convertire tra i tipi automaticamente?

    
posta eddie.sholl 11.09.2013 - 10:23
fonte

2 risposte

5

Assert.AreEqual è fondamentalmente solo zucchero per Assert.IsTrue(object.Equals(...)) . Se non esiste un operatore di confronto noto per i due tipi di argomento, confronteranno false .

dynamic è piuttosto intelligente, quindi, ad esempio, (dynamic)(int)1 == (decimal)1.0 valuta true . Questo funziona solo se si utilizza l'operatore == , però; non funzionerà se si tenta di utilizzare object.Equals , Assert.AreEqual , ((dynamic)x).Equals(...) o qualcosa di simile. Semplicemente la conversione in dynamic non funzionerà, devi effettivamente utilizzare il suo operatore == . La buona notizia è che la% dinamica== consente qualsiasi operando, il che significa che è possibile ottenere questo risultato per la compilazione in un'asserzione generica; se il confronto non è valido (ad esempio confrontando int con string , allora fallirà in fase di esecuzione con RuntimeBinderException .

La prossima cosa migliore, se sai che saranno tipi numerici, sarebbe il cast di tutti su Decimal o Double , sebbene tieni presente che se usi Double dovrai prendere in considerazione la possibilità di errore di arrotondamento in virgola mobile, e si dovrebbe definire l'uguaglianza in base ad alcune soglie, tipicamente un multiplo di Double.Epsilon . Decimal è molto più semplice a meno che tu non sappia per certo che avrai a che fare con virgola mobile.

Non penso che tu abbia davvero molte altre scelte. Personalmente non consiglierei la conversione delle stringhe perché molte classi non sovrascrivono ToString , quindi finisci per confrontare due istanze di qualcosa come System.Collections.Generic.List''1[System.Int32] , e la tua asserzione dichiara che sono uguali perché hanno la stessa rappresentazione di stringa quando in infatti non sono solo istanze diverse ma contengono elementi completamente diversi. Quindi non farlo. La coercizione su stringa può facilmente mascherare errori gravi nei test. Attenersi alle conversioni non-lossy, tutto o niente come sopra.

    
risposta data 09.01.2014 - 03:28
fonte
0

Converti in stringhe è ciò che penso. Le stringhe sono sottovalutate nei casi di test. Quindi puoi scrivere un metodo simile a

void AssertEqual(Object a, Object b)
{
  Assert.AreEqual(a.ToString(), b.ToString();
}

e forse aggiungere un parametro che è il messaggio di errore.

    
risposta data 10.12.2013 - 01:43
fonte

Leggi altre domande sui tag