alef 0.62.10

Opinionated polyglot binding generator for Rust libraries
Documentation
{#- C# test method template

   Context variables:
   - is_skipped: bool - whether to skip this test
   - skip_reason: string - skip reason for [Fact(Skip = "...")]
   - description: fixture description
   - return_type: "async Task" or "void"
   - method_name: test method name (PascalCase)
   - async_kw: "await " or empty string
   - call_target: target object for function call (class or client instance)
   - setup_lines: array of setup statement strings
   - call_expr: the function call expression
   - expects_error: bool
   - exception_class: exception class name to catch
   - declared_error_check: string containing the rendered declared-value assertion, or empty
   - client_factory_setup: client factory setup code (or empty string)
   - has_usable_assertion: bool - whether there's a result to assert on
   - void_not_error: bool - a returns_void call whose only meaningful check is `not_error`;
       wraps the call in Record.Exception/Record.ExceptionAsync and asserts it is null,
       since xUnit has no Assert.DoesNotThrow
   - result_var: result variable name
   - assertions_body: string containing all rendered assertions
   - refusal_skip_reason: optional string — when non-empty the fixture declared assertions and
       none of them rendered a runnable expectation, so the method carries `[Fact(Skip = ..)]`
       instead of `[Fact]`. The rendered skip markers stay in the body, so the refusal is not a
       silent skip.
   - unrenderable_error_assertions: skip markers for error-path assertions this backend cannot render
#}
{%- if is_skipped %}
    [Fact(Skip = "{{ skip_reason }}")]
    public void Test_{{ method_name }}()
    {
        // {{ description }}
    }
{%- elif expects_error %}
    [Fact]
    public {{ return_type }} Test_{{ method_name }}()
    {
        // {{ description }}
{% if client_factory_setup %}
{{ client_factory_setup }}
{% endif %}
{% if return_type == "async Task" %}
{% if declared_error_check %}
        var thrown = await Assert.ThrowsAnyAsync<{{ exception_class }}>(async () =>
{% else %}
        await Assert.ThrowsAnyAsync<{{ exception_class }}>(async () =>
{% endif %}
        {
{% for line in setup_lines %}
            {{ line }}
{% endfor %}
{% if is_streaming %}
            await foreach (var item in {{ call_target }}.{{ call_expr }}) { }
{% else %}
            await {{ call_target }}.{{ call_expr }};
{% endif %}
        });
{% if declared_error_check %}
{{ declared_error_check }}
{% endif %}
{% else %}
{% if declared_error_check %}
        var thrown = Assert.ThrowsAny<{{ exception_class }}>(() =>
{% else %}
        Assert.ThrowsAny<{{ exception_class }}>(() =>
{% endif %}
        {
{% for line in setup_lines %}
            {{ line }}
{% endfor %}
            {{ call_target }}.{{ call_expr }};
        });
{% if declared_error_check %}
{{ declared_error_check }}
{% endif %}
{% endif %}
{% if unrenderable_error_assertions %}
{{ unrenderable_error_assertions }}
{% endif %}
    }
{%- else %}
{%- if refusal_skip_reason %}
    [Fact(Skip = "{{ refusal_skip_reason }}")]
{% else %}
    [Fact]
{% endif %}
    public {{ return_type }} Test_{{ method_name }}()
    {
        // {{ description }}
{% if client_factory_setup %}
{{ client_factory_setup }}
{% endif %}
{% for line in setup_lines %}
        {{ line }}
{% endfor %}
{% if is_trait_bridge %}
        // Trait bridge registration: Bridge.Register() is self-contained and already
        // performs native registration internally — invoke it directly, discard the result.
        // Wrap in try/finally so the bridge unregister always runs and the per-test
        // registration does not leak into subsequent tests (e.g. displacing the host's
        // default backend impl in suites that depend on it).
        try
        {
            {{ call_expr }};
        }
        finally
        {
{% for line in teardown_lines %}
            {{ line }}
{% endfor %}
        }
{% elif is_streaming %}
        await foreach (var item in {{ call_target }}.{{ call_expr }})
        {
            // Stream items are consumed but assertions are skipped for streaming tests
        }
{% elif has_usable_assertion %}
        var {{ result_var }} = {{ async_kw }}{{ call_target }}.{{ call_expr }};
{{ assertions_body }}
{% elif void_not_error %}
{% if return_type == "async Task" %}
        var exception = await Record.ExceptionAsync(async () => await {{ call_target }}.{{ call_expr }});
{% else %}
        var exception = Record.Exception(() => {{ call_target }}.{{ call_expr }});
{% endif %}
        Assert.Null(exception);
{% else %}
        {{ async_kw }}{{ call_target }}.{{ call_expr }};
{% endif %}
    }
{%- endif %}