Comments (6)
@CaptnCodr yes, I agree.
That how we write tests in .NET (C#, F#) - multiple assertions for primitive types.
If you need more, you can implement helper functions for your project or override equality for record type.
from fsunit.
Hey @johanvts, do I understand right that you want to unwrap your types to test its value?
Then I would recommend to build a unwrap function that does that for you like this:
let unwrap (Number x) = x
((Number (1.1 * (1. + 2.))) |> unwrap) |> should (equalWithin 1E-10) ((Number 3.3) |> unwrap) //this test now passes
Same thing for your Name of string
: you can unwrap it to test the boxed string.
Maybe the equalWithin operator could be expanded to cover types with declared double fields or similar?
I think that this is not the purpose for this operation. You can test whole objects with the equal
operation e.g.:
{| Name = "Bob"; Age = 25.7 |} |> should equal {| Name = "Bob"; Age = 25.7 |}
from fsunit.
Thanks @CaptnCodr
Sorry for not being very clear. Let me try with your example:
{| Name = "Bob"; Age = 1.1 * (1 + 2) |} |> should equal {| Name = "Bob"; Age = 3.3 |}
Will fail due to rounding errors, so I would like to be able to write:
{| Name = "Bob"; Age = 1.1 * (1 + 2) |} |> should (equalWithin 0.001) {| Name = "Bob"; Age = 3.3 |}
and even better I would also like to have my DU types of float
supported (auto-unboxing) so I could write:
{|Name="Bob"; Age=Number (1.1 * (1. + 2.)) |} |> should (equalWithin 0.001) {|Name="Bob"; Age=Number (3.3) |}
Currenly to write this last test I have to test and unbox each field of the record seperately.
So I'm looking for either a better way to write that last test with FsUnit as is, or requesting that equalWithin
be expanded to:
- Work across all floats in a record.
- Work with DU types
of float
.
from fsunit.
I think this is not idiomatic for tests doing this. You may have to split it in serperated assertions in a single test:
[<Test>]
member _.``Record with 'Bob' and floating number`` () =
// Arrange
let unwrapNumber (Number x) = x
let unwrapName (Name x) = x
... /* Prepare modules, data etc. */
// Act
let record' =
... // returns {|Name= Name ("Bob"); Age=Number (1.1 * (1. + 2.)) |}
// Assert
record'.Age |> unwrapNumber |> should (equalWithin 0.001) 3.3
record'.Name |> unwrapName |> should equal "Bob"
Think about it and look into the pattern of unit tests.
You could also write an extension for your special case that e.g. automatically unwraps your floats before calling the original Fsunit operator.
from fsunit.
Thanks @CaptnCodr
Yes, splitting is exactly what I'm currently doing (my type converts to float so I just use float
to unwrap)
record.field1 |> float |> should (equalWithin 0.1) 10.0
record.field2 |> float |> should (equalWithin 0.1) 21.0
record.field3 |> float |> should (equalWithin 0.1) 53.0
but I expected to be able to do the same via:
record |> should (equalWithin 0.1) {field1=Number(10.0); field2=Number(21.0); field3=Number(53.0)}
I'm not sure what would not be idiomatic about that? I would expect it to do exactly the same as:
record |> should equal {field1=Number(10.0); field2=Number(21.0); field3 = Number(53.0)}
only respecting the given interval within which to consider numbers equal.
To me it seems perfectly natural that the relationship between equal
and equalWithin
is that they do the same, except equal
requires strict equality and equalWithin
considers numbers equal within an interval.
Please do feel free to close this issue if you don't want to move in this direction with equalWithin
, I mainly wanted to know I hadn't missed some better way of writing my tests and I am very grateful for the time you put into looking at this and writing very thorough answers. Thanks again.
from fsunit.
Hey @johanvts
What simply FsUnit does is:
- it consumes methods (or are adapted) of specific frameworks (xunit, nunit, mstest) and provides it via operators e.g.:
Assert.AreEqual(expected, actual)
=>actual |> should equal expected
- it follows that operators are in FsUnit implemented that are real assertions in nunit, xunit and/or mstest
- there is no "extra logic" implemented only the most necessary to satisfy the operation
equal
and equalWithin
are very different:
equal
is a simple check:x = y
equalWithin
checks if theactual
,expected
andtolerance
are convertible tofloat
and if the difference betweenactual
andexpected
is less than thetolerance
then this test passes
equal
handles all types. equalWithin
handles numeral types with a given range (tolerance
).
This feature does not fit in FsUnit, the reasons are described above.
I would like to close this issue. Do you agree with it, @sergey-tihon?
Thanks!
from fsunit.
Related Issues (20)
- System.NullReferenceException generated if bindings are outside of [<Fact>] attributed let binding HOT 8
- FsUnit does not work with Result HOT 2
- ofCase doesn't support generic union type HOT 2
- ofCase doesn't handle None (represented as null) HOT 3
- 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
- Comparing sequences fails HOT 13
- New Year's ToDos HOT 1
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.