ExMCP.Testing.Assertions (ex_mcp v0.10.0)
View SourceCustom assertions for MCP protocol testing.
This module provides MCP-specific assertions that go beyond basic ExUnit assertions, offering detailed validation for protocol compliance, content structure, and common MCP patterns.
Features
- Protocol Assertions: Validate MCP message structure and compliance
- Content Assertions: Type-safe content validation and inspection
- Tool Assertions: Validate tool definitions and results
- Resource Assertions: Validate resource definitions and responses
- Error Assertions: Structured error validation
- Performance Assertions: Response time and throughput validation
Usage
use ExMCP.TestCase
test "tool call returns valid content" do
result = call_tool(client, "sample_tool", %{input: "test"})
assert_success(result)
assert_valid_tool_result(result)
assert_content_type(result, :text)
assert_content_contains(result, "expected output")
end
Summary
Functions
Asserts that all items in a list pass a validation function.
Asserts that text content contains a specific string.
Asserts that content matches a regular expression.
Asserts that content is of a specific type.
Asserts that a response indicates an error.
Asserts that a value becomes true within a timeout period.
Asserts that a list of resources contains a specific resource.
Asserts that a list of tools contains a specific tool.
Asserts that a value matches MCP message structure.
Asserts that an operation completes within a time limit.
Asserts that events occur in a specific order.
Asserts that a response indicates success.
Asserts that multiple operations maintain average performance.
Asserts that content is valid according to MCP content protocol.
Asserts that a prompt definition is valid.
Asserts that a resource definition is valid.
Asserts that a tool definition is valid.
Asserts that a tool result contains valid content.
Types
@type assertion_opts() :: [ strict: boolean(), timeout: pos_integer(), retry_count: pos_integer(), message: String.t() ]
Assertion options for customizing behavior
@type mcp_message_type() ::
:request
| :response
| :notification
| :error
| :initialize
| :list_tools
| :call_tool
| :list_resources
| :read_resource
| :list_prompts
| :get_prompt
MCP message types for assertion validation
Functions
Asserts that all items in a list pass a validation function.
Examples
assert_all_valid(tools, &assert_valid_tool/1)
assert_all_valid(content_list, fn content ->
assert_content_type(content, :text)
assert_content_contains(content, "required")
end)
@spec assert_content_contains(ExMCP.Content.Protocol.content() | map(), String.t()) :: any()
Asserts that text content contains a specific string.
Examples
assert_content_contains(text_content, "hello")
assert_content_contains(tool_result, "expected output")
@spec assert_content_matches(ExMCP.Content.Protocol.content() | map(), Regex.t()) :: any()
Asserts that content matches a regular expression.
Examples
assert_content_matches(content, ~r/hello \w+/)
assert_content_matches(tool_result, ~r/\d{4}-\d{2}-\d{2}/)
@spec assert_content_type(ExMCP.Content.Protocol.content() | map() | [map()], atom()) :: any()
Asserts that content is of a specific type.
Examples
assert_content_type(content, :text)
assert_content_type(result, :image)
assert_content_type(result["content"], :text) # For tool results
Asserts that a response indicates an error.
Examples
assert_error({:error, :timeout})
assert_error(%{"error" => %{"code" => -1}})
# With specific error checking
assert_error(result, fn error ->
assert error.code == -32601
assert error.message =~ "Method not found"
end)
@spec assert_eventually((-> boolean()), assertion_opts()) :: :ok
Asserts that a value becomes true within a timeout period.
Examples
assert_eventually fn ->
Process.alive?(pid)
end, timeout: 1000
assert_eventually fn ->
GenServer.call(server, :is_ready)
end, timeout: 5000, interval: 100
Asserts that a list of resources contains a specific resource.
Examples
resources = [%{"uri" => "file://a.txt"}, %{"uri" => "file://b.txt"}]
assert_has_resource(resources, "file://a.txt")
Asserts that a list of tools contains a specific tool.
Examples
tools = [%{"name" => "tool1"}, %{"name" => "tool2"}]
assert_has_tool(tools, "tool1")
@spec assert_mcp_message(map(), mcp_message_type(), keyword()) :: map()
Asserts that a value matches MCP message structure.
Examples
assert_mcp_message(message, :request)
assert_mcp_message(message, :response, id: 123)
assert_mcp_message(message, :notification, method: "notifications/message")
@spec assert_performance((-> any()), assertion_opts()) :: any()
Asserts that an operation completes within a time limit.
Examples
assert_performance fn ->
slow_operation()
end, max_time: 1000
assert_performance fn ->
call_tool(client, "tool", %{})
end, max_time: 500, message: "Tool call should be fast"
Asserts that events occur in a specific order.
Examples
assert_sequence([
fn -> send(self(), :event1) end,
fn -> send(self(), :event2) end,
fn -> send(self(), :event3) end
]) do
assert_received :event1
assert_received :event2
assert_received :event3
end
Asserts that a response indicates success.
Examples
assert_success({:ok, result})
assert_success(%{"status" => "success"})
# With custom message
assert_success(result, "Tool call should succeed")
@spec assert_throughput((-> any()), assertion_opts()) :: [any()]
Asserts that multiple operations maintain average performance.
Examples
assert_throughput fn ->
call_tool(client, "tool", %{})
end, iterations: 10, max_avg_time: 100
@spec assert_valid_content(ExMCP.Content.Protocol.content() | map()) :: ExMCP.Content.Protocol.content() | map()
Asserts that content is valid according to MCP content protocol.
Examples
assert_valid_content(Protocol.text("Hello"))
assert_valid_content(%{"type" => "text", "text" => "Hello"})
Asserts that a prompt definition is valid.
Examples
prompt = %{
"name" => "sample_prompt",
"description" => "A sample prompt",
"arguments" => [
%{"name" => "topic", "description" => "The topic", "required" => true}
]
}
assert_valid_prompt(prompt)
Asserts that a resource definition is valid.
Examples
resource = %{
"uri" => "file://data.txt",
"name" => "Sample Data",
"description" => "Sample data file",
"mimeType" => "text/plain"
}
assert_valid_resource(resource)
Asserts that a tool definition is valid.
Examples
tool = %{
"name" => "sample_tool",
"description" => "A sample tool",
"inputSchema" => %{"type" => "object"}
}
assert_valid_tool(tool)
Asserts that a tool result contains valid content.
Examples
result = %{"content" => [%{"type" => "text", "text" => "Hello"}]}
assert_valid_tool_result(result)