2017-12-14 4 views
2

Ich versuche, FsUnit (unter der Haube, die es NUnit verwendet) zu verwenden, um meine F # -Code zu testen, aber es hat Probleme mit generischen diskriminierten Gewerkschaften. 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 dafür vielleicht besser geeignete Frameworks?Verwenden von NUnit mit generischen diskriminierten Verbindungen

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 :(

Antwort

4

Ein Teil der verwenden Problem in Ihrem Code ist, dass Assert.AreEqual nimmt zwei Parameter wie obj und so der Compiler weiß nicht, dass die Typen die gleichen sein sollten - wenn es das weiß, dann würde daraus schließen, dass expected ist vom Typ int OptionWithReason (mit result übereinstimmen).

Eine einfache Möglichkeit, dies zu beheben, ist eine Hilfsfunktion für areEqual zu definieren, die Parameter des gleichen Typs nimmt:

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

Jetzt können Sie Ihre Behauptung schreiben wie:

areEqual expected result 

Der Compiler wird folgern, dass die Typen expected und result die gleichen sind und es sollte funktionieren.

+1

Nizza sein, Ihre Lösung ist eigentlich viel einfacher als das, was ich gefunden habe (Wechsel zu Unquote). Ich werde es als akzeptiert markieren, obwohl ich bei Unquote bleiben werde, da es eine coole Bibliothek ist, die ich in meinem Spielzeugprojekt verwenden kann :) – DevNewb

1
let expected = None reason 

Hier kann Compiler weiß nicht, welche Art von generischen Parametern 'a, also wenn Gebrauch es verwendet in

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

Es auf eine Instanz OptionWithReason<object> äquivalent werden würde, die würde anders Jede Instanz von OptionWithReason<int>, wie der Fall result

Wie Test Framework, könnten Sie versuchen Expecto. Aber immer noch, ich denke, es würde das gleiche Problem darstellen

+0

Wie ich schon sagte: Ich verstehe, warum es passiert, ich bin für eine bessere Lösung, als mit Anmerkungen versehen – DevNewb

+0

Dann denke ich, die Antwort nein ist, denn ohne Typen mit Anmerkungen versehen, wäre es anders Typ – xuanduc987

3

Ich denke, ich habe es gefunden. Unquote scheint zu funktionieren. Ich habe es mit xUnit verwendet, nur weil es einfacher war, es mit dotnet-Core-Bibliotheken einzurichten. Ich brauchte nur die Bibliotheken zu importieren und zu ändern behauptet:

open Xunit 
open Swensen.Unquote 

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

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

Diese Art von Kniffen das Problem, weil wir F # 's Gleichheit statt Gabe an eine C# -Bibliothek als OptionWithReason<object>

Verwandte Themen