I've just finished a little module with a unit testing macro that might be useful, since I've found it useful so far. It's called einheit and it tries to be more friendly than the existing unittest module. There are examples in the test.nim file on the repo page.
Let me know if you guys like it and if there are any issues :) Anyone is also welcome to contribute.
:) Thanks.
To my knowledge, Nim doesn't prefer one way or the other in terms of CamelCase vs under_scores. Plus, you can use the macro in whatever case you want. I happen to prefer underscores now, even though I used to be hard core CamelCase back in my Java days.
If you look in the Nim source code, there is a mix of cases with a constant style per file. Feel free to use testSuite instead of test_suite :)
"Nim doesn't prefer one way or the other in terms of CamelCase vs under_scores"
Ah, but it does: https://github.com/nim-lang/Nim/wiki/Style-Guide-for-Nim-Code
Nimrod's "style-invariance" seems to have been aimed at being able to avoid using under_scores even if libraries do.
:) Ah, looks like my knowledge needed expanding. I will code with CamelCase with Nim from now on, and also update the code I wrote.
Thanks for pointing me to the style guide. I somehow missed it, even though I've been using Nim for quite a while :)
Very nice! Are you aware of py.test? It has some very nice features that you might want to implement:
The fixtures http://pytest.org/latest/fixture.html#fixture
and a lot of helpers e.g.: http://pytest.org/latest/assert.html#assert-with-the-assert-statement
assert (a == b) and (c == d)
may check that the failure is in the second equality check, and show to the user the actual values of c and d. If I got this wrong, please correct me.
Now, I am not sure how to do this in a general way. With a library of assertions, it is always possible to write a new assertion when the need arises to do reporting in a different way. With just the assert macro, what would be the desired output for an AST of an arbitrarily complex boolean expression?
For a concrete example, my linalg library has a method ~= which is used to compare vectors and matrices taking into account floating point errors. So I guess one could have an assertion such as
assert a ~= b
How would assert figure out what to print, without knowing in advance the existence of the ~= operator? I guess one could print out the values of all intermediary nodes of the AST, but this may get unwieldy for complex expressions.
With the possibility of developing custom assertions, one would write
assertAlmostEqual a, b
and then assertAlmostEqual would know the context and print out what is relevant a and b in this case.
I am sorry if this question is naive - everyone in the thread seems to get it, but I do not see an approach that would work in general
How would assert figure out what to print, without knowing in advance the existence of the ~= operator?
That should be named =~ then. In Nim comparison operators are either keywords in notin is isnot not of or start with one of = < > ! (and not ending in an arrow).
I am dead serious about using a different name such as testValue or similar. It would avoid the majority of these issues.
What is the issue here? That assert means something different in a testsuite context? That's a feature. :P
But the existing unittest simply uses check which is a nice name too.
andrea > How would assert figure out what to print, without knowing in advance the existence of the ~= operator? I guess one could print out the values of all intermediary nodes of the AST, but this may get unwieldy for complex expressions.
That's what I'm doing currently. Right now, it's just a simple comparison of whether or not the expression inside the assert is an infix AST node. If it is, I get the values and names of the expressions on either side of the infix operator, without caring what it is. You're exactly right that doing this for more complex expressions will get unwieldy. Trying to get values of say, assert (not f(g(x)) and someObj isnot otherObj) or (t(g(x)) is potentially complicated, but potentially doable. Iterating recursively, like @Araq said, could be used to get all symbols (nnkSym or nnkIdent?) and put them in a table with their values and then print them out. At least that's how I picture it. Someone correct me if my approach seems off :)
andrea > I am sorry if this question is naive - everyone in the thread seems to get it, but I do not see an approach that would work in general
It's not naive, it's honest. Questions are always good to ask because they reveal what's on your mind and potentially other people's as well. There's no shame in not knowing something. The only shame is not asking because then there's no way you can know :)
Araq > But the existing unittest simply uses check which is a nice name too.
I like check as well. I'm good with it being the keyword instead of assert.
Araq: "What is the issue here?"
From previous comments, I gathered that the issue is that the macro can't affect the meaning of assert in functions called from the testsuite block. You would need LISP-style dynamic binding for that.
As for the name: in one unit test package I wrote, I used a.mustBe(b[, message]). Boolean tests were along the lines of (x or y).mustBe(true). This worked well for my use case where most of the tests were for numeric calculations, but might be a bit verbose for the general case with lots of boolean tests. In that case I might go for expect(x or y).
I've changed the name to check, but the self is still needed for now.
@Araq, I've integrated the code you gave me for recursively iterating through the AST and it's not as complicated as I first thought. Thanks for that :)