/ Verwendung von NUnit mit generisch diskriminierten Gewerkschaften - Generics, f #, nunit, diskriminierte-union

Verwenden von NUnit mit generischen diskriminierten Gewerkschaften - Generika, f #, nunit, discriminated-union

Ich versuche, FsUnit zu verwenden (unter der Haube, die es verwendetNUnit), um meinen F # -Code zu testen, aber er hat Schwierigkeiten, mit generisch diskriminierten Vereinigungen umzugehen. Ich verstehe, warum es passiert, aber ich versuche einen Weg zu finden, Tests zu schreiben, ohne meine erwarteten Werte zu kommentieren. Irgendein Rat? Gibt es vielleicht besser geeignete Rahmen dafür?

type OptionWithReason<"a> =
| Some of "a
| None of string

let reason = "division by 0 is not yet supported"
let safeDivide x y =
if y = 0 then
None reason
else
Some(x/y)

let result = safeDivide 1 0

let expected = None reason
let expectedExplicit: int OptionWithReason = None reason

let test1 = result = expected //true
let test2 = result = expectedExplicit //true

NUnit.Framework.Assert.AreEqual(expectedExplicit,result) //pass
NUnit.Framework.Assert.AreEqual(expected,result) //fail :(

Antworten:

4 für die Antwort № 1

Ein Teil des Problems in Ihrem Code ist das Assert.AreEqual nimmt zwei Parameter als obj und so weiß der Compiler nicht, dass die Typen gleich sein sollten - wenn er dies weiß, würde er daraus schließen expected ist vom Typ int OptionWithReason (Zusammenpassen result).

Eine einfache Möglichkeit, dies zu beheben, besteht in der Definition einer Hilfsfunktion für areEqual das nimmt Parameter des gleichen Typs an:

let areEqual (first:"T) (second:"T) =
NUnit.Framework.Assert.AreEqual(first, second)

Nun können Sie Ihre Behauptung folgendermaßen schreiben:

areEqual expected result

Der Compiler wird darauf schließen, dass die Typen von expected und result sind gleich und es sollte funktionieren.


3 für die Antwort № 2

Ich glaube ich habe es gefunden. Unquote scheint zu funktionieren. Ich habe es mit xUnit verwendet, nur weil es einfacher war, mit Dotnet-Kernbibliotheken einzurichten. Ich brauchte nur die Bibliotheken zu importieren und Assets zu ändern:

open Xunit
open Swensen.Unquote

[<Fact>]
let testDUComparison () =
test <@ expected = result @>

[<Fact>]
let testDUComparisonExplicit () =
test <@ expectedExplicit = result @>

Diese Art weicht dem Problem aus, weil wir die Gleichheit von F # verwenden, anstatt sie an eine C # -Bibliothek zu übergeben OptionWithReason<object>


1 für die Antwort № 3
let expected = None reason

Hier kann der Compiler den Typ der generischen Parameter nicht kennen "awenn also verwenden Sie es in

NUnit.Framework.Assert.AreEqual(expected,result)

Es würde einer Instanz von gleichwertig werden OptionWithReason<object> was sich von jeder Instanz von unterscheiden würde OptionWithReason<int>wie im Fall von result

Als Testframework könnten Sie es versuchen Expecto. Ich denke jedoch, dass es das gleiche Problem darstellen würde