Comments (13)
You are not the only one who needs/needed this. 😉
from fsunit.
I was counting on that, otherwise why add it, right?
from fsunit.
Hi @abelbraaksma,
there is an operator (equivalent
) to compare lists, arrays and sequences that is not implemented for xUnit
.
MsTest
and NUnit
have collection asserts for that case. xUnit doesn't, that's because it isn't implemented in FsUnit.Xunit
.
xUnit
is not idiomatic for that.
Full list of operators: http://fsprojects.github.io/FsUnit/operators.html
from fsunit.
Yes, so basically this doesn’t work. Also, equivalent
I believe doesn’t test sequence order, right @CaptnCodr? My guess is that this could work by adding a type test in the equals
code that just pairwise iterates over any given sequence.
from fsunit.
Yes, equivalent
only tests if the elements are equal, order doesn't matter.
I don't know why e.g. seq {1;2;3} = seq {1;2;3}
results in false
; and seq [1;2;3] = seq [1;2;3]
results in true
.
That's basically what happens in equal
: actual = expected
.
I think that's by design.
I don't know if that's a fix worth to just "fix" the equality of seq
. What do you think, @sergey-tihon?
from fsunit.
I guess that it is does not work for sequences because they can be infinite.
It would be weird to get in infinite loop inside equal
from fsunit.
It would be weird to get in infinite loop inside equal
Since this is a test framework, if someone requests if A=B, then we should do our best to honour that request. If someone wants to compare infinite sequences this way, they’ll simply get a test time out. And these are small sequences, but that’s really up to the programmer.
from fsunit.
Yes and no,
when there is no sequence built-in sequence equality comparison in F# then it gets harder than you think.
Consider that you can have e.g. nested sequences or sequences with objects those cannot be compared, at this point it gets complicated and we don't want to reinvent the wheel with complicated implementations. Simple implementations or constraints directly from NUnit
, xUnit
and MsTest
are ok and this is not simple.
I recommend your mentioned workaround in the beginning to cast it to an array
that has equality comparison built-in.
from fsunit.
Simple implementations or constraints directly from NUnit, xUnit and MsTest are ok and this is not simple.
But xUnit
has a built-in sequence comparison on Assert.Equal<_>
:
[<Fact>]
let ``Test collections`` () =
let x = Seq.init 100 ((+) 1)
let y = seq {
yield! Seq.init 99 ((+) 1)
yield 43
}
Assert.Equal<seq<_>>(x, y)
Which is results in a very useful message:
Assert.Equal() Failure
↓ (pos 99)
Expected: ···.., 96, 97, 98, 99, 100]
Actual: ···.., 96, 97, 98, 99, 43]
↑ (pos 99)
Some random thoughts below (with a suggestion at the bottom):
Tbh, F# behaves really weird here:
> let x = [1..3] |> Seq.ofList;;
val x: seq<int> = [1; 2; 3]
> let y = [1..3] |> Seq.ofList;;
val y: seq<int> = [1; 2; 3]
> x = y;;
val it: bool = true
And:
> let x = [1..100] |> Seq.ofList;;
val y: seq<int> =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; ...]
> let y = [1..100] |> Seq.ofList;;
val y: seq<int> =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; ...]
> x = y;;
val it: bool = true
And:
> let x = Seq.empty<int>;;
val x: seq<int>
> let y = Seq.empty<int>;;
val y: seq<int>
> x = y;;
val it: bool = true
But:
> let x = Seq.init 0 ((+) 1);;
val x: seq<int>
> let y = Seq.init 0 ((+) 1);;
val y: seq<int>
> x = y;;
val it: bool = false
But:
> let x = Seq.init 2 ((+) 1);;
val x: seq<int>
> let y = Seq.init 2 ((+) 1);;
val y: seq<int>
> x = y;;
val it: bool = false
Which to me means that equality in sequences is a mouse trap in F#. I can kinda understand that sequences are not directly comparable (them maybe having side effects and what not). And it appears to me that the only thing that is being compared is reference equality (though: why then are the first two examples true
? They are not reference-equal).
You'd expect something like this though, which may be a candidate extension?
> let x = Seq.init 100 ((+) 1);;
val x: seq<int>
> let y = Seq.init 100 ((+) 1);;
val y: seq<int>
> (x, y) ||> Seq.forall2 (=);;
val it: bool = true
Thinking out loud: maybe we can add something like x |> should be (pairwiseEqual y)
?
from fsunit.
@abelbraaksma When you have an empty seq
it does not succeed anymore:
> (Seq.init 100 ((+) 1), Seq.empty) ||> Seq.forall2 (=);;
val it: bool = true
I was thinking about to make an extra operator for FsUnit.xUnit that isn't quite far away.
equalSeq
with just Assert.Equal<seq<_>>(x, y)
as an implementation could work pretty well, isn't it @sergey-tihon?
e.g.: seq { 1; 2; 3 } |> should equalSeq (seq { 1; 2; 3 })
from fsunit.
@abelbraaksma When you have an empty seq it does not succeed anymore:
Hmm, yeah. Related: dotnet/fsharp#14121, which I raised, because there's quite a bit of weird stuff going on when applying functions to two sequences. I.e., List.map2
and Seq.map2
do not behave the same.
Which basically means that two sequences are only Seq.forall2 -> true
in cases where all items in both sequences until one is exhausted are true. But using List.forall2
or Array.forall2
it'll raise on unequal lengths.
This is not the same as Assert.Equals<seq<_>>
, which will trigger when the sequences are of unequal length.
seq { 1; 2; 3 } |> should equalSeq (seq { 1; 2; 3 })
That's a good idea. For myself, I just added seq { 1; 2; 3 } |> should be (pairwiseEqual (seq { 1; 2; 3 })
or something along those lines, which should also call into Assert.Equals<seq<_>>
, not Seq.forall2
, apparently.
Arguably, equalSeq
is better discoverable, as it will appear in the dropdown box when typing x |> should equal...
, and users may be less inclined to use equal
with sequences and falling into this trap.
from fsunit.
Hey @abelbraaksma,
equalSeq
is now available in Release v5.1.0
.
This has been uploaded to Nuget just now. 🙂
Cheers!
from fsunit.
@CaptnCodr that’s awesome, thanks! I’ll be updating my code, I found myself being very careful when testing sequences, this will certainly help (and with my current work on TaskSeq
, all I do is comparing sequences 😆).
from fsunit.
Related Issues (20)
- ofCase doesn't handle None (represented as null) HOT 3
- equalWithin on DU types of float HOT 6
- Implementing Expecto HOT 6
- `result |> should be (ofCase <@ Ok @>)` throws exception at runtime HOT 3
- Error message when DateTime is not equal does not provide any help HOT 4
- Error message for "equal" is difficult to read and does not show the date milliseconds also when that is the only difference
- Method not found: 'Void Xunit.Sdk.AssertActualExpectedException..ctor HOT 2
- Pipelines are not correctly failing HOT 3
- Inconsistent behaviour of `should equal` in NUnit vs XUnit HOT 1
- Update docs site HOT 7
- error FS0074: The type referenced through 'NHamcrest.IMatcher`1' is defined in an assembly that is not referenced. HOT 2
- Using `should throw` does not show the raised exception, only the string version of the lambda HOT 5
- [Feature request] Creating custom constraints HOT 4
- Using 'should throw' or 'should throwWithMessage' never succeeds unless function returns unit HOT 15
- Deep equality for C# types HOT 5
- New Year's ToDos HOT 1
- Is FSharp.Core 6.0.7 really the lowest dependency for FsUnit? HOT 3
- `MatchException` does not exist anymore in 2.5.0 HOT 2
- Do not use an upper bound on dependencies, unless you have to HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fsunit.