Git Product home page Git Product logo

Comments (6)

sergey-tihon avatar sergey-tihon commented on May 27, 2024 1

@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.

CaptnCodr avatar CaptnCodr commented on May 27, 2024

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.

johanvts avatar johanvts commented on May 27, 2024

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:

  1. Work across all floats in a record.
  2. Work with DU types of float.

from fsunit.

CaptnCodr avatar CaptnCodr commented on May 27, 2024

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.

johanvts avatar johanvts commented on May 27, 2024

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.

CaptnCodr avatar CaptnCodr commented on May 27, 2024

Hey @johanvts

What simply FsUnit does is:

  1. 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
  2. it follows that operators are in FsUnit implemented that are real assertions in nunit, xunit and/or mstest
  3. 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 the actual, expected and tolerance are convertible to float and if the difference between actual and expected is less than the tolerance 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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.