-
Notifications
You must be signed in to change notification settings - Fork 15
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
Build a testing module #417
Comments
Nope on the latter; thinko. The "real name" of the prefix thus imported would be ...fortunately. I was not looking forward to implementing that extra bit of parser complexity. 😂 |
I just realized that the
one could write
It (a) satisfies the kind of orthogonality we're looking for in our primitives, and (b) suggests that perhaps asserting is not limited to testing. I like the sound of both of those ideas. I don't mind making |
As I was reading how to design co-programs, I was thinking maybe there should be a Maybe such an annotation could even be included into API documentation somehow. (And it should be designed with that in mind, with maybe an string parameter describing the use case.) Also, maybe a linter tool of some kind could easily detect if some input or output case was missing, and flag that up as a missing |
According to a throwaway comment in #256. This built-in might not be long-lived, the comment at #417 (comment) suggests it might be better to fold this one into `assert` and make the latter a built-in. Until then, consider `assertType` a stopgap.
The way Ava reports test failures is very close to what I had in mind. |
This is in fact necessary because the I'm thinking |
I think as a pleasant side effect of |
No, it isn't, not with our tight prefixes at least. Same as #300 (comment), it could be a term. |
I know I've used I no longer believe those two concepts should be mixed into a single keyword. I'd prefer to use |
...and we should probably not have the |
Counterargument: D uses |
It strikes me that the |
Just like a module file can have a
MAIN
function, it can also have one or more functions marked with anis test
trait (or #257 a@test
annotation). Presumably, callingbin/007 myscript --test
will run these functions. Presumably x 2, a usage message will include the--test
flag if there are@test
annotations.MAIN
does. The general case will be that the mainline doesn't do anything, except for maybe initialize values.@test
annotation. If a nested function has it, that's a (beautiful) compile-time error.@test
annotation seems to me to be a (Contextual macros #349) contextual macro hosted by the compunit, which can create an array of references to@test
-annotated functions, that can then be run after the mainline. (Conceptually, through aLEAVE
phaser on the mainline or something.)Importing the test module
Recommended that you import the things you need from the
test
module:or
You could also, if you want, import only the module:
And then use the qualified names, like
@test.test
andtest.assert
.Assertions
assert
is a prefix macro. It expects an expression, a predicate that we want to be truthy for the test to pass.(Edit: But see the comment further down, which argues for spelling it
expect
instead.)@test
annotation will make sure that the function has at least one leftmostassert
somewhere. It's OK for them to be nested below the top block of the function (for example, infor
loops).@test
function. They are short-circuiting, like the boolean operators, in the sense that a failed assert aborts later execution in the function.The strength of
assert
(and a very nice use case for macros) is that when an assertion fails, enough information has been saved to give really specific diagnostics:Without going into detail, the
assert
macro has done the job of saving line-and-file information, the whole code in the assertion (looking at you, Python), as well as intercepting any non-constant subexpressions — it interceptscart.totalAmount()
, not42
— saving those values away somewhere for the diagnostics.(Very conjectural, but: in some cases it might be possible to data-flow back through the relevant function/method calls, at compile time, and install the appropriate "spies" in that code as well, to provide "reason" diagnostics, the kind of things you'd be wont to look up when you saw the test failure. A decent balance would need to be struck between being informative but not too verbose.)
Asserting an exception got thrown
The
threw
prefix is meant to be placed in anassert
predicate immediately after a line of business code we expect to fail with a particular exception type.A couple of comments:
assert threw
is "dead"... but that's fine, because theassert
has made sure toCATCH
block for itself — if there is one already, give a pleasing compiler error — where it checks the type of the exception, andthrew
prefix actually returnsFalse
, because if it ever runs, then we didn't actually throw something, andassert
knows to give a good diagnostic in this case, even including the preceding statement that should've thrown the exception.If we want to capture the exception and introspect it (for example checking the exact message, or other fields), use the
with
statement (#156):The
assert
keyword is implied in this case; using it is fine, and may count as extra documentation, but just usingwith
is enough.Other annotations
I can see the use case immediately for a
@beforeEach
annotation, and an@afterEach
one. They are "phaser-like", in that they are instrumented to run around the tests.Maybe even a
@beforeAll
and@afterAll
could be useful — their main benefit would be that they only run in the case of running the module during testing.I'm not at all ready to do any kind of nested testing. I think that's extra complexity without any benefit.
I was gonna say we might want to have an annotation for parameterized tests, but... I'm not actually convinced that'd be a win compared to just having a
for
loop inside the test function.However, I do see a lovely use for a
@mock
annotation on (typed #33) parameters. That's far into the future, but... nice way not to have to initialize the mock yourself, and still have it mock the right dependency. Of course, you're likely to want to initialize the SUT in@beforeEach
or@beforeAll
, so mocked parameters should work there too.I'm not aware of a reason to make the test module work with classes instead of functions, although such a reason might exist.
The text was updated successfully, but these errors were encountered: