An experimental assertion library based on code-reflections project

Tagir Valeev amaembo at gmail.com
Sat Jul 6 11:05:37 UTC 2024


Hello!

Recently I've implemented my pet project idea of an assertion library based
on code reflection and want to share the results. It's mostly a
proof-of-concept, rather than production-ready stuff, and many things are
missing, but still one can play with it already. Here's the source code:

https://github.com/amaembo/code-reflection-asserts

The idea is that when you use assertions with JUnit or other testing
framework, and assertion fails, you'd like to get diagnostics. If you use a
simple assertion like assertTrue(list.contains(element)), you'll only get
the failed assertion message without any details. Alternatively, people use
libraries like AssertJ, which provide tons of helper methods to get verbose
assertions Assertions.assertThat(list).contains(element). However, for
every API method you need a corresponding AssertJ method, so AssertJ API is
really big, and one needs to learn it.

My idea is that we can get only one assertTrue method, like previously, but
instead of supplying a direct boolean expression, we provide a quoted
lambda instead:

import static one.util.asserts.RefAsserts.assertTrue;

assertTrue(() -> list.contains(element));

If the assertion fails, the assertTrue method implementation does all the
magic. It destructures the expression to individual components, evaluates
them separately and prints the intermediate results, like:

java.lang.AssertionError:
failed
list -> ["Hello", "World"]
element -> "Bye"
list.contains(element) -> false

To implement this, we need a kind of decompiler that can restore the Java
text from the Quoted tree and a kind of interpreter that can manually
compute the result of a given subtree. I wrote a draft implementation. Only
single expression lambdas are supported so far, and some advanced kinds of
expressions like switch expressions or nested lambdas are not supported.
When an unsupported construct is encountered, it falls back to the usual
assertion mechanism (just executes the lambda). Also, the error handling is
not implemented completely, but sometimes it works. E.g., if you write

assertTrue(() -> (3 + 3) / (2 - 2) > 0);

You'll get:

failed
3 + 3 -> 6
2 - 2 -> 0
(3 + 3) / (2 - 2) -> throws java.lang.ArithmeticException: / by zero
(3 + 3) / (2 - 2) > 0 -> throws java.lang.ArithmeticException: / by zero

I think you get the idea. I'd like to hear from Babylon project
contributors whether such a kind of a library is considered to be a valid
use case for code reflections. Any other thoughts and comments are also
welcome.

With best regards,
Tagir Valeev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/babylon-dev/attachments/20240706/0bf5a4e3/attachment.htm>


More information about the babylon-dev mailing list