2010-12-01 5 views
22

Grundsätzlich NUnit, xUnit, MbUnit, MSTest und dergleichen Methoden ähnlich der folgenden:Gibt es ein C# Unit-Testframework, das beliebige Ausdrücke anstelle einer begrenzten Anzahl von Adhoc-Methoden unterstützt?

Assert.IsGreater(a,b) 
//or, a little more discoverable 
Assert.That(a, Is.GreaterThan(b)) 

Jedoch gibt es eine begrenzte Anzahl von solchen Vergleichsoperatoren eingebaut; und sie kopieren die Sprachenoperatoren unnötig. Wenn ich will alles noch etwas komplex, wie ...

Assert.That(a.SequenceEquals(b)) 

Ich bin oft entweder links durch die manuelle Graben das Äquivalent des Ausdrucks in NUnit-sprechen zu finden, oder gezwungen sind, zu fallen-zurück zu einfache boolesche Assertionen mit weniger hilfreichen Fehlermeldungen

C#, integriert aber auch mit beliebigen Ausdrücke - so sollte es möglich sein, ein Verfahren mit der folgenden Signatur hat:

void That(Expression<Func<bool>> expr); 

Ein solches Verfahren verwendet werden, um sowohl den Test durchführt (dh Validierung der Behauptung) und auch eine weniger undurchsichtige Diagnose im Falle eines Testversagens bereitzustellen; schließlich kann ein Ausdruck in Pseudocode gerendert werden, um anzuzeigen, welcher Ausdruck fehlgeschlagen ist; und mit einiger Mühe könnten Sie sogar versagende Ausdrücke intelligent bewerten, um einen Hinweis auf den Wert von Teilausdrücken zu geben.

Zum Beispiel:

Assert.That(()=> a == b);//could inspect expression and print a and b 
Assert.That(()=> a < b && b < c); 
//could mention the values of "a<b" and "b<c" and/or list the values of a, b, and c. 

Zumindest würde es die Verwendung einer parallelen Sprache für Ausdrücke überflüssig machen und in einigen Fällen kann es Fehlermeldungen nützlicher machen.

Gibt es so etwas?

Bearbeiten: Nach dem Versuch (und liking!) Power Assert, endete ich es neu implementieren, um mehrere Einschränkungen zu beheben. Meine Variante davon ist veröffentlicht als ExpressionToCode; Eine Liste der Verbesserungen finden Sie unter my answer below.

+0

die Ideen in Rhino Mocks –

+0

MbTest Betrachten? Ich nehme an, du mischst MbUnit und MSTest zusammen :) –

+0

Whoops, du hast Recht - behoben. –

Antwort

2

(Original Poster hier)

Ich liebe PowerAssert.NET ‚s einfache Syntax und Nachrichten, aber die C# produziert es viele Probleme hat. Insbesondere werden mehrere Ausdrucksfeatures nicht unterstützt, und es werden keine Klammern hinzugefügt, wenn dies durch Operatorpräzedenz/Assoziativität erforderlich ist. Nachdem ich ein paar Fehler behoben (und sie dem Autor gemeldet habe), fand ich es einfacher, sie mit einem anderen Ansatz zu beheben und sie von Grund auf neu zu implementieren.

Die Verwendung ist ähnlich:

PAssert.That(()=> 
    Enumerable.Range(0,1000).ToDictionary(i=>"n"+i)["n3"].ToString() 
    == (3.5).ToString() 
); 

Ausgänge:

PAssert.That failed for: 

Enumerable.Range(0, 1000).ToDictionary(i => "n" + (object)i)["n3"].ToString() == 3.5.ToString() 
      |     |       |   |  |  | 
      |     |       |   |  |  "3.5" 
      |     |       |   |  false 
      |     |       |   "3" 
      |     |       3 
      |     {[n0, 0], [n1, 1], [n2, 2], [n3, 3], [n4, 4], [n5, 5], [n6, 6], [n7, 7], [n8, 8], [n9, 9], ...} 
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...} 

Verbesserungen gegenüber PowerAssert.NET:

  • Unterstützt statisches Feld und Eigentum Zugang
  • mehr Betreiber unterstützt, wie zum Beispiel logisch und bitweise n egation.
  • erkennt Indexer Verwendung C# (zB dict["mykey"]==3)
  • Fügt Klammern in dem vom Betreiber Rangfolge und Assoziativität erforderlich (zB () => x - (a - b) + x * (a + b) korrekt regeneriert)
  • gültigen numerischen und anderen konstanten Literale einschließlich Fluchten und Suffixe als geeignet für die Expression Typ Erzeugt (zB 1m + (decimal)Math.Sqrt(1.41))
  • Unterstützt C# syntaktischen Zucker für Objektinitialisierer, Objektelement initializers, Liste initializers, Erweiterungsmethoden, unter anderem.
  • Verwendet die gleichen Abstandsregeln, die Visual Studio standardmäßig verwendet.
  • Unterstützt verschachtelte Lambdas
  • Erweitert generische Instanzen in normales C#; z.B. Func<int, bool>
  • Unterstützt mehr Ausdrucksbäume Konstrukte noch nicht von C# 4.0 eingebettetem Ausdrücke verwendet.

Das resultierende Projekt (mit Unit-Tests) in Google Code unter dem Namen gehostete ExpressionToCode - Ich hoffe, dass es für andere nützlich ist.

5

http://satisfyr.codeplex.com/

Verwendet genau Lambda-Ausdrücke wie Sie beschrieben. Sie nehmen nicht einmal eine binäre Abhängigkeit an, sondern fügen nur eine einzige Quelldatei hinzu, die Ihrem Unit-Test-Framework entspricht.

