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

Try to differentiate between null and empty strings in test theories #494

Merged
merged 3 commits into from
Apr 4, 2024

Conversation

Numpsy
Copy link
Contributor

@Numpsy Numpsy commented Mar 17, 2024

refs #493

Some testing to pin down where the issue is - not sure if this is the best apporach to fixing it, or if there are other types than strings that might have similar issues.

@farlee2121
Copy link
Collaborator

Overall, looks good. Gives us a place to make changes if we find any more special values that need differentiated.

I made one change: I grouped the new tests in an explanatory test list.

Checking off a few other potential special values

  • white space should produce different values
  • numeric types... I can't think of any issues
  • weird chars... zero-width characters?
  • reference types... this could be a problem. Classes don't have good default string representations

Example of breaking reference type

type ClassA(i: int) = 
  let i = i

testTheory "I am theory" [ClassA(5); ClassA(4)] (fun (refType: ClassA) -> true)

I'm not sure how common this reference type scenario is. The empty vs null one seems quite common though, and it's worth getting a fix in for that at least.

@farlee2121
Copy link
Collaborator

Also, thanks for the PR!

@Numpsy
Copy link
Contributor Author

Numpsy commented Mar 18, 2024

  • white space should produce different values

With the current change, it works to run the tests when the value is just whitespace, but the Visual Studio test explorer looks a bit 'unfriendly' -
image

If I borrow the quoting approach from NUnit

if value = Unchecked.defaultof<'T> then "null" else $"\"{value}\""

then it looks like this, which seems nicer:

image
image

@Numpsy
Copy link
Contributor Author

Numpsy commented Mar 18, 2024

weird chars... zero-width characters?

I don't know if there are any potential locale specific issues that might occur?

reference types... this could be a problem. Classes don't have good default string representations

I can't recall offhand what NUnit/XUnit do for that, will have to test.

@farlee2121
Copy link
Collaborator

Using NUnit and XUnit theories as a reference is a great idea

@Numpsy
Copy link
Contributor Author

Numpsy commented Mar 20, 2024

Ok, I don't think you can specify class instances in the NUnit TestCase attribute, and if I use TestCaseSource then I get this, where it only lists one test but then has two results, and the display name in the test explorer is just the class type -

Visual Studio:
image

Ionide:
image

@Numpsy Numpsy marked this pull request as ready for review March 21, 2024 10:31
@farlee2121
Copy link
Collaborator

C# attributes can only accept constant parameters. Makes sense that class instances are out.

That's interesting that TestCaseSource behaves differently than the attributes.
That still leaves us with an open question on how to handle classes.

Did you check out xUnit too?

@Numpsy
Copy link
Contributor Author

Numpsy commented Mar 25, 2024

just tried adding a 'TheoryData' based test to an Xunit based test project and got

image

So it's still showing one test with several results, but in that case it's managing to show a string representation of the class instance instead of just showing the type name

@farlee2121
Copy link
Collaborator

Thanks for the research!

Maybe we could mimic the xUnit approach to class rendering. That could open new issues with special characters in test names though...
We could potentially detect duplicate test names and merge them into a single test with the cases in the description, but that feels like an unintuitive user experience.

I think it's worth merging the string/null fix by itself, since that's a fairly common issue.
It's less clear how common the class issue would be. I also doubled checked that records and unions have sensible default string representations and wouldn't suffer from the same issue as classes.

@Numpsy
Copy link
Contributor Author

Numpsy commented Apr 3, 2024

It's less clear how common the class issue would be.

I don't recall having used classes with TestCase myself (it's usually base types like strings, numbers, enums). so making the string case work fixes my problem.

That could open new issues with special characters in test names though
We could potentially detect duplicate test names and merge them into a single test with the cases in the description

I'm not sure if putting that data in the test names would have issues if the class instances had dynamic fields in them? (e.g. say you had a test class instance with a time stamp or guid or some such property in it, trying to render that as part of the test name rather than just in the results might be problematic?)

@farlee2121 farlee2121 merged commit f359e21 into haf:main Apr 4, 2024
2 checks passed
@farlee2121
Copy link
Collaborator

The characters that cause issues (that I'm aware of) are + and ., which are used as separators for test segments.
I don't think guids or dates would typically contain those.

I've also seen some filter issues with characters like ()&|, but it's on the test explorer to escape those kinds of characters.

@farlee2121
Copy link
Collaborator

Oof. Glad I thought to test before pushing the packages.
It looks like quotes around strings causes issues with the Ionide test explorer. I'll see if it can be fixed

@farlee2121
Copy link
Collaborator

A fix is PRed ionide/ionide-vscode-fsharp#1999

@Numpsy
Copy link
Contributor Author

Numpsy commented Apr 5, 2024

Oof. Glad I thought to test before pushing the packages. It looks like quotes around strings causes issues with the Ionide test explorer. I'll see if it can be fixed

Sorry, thought I'd tested that when I made the screen shots, must not have though :-(

My comment about dates etc was more about 'dynamic' data, as in what will the test explorer do if the test name were made of data that might be different between runs (maybe not common, but could happen with class types?) - although maybe you could have a + in the string for a time value as an offset from UTC.

Your comment about . made me think about floating point numbers as well though - which currently look like this in Ionide:

image

@Numpsy Numpsy deleted the string_theory branch April 5, 2024 09:32
@Numpsy
Copy link
Contributor Author

Numpsy commented Apr 5, 2024

  • reference types... this could be a problem. Classes don't have good default string representations

Just accidentally fell over a related situation here - If I try to give a testTheory arrays of strings as inputs, then each array has the same string representation so you get a Found duplicated test names error again

@farlee2121
Copy link
Collaborator

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

Successfully merging this pull request may close these issues.

None yet

2 participants