Make `FutureMatcher` more first-class?
Closed this issue · 2 comments
I've been tripped up by this a couple times: to be specific, that FutureMatcher
is a significantly underpowered version of Matcher
e.g. in etorreborre/specs2-cats#18 (comment), where creating a FutureMatcher
doesn't use AsResult
, in another case I tried using returns
, beLike
, etc. but that didn't seem to work, etc.
I know these issues can be patched as they come up, but I wonder if this is a more fundamental issue that Matcher
and FutureMatcher
form two unrelated hiearchies AFAICT making it difficult to enforce consistent behaviour between them.
Maybe it's too crazy, but if specs2 takes an async-first approach, maybe FutureMatcher
should be a top the top of the hiearchy, and everything else should be implemented in terms of that? E.g. Matcher
is just a FutureMatcher
where all the Future
's are already completed via Future.successful
(or Future.failed
maybe).
Thanks for the suggestion, I need to think about this. I'm kind of reluctant because that might have some large impacts on the current situation and maybe the biggest one would be that an execution context might be necessary everywhere. And for the specifications that are just testing pure, synchronous code that would be superfluous.
I am also not sure how that would play with mutable specifications where matchers can throw exceptions.
So for now I'd rather leave things as they are where FutureMatchers
is a shortcut for Future-like
data type (they're aren't so many of them), to avoid having to write:
IO(1).map(v => v must beEqualTo(1)).unsafeToFuture()
Thanks for considering this! Just a note:
maybe the biggest one would be that an execution context might be necessary everywhere. And for the specifications that are just testing pure, synchronous code that would be superfluous.
I agree it would be superfluous, but I don't think it is necessary actually. For pure/synchronous operations on Matcher
, you can delegate to the FutureMatcher
implementation by providing the parisitic
execution context which runs it on the current thread.
https://www.scala-lang.org/api/3.1.0/scala/concurrent/ExecutionContext$$parasitic$.html.
So for now I'd rather leave things as they are
👍