# `ExMCP.TestCase`
[🔗](https://github.com/azmaveth/ex_mcp/blob/v1.0.0/lib/ex_mcp/testing/case.ex#L1)

Custom test case for ExMCP with MCP-specific testing utilities.

This module provides a comprehensive testing framework specifically designed
for MCP (Model Context Protocol) applications, including:

- Custom assertions for MCP protocol validation
- Mock server and client infrastructure
- Content testing utilities
- DSL testing helpers
- Performance testing tools
- Integration testing support

## Usage

    defmodule MyMCPTest do
      use ExMCP.TestCase, async: true

      test "tool call validation" do
        tool_result = %{
          "content" => [%{"type" => "text", "text" => "Hello"}]
        }

        assert_valid_tool_result(tool_result)
        assert_content_type(tool_result, :text)
        assert_content_contains(tool_result, "Hello")
      end

      test "server integration" do
        with_mock_server(tools: [sample_tool()]) do |client|
          result = call_tool(client, "sample_tool", %{input: "test"})
          assert_success(result)
        end
      end
    end

# `add_cleanup`

```elixir
@spec add_cleanup(map(), (-&gt; any())) :: map()
```

Adds a cleanup function to the test context.

# `capture_logs`
*macro* 

Captures log output during test execution.

## Examples

    logs = capture_logs do
      Logger.info("Test message")
      some_operation()
    end

    assert logs =~ "Test message"

# `concurrent_test`
*macro* 

Creates a test that runs concurrently with other tests.

## Examples

    concurrent_test "parallel operation", count: 5 do |index|
      result = parallel_operation(index)
      assert result.id == index
    end

# `create_test_context`

```elixir
@spec create_test_context(map()) :: map()
```

Creates a test context with cleanup.

## Examples

    context = create_test_context(%{
      server_port: 8080,
      temp_dir: "/tmp/test"
    })

    # Use context in tests
    assert context.server_port == 8080

    # Cleanup is automatic

# `flush_messages`

```elixir
@spec flush_messages() :: [any()]
```

Flushes all messages from the test process mailbox.

# `measure_time`
*macro* 

Measures execution time of a block.

## Examples

    {result, time_ms} = measure_time do
      heavy_computation()
    end

    assert time_ms < 1000  # Should complete in under 1 second

# `repeat_test`
*macro* 

Runs a test multiple times to check for flakiness.

## Examples

    repeat_test 10 do
      result = potentially_flaky_operation()
      assert result == :ok
    end

# `run_parallel`

```elixir
@spec run_parallel(
  [(-&gt; any())],
  keyword()
) :: [any()]
```

Runs tests in parallel and collects results.

## Examples

    results = run_parallel([
      fn -> test_operation_1() end,
      fn -> test_operation_2() end,
      fn -> test_operation_3() end
    ])

    assert length(results) == 3
    assert Enum.all?(results, &(&1 == :ok))

# `start_test_supervisor`

```elixir
@spec start_test_supervisor([Supervisor.child_spec()]) ::
  {:ok, pid()} | {:error, any()}
```

Creates a supervision tree for testing.

## Examples

    {:ok, supervisor} = start_test_supervisor([
      {MyWorker, [name: :test_worker]},
      {MyServer, [port: 0]}
    ])

    # Test with supervised processes
    assert Process.alive?(Process.whereis(:test_worker))

# `unique_id`

```elixir
@spec unique_id(String.t(), pos_integer()) :: String.t()
```

Generates unique test data with a prefix.

## Examples

    id = unique_id("test")          # "test_a1b2c3d4"
    name = unique_id("user", 8)     # "user_1a2b3c4d"

# `wait_until`

```elixir
@spec wait_until(
  (-&gt; boolean()),
  keyword()
) :: :ok | :timeout
```

Waits for a condition to become true within a timeout.

## Examples

    wait_until(fn -> Process.alive?(pid) end, timeout: 1000)

# `with_config`
*macro* 

Runs a test with specific configuration overrides.

## Examples

    with_config([timeout: 10_000, retries: 3]) do
      test_with_custom_config()
    end

# `with_mock_server`
*macro* 

Runs a test with a mock MCP server.

## Examples

    with_mock_server(tools: [sample_tool()], resources: [sample_resource()]) do |client|
      result = ExMCP.Client.list_tools(client)
      assert {:ok, %{"tools" => tools}} = result
      assert length(tools) == 1
    end

# `with_temp_file`
*macro* 

Creates a temporary file with content for testing.

## Examples

    with_temp_file("test content", ".txt") do |file_path|
      content = File.read!(file_path)
      assert content == "test content"
    end

# `with_test_server`
*macro* 

Runs a test with a real MCP server process.

## Examples

    with_test_server(MyServer, port: 8080) do |client|
      result = ExMCP.Client.list_tools(client)
      assert {:ok, %{"tools" => _}} = result
    end

# `with_timeout`
*macro* 

Runs a block with a timeout, failing the test if it takes too long.

## Examples

    with_timeout 5000 do
      slow_operation()
    end

---

*Consult [api-reference.md](api-reference.md) for complete listing*
