def METHOD_NAME(functions=(), j=1):
    """
    Generates expression tests.
    For every signature prim, rev and fwd instantiations are tested (with all scalars
    of type double/var/fvar<double>). Tests check the following:
     - signatures can be compiled with expressions arguments
     - results when given expressions are same as when given plain matrices
       (including derivatives)
     - functions evaluate expressions at most once
    :param functions: functions to generate tests for. This can contain names of functions
    already supported by stanc3, full function signatures or file names of files containing
    any of the previous two. Default: all signatures supported by stanc3
    :param j: number of files to split tests in
    """
    tests = []
    functions, signatures = handle_function_list(functions)
    signatures = set(signatures)
    if not functions and not signatures:
        default_checks = True
        signatures |= set(get_signatures())
    else:
        for signature in get_signatures():
            sp = SignatureParser(signature)
            if sp.function_name in functions:
                signatures.add(signature)
        default_checks = False
    for n, signature in enumerate(signatures):
        for overload in ("Prim", "Rev", "Fwd"):
            sp = SignatureParser(signature)
            # skip ignored signatures if running the default checks
            if default_checks and sp.is_ignored():
                continue
            # skip signatures without inputs that can be eigen types
            if not sp.has_eigen_compatible_arg():
                continue
            # skip functions in forward mode with no forward mode overload, same for reverse mode
            if overload == "Fwd" and not sp.is_fwd_compatible():
                continue
            if overload == "Rev" and not sp.is_rev_compatible():
                continue
            is_reverse_mode = overload == "Rev" and not sp.returns_int()
            cg = CodeGenerator()
            # Generate two sets of arguments, one will be expressions one will not
            arg_list_expression_base = cg.build_arguments(sp, sp.number_arguments() * [overload], size = 1)
            arg_list_expression = [cg.convert_to_expression(arg, size = 1) if arg.is_eigen_compatible() else arg for arg in arg_list_expression_base]
            arg_list_no_expression = cg.build_arguments(sp, sp.number_arguments() * [overload], size = 1)
            # Check results with expressions and without are the same
            cpp_function_name = "stan::math::" + sp.function_name
            result = cg.function_call_assign(cpp_function_name, *arg_list_expression)
            result_no_expression = cg.function_call_assign(cpp_function_name, *arg_list_no_expression)
            cg.expect_eq(result, result_no_expression)
            # Check that expressions evaluated only once
            for arg in arg_list_expression:
                if arg.is_expression():
                    cg.expect_leq_one(arg.counter)
            # If reverse mode, check the adjoints
            if is_reverse_mode:
                summed_result = cg.recursive_sum(result)
                summed_result_no_expression = cg.recursive_sum(result_no_expression)
                sum_of_sums = cg.add(summed_result, summed_result_no_expression)
                cg.grad(sum_of_sums)
                for arg, arg_no_expression in zip(arg_list_no_expression, arg_list_expression):
                    cg.expect_adj_eq(arg, arg_no_expression)
                cg.recover_memory()
            tests.append(
                test_code_template.format(
                    overload=overload,
                    comment=signature.strip(),
                    test_name=sp.function_name + repr(n),
                    code = cg.cpp(),
                )
            )
    save_tests_in_files(j, tests)