Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An observation / question about using testTheory with 'null' and '"" as inputs #493

Closed
Numpsy opened this issue Mar 17, 2024 · 3 comments
Closed

Comments

@Numpsy
Copy link
Contributor

Numpsy commented Mar 17, 2024

An observation whilst trying to do a few simple error case input tests with testTheory -

I noticed that if I have test code like

[<Tests>]
let tests =
  testList "samples" [
    testTheory
        "null and empty arent the same"
        [ ""; null ]
        (fun value ->

            printf "%s" value)
  ]

The the test explorer in Ionide only showed one test:

image

And then when I tried running from the command line, I got

[11:06:04 INF] Found duplicated test names, these names are: [["samples"; "null and empty arent the same"; ""]] <Expecto>

Maybe it's not a typical thing to do in F#, but for comparison If I do the same thing in NUnit with TestCase then it puts the string 'null' in the test name rather than an empty string so that the two tests show up differently:
image

So maybe it'd be possible to do something similar here?

Thanks

@farlee2121
Copy link
Collaborator

farlee2121 commented Mar 17, 2024

Thanks for the examples!

It sounds like the problem is that null and empty string are, by default, rendered as the same string so the test name for both cases is the same and the test runner gets mad, thus displaying only one test.

I'd guess the solution here is to introduce a pretty printer that detects special values like this.

That'd probably be changed here

let inline testTheory name cases test =
    let caseToTest case =
        testCase (string case) <| fun () ->
        //        ^^^^^^^

Just conjecture though. I haven't tried anything yet

@Numpsy
Copy link
Contributor Author

Numpsy commented Mar 17, 2024

Just conjecture though. I haven't tried anything yet

Just from a quick go with Expectos own tests, it does look like a different string function like

  let inline private stringify (value : 'T) =
      if typeof<'T> = typeof<string> then
        if value = Unchecked.defaultof<'T> then "null" else value.ToString()
      else
        string value

  /// Builds a theory test case
  let inline testTheory name cases test =
    let caseToTest case =
      testCase (stringify case) <| fun () ->
        test case |> ignore
    testList name (cases |> Seq.map caseToTest |> List.ofSeq)

lets these cases pass

    testTheory "odd numbers" [1; 3; 5] <| fun x ->
      Expect.isTrue (x % 2 = 1) "should be odd"

    testTheory "empty strings" [""; null] <| fun x ->
      Expect.isTrue (System.String.IsNullOrEmpty(x)) "should be null or empty"

@farlee2121
Copy link
Collaborator

Moving this from the PR for discoverability and potential continued discussion

While not very elegant, a workaround could be to give each case a data point to differentiate it. I.e. [("case1", [array here]); ("case2", [other array]).

Actually, we could potentially generalize such an approach. Automatically add a case identifier to make sure each case is unique even if the arguments don't have distinct string representations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants