2016-07-14 13 views
4

Wie kann ich den Wert eines diskriminierten Gewerkschaftsfall in FsUnit Assert ignorieren?Wie kann ich den Wert eines diskriminierten Gewerkschaftsfalls in der Behauptung von FsUnit ignorieren?

Nehmen Sie zum Beispiel:

In meinem Test, möchte ich dies tun:

let display = balance |> select Pepsi 
display |> should equal Denied 

würde ich das nicht etwas dagegen tun:

display |> should equal (Denied _) 

Aber ich Ich bin gezwungen, dies zu tun:

display |> should equal (Denied {Deposited=0.25; Requires=1.00}) 

Beachten Sie, wie explizit ich mit dem obigen Ausdruck sein muss.

Daher möchte ich nur wissen, ob es abgelehnt wurde. Die Details interessieren mich nicht.

Hier ist der eigentliche Test:

[<Test>] 
let ``Vending machine reflects more money required for selection``() = 
    // Setup 
    let balance = Quarter |> insert [] 

    // Test 
    let display = balance |> select Pepsi 

    // Verify 
    display |> should equal (Denied {Deposited=0.25; Requires=1.00}) 

Hier ist die Funktion:

let select product balance = 
    let attempt = { Deposited=balance 
        Requires=product |> getPrice } 

    let paidInFull = attempt.Deposited >= attempt.Requires 

    if not paidInFull then 
     Denied attempt 
    else Granted product 

Hier ist die gesamte Domain:

module Machine 

type Deposit = 
    | Nickel 
    | Dime 
    | Quarter 
    | OneDollarBill 
    | FiveDollarBill 

type TransactionAttempt = { 
    Deposited:float 
    Requires:float 
} 

type State = 
    | OutOfService 
    | PaymentReceived of Deposit 
    | WaitingForSelection 
    | NotPaidInFull of TransactionAttempt 

type Product = 
    | Pepsi 
    | Coke 
    | Sprite 
    | MountainDew 

type RequestResult = 
    | Denied of TransactionAttempt 
    | Granted of Product 

(* Functions *) 
open System 

let display = function 
    | OutOfService   -> "Out of Service" 
    | WaitingForSelection  -> "Make selection" 
    | NotPaidInFull attempt -> sprintf "%s Required" ((attempt.Requires - attempt.Deposited).ToString("C2")) 
    | PaymentReceived deposit -> match deposit with 
           | Nickel   -> "5¢" 
           | Dime   -> "10¢" 
           | Quarter  -> "25¢" 
           | OneDollarBill -> "$1.00" 
           | FiveDollarBill -> "$5.00" 

let getBalance coins = 
    coins |> List.fold (fun acc d -> match d with 
            | Nickel   -> acc + 0.05 
            | Dime   -> acc + 0.10 
            | Quarter  -> acc + 0.25 
            | OneDollarBill -> acc + 1.00 
            | FiveDollarBill -> acc + 5.00) 0.00 
let insert balance coin = 
    coin::balance |> getBalance 

let getPrice = function 
    | Pepsi  -> 1.00 
    | Coke  -> 1.00 
    | Sprite  -> 1.00 
    | MountainDew -> 1.00 

let select product balance = 
    let attempt = { Deposited=balance 
        Requires=product |> getPrice } 

    let paidInFull = attempt.Deposited >= attempt.Requires 

    if not paidInFull then 
     Denied attempt 
    else Granted product 
+1

Die Antwort von @rmunn sieht gut aus, aber was ist falsch mit 'display |> sollte gleich (Verweigert {Abgelegt = 0,25; Benötigt = 1,00})'? Sollte "Abgelehnt" [Abgelegt = 0,22; Benötigt = 1.04} 'den Test bestehen? –

+0

Danke Mark. Du hast recht. –

Antwort

9

Die einfachste Sache, die ich mit oben kommen kann ist, zu schreiben ein Prädikat für den gewünschten Scheck:

let isDenied du = 
    match du with 
    | Denied _ -> true 
    | _ -> false 

Oder seit let f x = match x with ... entspricht let f = function ..., das könnte sein:

let isDenied = function Denied _ -> true | _ -> false 

Dann wird Ihr Test wie folgt aussieht:

display |> isDenied |> should be True 

Beachten Sie, dass True mit einem Kapital T, ist eine Einschränkung. Wenn Sie den Booleschen Wert sind zu vergleichen, dann wäre es

display |> isDenied |> should equal true 

Wenn Sie feststellen, Sie haben viele dieser benutzerdefinierten Prädikate zu schreiben, gibt es wahrscheinlich eine allgemeinere Lösung eine benutzerdefinierte Einschränkung für NUnit Einbeziehung schreiben oder XUnit oder welches Testframework auch immer am Backend verwendet wird. Aber als relativer Neuling zu F # solltest du wahrscheinlich zuerst mit der einfachen Lösung gehen und sie später verallgemeinern.

P.S. Wenn Sie sich entscheiden, eine benutzerdefinierte Einschränkung zu schreiben, sehen Sie sich https://github.com/fsprojects/FsUnit/blob/master/src/FsUnit.NUnit/FsUnit.fs (wenn Sie NUnit verwenden) oder https://github.com/fsprojects/FsUnit/blob/master/src/FsUnit.Xunit/FsUnit.fs (wenn Sie XUnit verwenden) als Inspiration an.