2010-01-04 14 views
5

Nei test dell'unità C#, ho spesso richiesto un elenco di righe in base a un elenco di ID. Poi voglio assicurarmi che 1) per tutti gli ID, ci sia almeno una riga trovata con quell'ID e 2) per tutte le righe restituite, ogni riga ha un ID che è nella lista degli ID da trovare. Ecco come ho di solito assicurano che:Confronto elenco a due vie nel test unità C#

Credo che l'uso di Any e All è conveniente per tali controlli, ma volevo vedere se qualcuno pensa che questo è meno leggibile di quello che potrebbe essere, o se c'è forse un modo più bello di fare controlli bidirezionali come questo. Sto utilizzando MSTest in Visual Studio 2008 Team System per il test delle unità. Questo forse dovrebbe essere wiki della comunità se è troppo soggettivo.

Edit: Ora sto utilizzando una soluzione basata su suggerimento di Aviad P., e anche il fatto che il seguente test viene superato:

string[] ids1 = { "a", "b", "c" }; 
string[] ids2 = { "b", "c", "d", "e" }; 
string[] ids3 = { "c", "a", "b" }; 
Assert.AreEqual(
    1, 
    ids1.Except(ids2).Count() 
); 
Assert.AreEqual(
    2, 
    ids2.Except(ids1).Count() 
); 
Assert.AreEqual(
    0, 
    ids1.Except(ids3).Count() 
); 

risposta

4

Si può scegliere di utilizzare l'operatore Except:

var resultIds = results.Select(x => x[primaryKey]); 

Assert.IsTrue(resultIds.Except(ids).Count() == 0, 
"Returned results had unexpected IDs"); 

Assert.IsTrue(ids.Except(resultIds).Count() == 0, 
"Not all IDs were found in returned results"); 
+0

Questo sembra buono, e mi piace come scrivere 'x [primaryKey]' solo una volta. Comunque, penso che dovrebbe essere 'Count() == 0', considerando come' Except' è descritto. –

+0

In realtà, è necessario mantenere> 0, ma scambiare i messaggi in giro. Modificata la mia risposta. –

+0

Perché avresti bisogno di '> 0'? Prevedo che non ci sia alcuna differenza tra l'elenco degli ID dei risultati recuperati e l'elenco degli ID che ho interrogato. Intellisense descrive "Eccetto" come produrre la "differenza di set di due sequenze". –

3

IMO, non come leggibile come potrebbe essere . Crea e documenta un metodo che restituisce vero/falso. Quindi chiama Assert.IsTrue (methodWithDescriptiveNameWhichReturnsTrueOrfalse(), "motivo dell'errore");

+2

+1 Questo è essenzialmente il * Custom Assertion * xUnit Test Pattern, anche se si potrebbe anche renderlo un metodo nullo e spostare l'asserzione nel metodo. –

0

NUnit ha il CollectionAssert famiglia di affermazioni che aiutano la leggibilità.

1

Ecco un frammento di codice che ho fatto a che fare con due enumerables, e gettando eccezione durante facendo prova di unità in MS di prova, potrebbe aiutare:

Usa

confrontare due enumerables:

MyAssert.AreEnumerableSame(expected,actual); 

gestire eccezione

MyAssert.Throws<KeyNotFoundException>(() => repository.GetById(1), string.Empty); 

Codice

public class MyAssert 
    { 
     public class AssertAnswer 
     { 
      public bool Success { get; set; } 
      public string Message { get; set; } 
     } 

     public static void Throws<T>(Action action, string expectedMessage) where T : Exception 
     { 
      AssertAnswer answer = AssertAction<T>(action, expectedMessage); 

      Assert.IsTrue(answer.Success); 
      Assert.AreEqual(expectedMessage, answer.Message); 
     } 

     public static void AreEnumerableSame(IEnumerable<object> enumerable1, IEnumerable<object> enumerable2) 
     { 
      bool isSameEnumerable = true; 
      bool isSameObject ; 

      if (enumerable1.Count() == enumerable2.Count()) 
      { 
       foreach (object o1 in enumerable1) 
       { 
        isSameObject = false; 
        foreach (object o2 in enumerable2) 
        { 
         if (o2.Equals(o1)) 
         { 
          isSameObject = true; 
          break; 
         } 
        } 
        if (!isSameObject) 
        { 
         isSameEnumerable = false; 
         break; 
        } 
       } 
      } 
      else 
       isSameEnumerable = false; 

      Assert.IsTrue(isSameEnumerable); 
     } 

     public static AssertAnswer AssertAction<T>(Action action, string expectedMessage) where T : Exception 
     { 
      AssertAnswer answer = new AssertAnswer(); 

      try 
      { 
       action.Invoke(); 

       answer.Success = false; 
       answer.Message = string.Format("Exception of type {0} should be thrown.", typeof(T)); 
      } 
      catch (T exc) 
      { 
       answer.Success = true; 
       answer.Message = expectedMessage; 
      } 
      catch (Exception e) 
      { 
       answer.Success = false; 
       answer.Message = string.Format("A different Exception was thrown {0}.", e.GetType()); 
      } 

      return answer; 
     } 
    } 
Problemi correlati