[英]Using `should equal` with sequences in F# and FsUnit
我正在使用FsUnit.Xunit
。 以下测试用例失败:
[<Fact>]
let ``Initialization of DFF`` () =
dff Seq.empty Seq.empty |> should equal (seq {Zero})
测试失败是:
Message:
FsUnit.Xunit+MatchException : Exception of type 'FsUnit.Xunit+MatchException' was thrown.
Expected: Equals seq [Zero]
Actual: seq [Zero]
Stack Trace:
That.Static[a](a actual, IMatcher`1 matcher)
Signal.Initialization of DFF() line 11
如果测试是,我会得到同样的错误:
[<Fact>]
let ``Initialization of DFF`` () =
dff Seq.empty Seq.empty |> should equal (Seq.singleton Zero)
我从未使用FsUnit.Xunit
测试过序列的相等性,所以我很困惑发生了什么。 我什至不确定失败消息告诉我什么,因为它似乎在说预期和实际是相同的。 我可以通过将序列转换为列表来使其正常工作,但不必这样做会很好。
有人可以解释这里发生了什么吗? 似乎我不理解错误消息,因此可能是关于Equals
和比较序列值(文字?)。 谢谢。
能够重现的源代码(我认为这就是一切):
type Bit =
| Zero
| One
type Signal = seq<Bit>
let Nand a b =
match a, b with
| Zero, Zero -> One
| Zero, One -> One
| One, Zero -> One
| One, One -> Zero
let Not input =
Nand input input
let And a b =
Not (Nand a b)
let Or a b =
Nand (Not a) (Not b)
let private liftToSignal1 op (signal: Signal) : Signal =
Seq.map op signal
let private liftToSignal2 op (signalA: Signal) (signalB: Signal) : Signal =
Seq.map2 op signalA signalB
let Not' = liftToSignal1 Not
let And' = liftToSignal2 And
let Or' = liftToSignal2 Or
let rec dff data clock : Signal =
seq {
yield Zero
yield! Or' (And' data clock)
(And' (dff data clock) (Not' clock))
}
这是结构与引用平等的问题。 在 F# 中seq { 'a' } = seq { 'a' } // false
but [ 'a' ] = [ 'a' ] // true
因为seq
是IEnumerable
并且不支持结构相等(或比较)。 列表(和其他 F# 容器类类型)更加“智能”,即如果包含的对象支持,它们支持结构相等/比较:
[ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] =
[ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] // true
但不要,如果它们包含任何不包含的内容: [ box(fun() -> 3) ] = [ box(fun() -> 3) ] // false
因此,为了使测试工作,添加一个List.ofSeq
:
dff Seq.empty Seq.empty |> List.ofSeq |> should equal [ Zero ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.