+0

Sieht gut aus, ich werde es versuchen ... danke! –

+0

im Grunde sehr ähnlich assert an der Macht Obwohl, ich glaube, dies Option etwas weniger verwendbar ist, da (1) die Fehlermeldungen sind nicht ganz so explizit, (2) die Syntax weniger Tests gut in typische Einheit paßt, (3) das Lambda Ausdrücke haben einen Parameter, was bedeutet, dass der tatsächliche Name oder Inhalt des Ausdrucks, mit dem der Parameter gefüllt wurde, zur Testzeit nicht verfügbar ist. –

+0

Froh, dass du etwas gefunden hast, das für dich funktioniert :) Ich persönlich satisfyr ist eine großartige Ergänzung für mich, da ich es sowohl in xUnit.net als auch in MSTest verwenden kann. –

0

Das Einheitentestframework von Visual Studio 2010 verfügt über eine CollectionAssert-Klasse, die nützlich ist.

Es bietet auch eine Bestätigung.IsTrue (bool) für allgemeine Fälle, die Sie selbst erstellen, aber keine, die Ausdrücke verwenden;

11

Schauen Sie sich die PowerAssert Bibliothek (Beispiel Ausgang unten):

PAssert.IsTrue(() => x + 5 == d.Month * y); 


System.Exception : IsTrue failed, expression was: 

x + 5 == d.Month * y 
| | | | |  | | 
| | | | |  | 6 
| | | | |  18 
| | | | 3 
| | | 01/03/2010 00:00:00 
| | False 
| 16 
11 

http://powerassert.codeplex.com/

+0

Ah, auch sehr schön ... –

+0

Nun, das Projekt nicht vollständig ausgereift erscheinen, aber die Fehler, die ich sofar trivial gewesen begegnet sind zu beheben, und Ich mag die Syntax - diese sieht besser aus als Satisfyr. Vielen Dank! –

+1

Nun, ich mag die Idee hinter der Macht zu behaupten, aber es gab ein paar zu viele Probleme, denen ich begegnete; Ich habe die Kernidee erneut implementiert als [ExpressionToCode] (http://code.google.com/p/expressiontocode/) –

2

Cone (https://github.com/drunkcod/cone) ein NUnit Addin ist, die mit 2.5.5 & 2.5.7 (andere Versionen funktioniert nur eine Neukompilierung), die Ihnen diese Fähigkeit zusammen mit einigen anderen raffinierten Funktionen gibt.

5

Es gibt tatsächlich einen sehr guten Grund, dass NUnit sein eigenes DSL anbietet, anstatt normale C# -Ausdrücke zu benutzen. Es ist, dass NUnit mit beliebigen .NET Sprache mit der gleichen Syntax arbeiten soll. Das heißt nicht, dass wir keine Lambdas haben können, nur dass wir uns niemals ausschließlich auf eine bestimmte Sprachfunktion verlassen werden.

Viele der vorgestellten Ideen funktionieren und viele der Softwarelösungen von Drittanbietern können in NUnit integriert werden, vorausgesetzt, dass ihre Autoren diese anbieten möchten. Natürlich bevorzugen viele Leute, ihre Lösungen getrennt zu halten, und das ist auch in Ordnung. Aber sprechen Sie mit Ihren Lieblingsautoren, wenn Sie möchten, dass sie enger mit NUnit zusammenarbeiten.

In NUnit 2.5 können Sie PredicateConstraint verwenden, das ein Lambda als Argument verwendet. Die Syntax ist jedoch ein wenig einschränkend. Die Spiele Schlüsselwort wird in der Mitte eines Ausdrucks arbeiten, können Sie so schreiben ...

Assert.That (someActual, Not.Matches (someLambda);

aber ohne die nicht tun erfordert ...

Assert.That (someActual, neues PredicateConstraint (someLambda));.

Und natürlich, keiner von ihnen ist so sauber, wie die vorgeschlagene Syntax

Jeder an diesem Thema interessiert ist herzlich eingeladen uns auf nunit-diskutieren wo dis Gespräche darüber, was in NUnit sein sollte, führen zu Taten!

Charlie

+0

Willkommen bei Stack Overflow!Es ist immer gut, einen Entwickler zu sehen, dessen Namen ich hier schnell erkenne :) –

+1

Ausdrücke sind nicht an C# gebunden - sie sind auch in mindestens VB.NET vorhanden; und sie sind in jedem Fall eine Kernkomponente von LINQ und DLR - also keine sehr einschränkende Anforderung. Und natürlich können Sie * immer * einfache boolesche Assertions verwenden und ein DSL als Fallback haben - es ist nur, warum nicht die verfügbaren Funktionen zumindest wo möglich nutzen. Außerdem sind Ausdrücke nicht ganz so umfassend wie die vollständige Sprache und in .NET 3.5 noch weniger; Das ist eindeutig nicht für maximal kompatiblen Code. –

+1

@eamon: Lassen Sie mich Ihnen ein extremes Beispiel geben, das meinen Standpunkt veranschaulicht. Der Operator == ist eine Sprachfunktion. Natürlich entspricht es in vielen Sprachen der gleichen oder ähnlichen Syntax und kann in jeder davon eine etwas andere Semantik haben. Daher stellt NUnit eine eigene EqualTo-Methode zur Verfügung, um identische Semantik über alle .NET-Sprachen zu bieten, die es verwenden. Keine sprachbasierte Implementierung kann jemals "EqualTo" ersetzen. Sie können diese Implementierungen jedoch weiterhin mit NUnit verwenden, solange Sie sich über die Bedeutung im Klaren sind. –

Verwandte Themen