@TestFactory
public Stream<DynamicNode> testEvaluate() throws ExpressionException {

    List<ExpressionTestCase> testCases = ImmutableList.of(
        // basic arithmetic
        testCase("1 - 2 + 3", 2),
        // unary ops
        testCase("2 + +4", 6),
        testCase("2 - -4", 6),
        testCase("2 * -4", -8),
        // check functions
        testCase("sin(5)", sin(5)),
        testCase("atan2(3, 4)", atan2(3, 4)),
        // check conditionals
        testCase("0 || 5", 5),
        testCase("2 || 5", 2),
        testCase("2 && 5", 5),
        testCase("5 && 0", 0),
        // check ternaries
        testCase("false ? 1 : 2", 2),
        testCase("true ? 1 : 2", 1),
        // - ternary binds inside
        testCase("true ? true ? 1 : 2 : 3", 1),
        testCase("true ? false ? 1 : 2 : 3", 2),
        testCase("false ? true ? 1 : 2 : 3", 3),
        testCase("false ? false ? 1 : 2 : 3", 3),
        // check return
        testCase("return 1; 0", 1)
    );
    return testCases.stream()
        .map(testCase -> dynamicTest(
            testCase.getExpression(),
            () -> checkTestCase(testCase)
        ));
}