Closed vfaronov closed 3 years ago
On second thought, looks like this won’t work, because the first thing a utility function needs is Helper()
, and there’s no way for *rapid.T
to implement it.
My other idea would be to export a T *testing.T
field on rapid.T
, but it’s not clear how that would be better than just having two variables.
Still, please do comment: Is it OK to call the underlying (*testing.T).Fatalf
directly instead of the (*rapid.T).Fatalf
, etc.?
(*testing.T).Fatalf
is a bit magical: it calls FailNow, which does runtime.Goexit()
. So rapid has no chance to do e.g. shrinking. I've never tested this case.
Do you have the same use case of writing tests that run on both hand-picked examples, and rapid-generated ones? It is an important one, and I've planned to add direct support for it (it is in my before-1.0 ideas list).
Do you have the same use case of writing tests that run on both hand-picked examples, and rapid-generated ones?
No, just small utility functions, such as program-specific assertions.
Well, this might still be convenient:
func mustBaz(t rapid.CommonT, tt *testing.T) {
tt.Helper()
if err := baz(); err != nil {
t.Fatalf("failed to baz: %v", err)
}
}
and then call mustBaz(t, t)
from regular tests and mustBaz(t, tt)
from rapid tests. Which is to say, a rapid.CommonT
might still be useful.
Hm, can you try making type tb interface
in engine.go
public, and doing
func mustBaz(t rapid.TB) {
t.Helper()
if err := baz(); err != nil {
t.Fatalf("failed to baz: %v", err)
}
}
? I think it should route Helper()
properly both for *rapid.T
and *testing.T
.
@vfaronov did you have a chance to try my suggestion?
Sorry for the delay. You’re right, it seems to work! I didn’t think of embedding.
@flyingmutant Thank you!
Thanks for this fine library.
I have the same problem as in #6: utility functions that I would like to call from both regular and property-based tests. They can’t take
*rapid.T
because there is none in regular tests. They could take*testing.T
— the same one that I pass torapid.Check
— and this is how #6 was settled — but, firstly, this makes testing functions slightly less readable (can’t just pass the samet
everywhere, need separate variables), and secondly, is it even correct? don’t the*rapid.T
methods do anything rapid-specific above and beyond the underlying*testing.T
?It would be most convenient to make these utility functions take an interface — defined and exported from
rapid
, e.g.rapid.CommonT
or something — that both*rapid.T
and*testing.T
implement.But I’m not sure this is the right approach. Feel free to close this issue if you don’t like the idea.