2016-07-14 2 views
4

Как я могу игнорировать значение случая дискриминированного объединения в утверждении FsUnit?Как игнорировать значение случая дискриминированного объединения в утверждении FsUnit?

Возьмем, к примеру:

В моем тесте, я хочу сделать это:

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

Я не возражал бы делать это:

display |> should equal (Denied _) 

Однако я При этом это делается:

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

Обратите внимание, как я должен быть с выражением выше.

Следовательно, я просто хочу знать, было ли это отказано. Меня не интересуют детали.

Вот фактический тест:

[<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}) 

Вот функция:

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 

Вот весь домен:

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

Ответ от @rmunn выглядит хорошо, но что не так с 'display |> должно равняться (отрицается {Depositited = 0.25; Requires = 1.00})'? Должен ли 'Отрицать {Депонировано = 0,22; Requires = 1.04} 'пройти тест? –

+0

Спасибо, Марк. Ты прав. –

ответ

9

Самое простое, что я могу придумать, чтобы написать предикат для проверки вы хотите:

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

Или так let f x = match x with ... эквивалентно let f = function ..., что может быть:

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

Тогда ваш тест выглядит следующим образом:

display |> isDenied |> should be True 

Обратите внимание, что True, с большой буквы, является сдерживающим фактором. Если вы сравниваете в логическое значение, то это было бы

display |> isDenied |> should equal true 

Если вы обнаружили, что вы, чтобы писать МНОГО этих пользовательские предикаты, есть, вероятно, более общее решение с написанием заказного ограничения для NUnit или XUnit или любые рамки тестирования, которые вы используете на задней панели. Но как относительный новичок в F #, вы, вероятно, должны сначала пойти с простым решением и обобщить его позже.

P.S. Если вы решите написать пользовательское ограничение, посмотрите на https://github.com/fsprojects/FsUnit/blob/master/src/FsUnit.NUnit/FsUnit.fs (если вы используете NUnit) или https://github.com/fsprojects/FsUnit/blob/master/src/FsUnit.Xunit/FsUnit.fs (если вы используете XUnit) для вдохновения.

Смежные вопросы