2011-11-17 11 views
12

Attualmente sto sviluppando un wrapper C# P/invoke su una DLL che fa parte del mio prodotto. Non ho esperienza con C# e questa è la prima codifica C# significativa che ho fatto. Sono profondamente consapevole del fatto che mi manca molta conoscenza dei punti e degli idiomi più fini della lingua.Come posso estendere la classe NUnit Assert aggiungendo un nuovo sovraccarico statico per AreEqual?

La mia domanda riguarda le unit test che sto scrivendo per cui sto usando NUnit. Ho bisogno di confrontare i valori delle variabili double[]. Se utilizzo Assert.AreEqual(...) per fare ciò, i valori vengono confrontati per l'uguaglianza esatta. Tuttavia, vorrei confrontarmi con una tolleranza. Esistono sovraccarichi AreEqual() per valori reali scalari che ammettono un parametro delta. Tuttavia, non sono stato in grado di trovare un equivalente per gli array. Ho perso qualcosa di ovvio?

Al momento ho risolto il problema con il seguente codice:

class Assert : NUnit.Framework.Assert 
{ 
    public static void AreEqual(double[] expected, double[] actual, double delta) 
    { 
     AreEqual(expected.Length, actual.Length); 
     for (int i = 0; i < expected.Length; i++) 
     { 
      AreEqual(expected[i], actual[i], delta); 
     } 
    } 
} 

Anche se questo sembra funzionare Mi chiedo se ci sia una soluzione più pulita a disposizione. In particolare, sono preoccupato che l'uso dello stesso nome per la mia classe derivata sia non solo di scarsa qualità, ma potrebbe portare a problemi non previsti lungo la strada.

Vorrei utilizzare i metodi di estensione, ma capisco che sono utilizzabili solo quando c'è un'istanza della classe in estensione. Naturalmente, ho sempre chiamato solo metodi statici sulla classe Assert.

Mi dispiace se questo sembra un po 'nebuloso, ma il mio istinto mi dice che non sto facendo questo nel modo migliore e mi piacerebbe sapere come farlo nel modo giusto.

+1

Hai provato [Metodi di estensione] (http://msdn.microsoft.com/en-us/library/bb383977.aspx)? –

+5

@Ofer Zelig mentre ti ho dato il +1 mi sono ricordato che i Metodi di Estensione, mentre definiti statici, funzionano solo sulle istanze. – dowhilefor

+0

Così come sembra ora, non si può fare (a meno che non si stia implementando la classe wrapper, un sacco di lavoro duro e brutto). Vedi [this] (http://stackoverflow.com/questions/249222/can-i-add-extension-methods-to-an-existing-static-class/435617#435617) e [this] (http: // madprops.org/blog/static-extension-methods/). –

risposta

7

Dopo l'introduzione della sintassi asserzione fluente in NUnit, il metodo Within() è stato a disposizione per questo scopo:

double actualValue = 1.989; 
double expectedValue = 1.9890; 
Assert.That(actualValue, Is.EqualTo(expectedValue).Within(0.00001)); 
Assert.That(actualValue, Is.EqualTo(expectedValue).Within(1).Ulps); 
Assert.That(actualValue, Is.EqualTo(expectedValue).Within(0.1).Percent); 

Per le raccolte, il comportamento predefinito di Is.EqualTo() è quello di confrontare i membri delle collezioni individualmente, con questi confronti individuali sono stati modificati da Within(). Quindi, è possibile confrontare due matrici di doppi modo:

var actualDoubles = new double[] {1.0/3.0, 0.7, 9.981}; 
var expectedDoubles = new double[] { 1.1/3.3, 0.7, 9.9810}; 
Assert.That(actualDoubles, Is.EqualTo(expectedDoubles).Within(0.00001)); 
Assert.That(actualDoubles, Is.EqualTo(expectedDoubles).Within(1).Ulps); 
Assert.That(actualDoubles, Is.EqualTo(expectedDoubles).Within(0.1).Percent); 

Questo si confronta ogni elemento di actualDoubles all'elemento corrispondente expectedDoubles utilizzando la tolleranza specificata, e fallirà se alcuni non sono sufficientemente vicine.

+0

Grazie mille per questo. Sembra che sia il modo in cui mi aspetto di risolvere il problema. Apprezzo il tuo tempo qui. Grazie mille. Per questioni personali, trovo queste interfacce fluenti un po 'opache. Una volta che l'hai scritto, ha un senso, ma devi craccarlo per poterlo scrivere la prima volta! –

+1

Penso che il trucco con interfacce fluenti di questo tipo sia lo sviluppo basato su punti. Se stai utilizzando un IDE come Visual Studio, devi solo conoscere il primo "link nella catena", ad es. 'Is', quindi puoi premere' .' e Intellisense ti mostrerà tutte le opzioni per il tuo 'prossimo passo'. Ho imparato molte funzioni come 'Within()' in questo modo, piuttosto che leggere i documenti NUnit. – Peter

2

Penso che quello che avrei fatto è semplicemente definire una funzione da qualche parte nel test harness

public static bool AreEqual(double[], double[], double delta)

che fa il confronto e restituisce vero o falso in modo appropriato. Nel tuo test scrivi semplicemente:

Assert.IsTrue(AreEqual(expected, result, delta)) ; 
+0

Grazie per questo. È certamente una buona idea. Il rovescio della medaglia per me è che ho scoperto che quando ho provato a implementarlo ho dovuto reimplementare il confronto 'delta' che viene fornito gratuitamente quando chiami AreEqual con reali input scalari. Quindi la risposta di @dowhilefor sembrava adattarsi meglio alle mie esigenze questa volta. Grazie per la cura! –

2

"Meglio" è sempre una questione di gusti. In questo caso, direi di si. Dovresti fare la tua affermazione, senza sottomettere l'affermazione di nunit. Nunit ha già più classi Assert con differenti asserzioni specifiche. Come CollectionAssert. Altrimenti il ​​tuo metodo va bene.

+0

Grazie per questo. Non avevo individuato le altre classi 'XXXAssert'. Così ho aggiunto una classe 'ArrayAssert' e ho spostato il mio codice lì. Adesso è abbastanza naturale e le mie vibrazioni negative si sono ritirate. –

2

Avevo bisogno di creare assert personalizzato, nel tuo caso c'era un'alternativa fornita dal framework. Tuttavia questo non ha funzionato quando volevo avere una dichiarazione completamente personalizzata. Ho risolto questo problema aggiungendo una nuova classe statica chiamata in nunit.

public static class FooAssert 
{ 
    public static void CountEquals(int expected, FooConsumer consumer) 
    { 
     int actualCount = 0; 
     while (consumer.ConsumeItem() != null) 
      actualCount++; 

     NUnit.Framework.Assert.AreEqual(expected, actualCount); 
    } 
} 

Poi, in un test

[Test] 
public void BarTest() 
{ 
    // Arrange 
    ... 

    // Act 
    ... 

    // Assert 
    FooAssert.CountEquals(1, fooConsumer); 
} 

so che sono un po 'in ritardo per il partito, potrebbe ancora essere utile per qualcuno

Problemi correlati