Skip to main content
Glama
run_tests.py3.78 kB
"""Tool for executing Unity Test Runner suites.""" from typing import Annotated, Literal, Any from fastmcp import Context from pydantic import BaseModel, Field from models import MCPResponse from services.registry import mcp_for_unity_tool from services.tools import get_unity_instance_from_context from transport.unity_transport import send_with_unity_instance from transport.legacy.unity_connection import async_send_command_with_retry class RunTestsSummary(BaseModel): total: int passed: int failed: int skipped: int durationSeconds: float resultState: str class RunTestsTestResult(BaseModel): name: str fullName: str state: str durationSeconds: float message: str | None = None stackTrace: str | None = None output: str | None = None class RunTestsResult(BaseModel): mode: str summary: RunTestsSummary results: list[RunTestsTestResult] class RunTestsResponse(MCPResponse): data: RunTestsResult | None = None @mcp_for_unity_tool( description="Runs Unity tests for the specified mode" ) async def run_tests( ctx: Context, mode: Annotated[Literal["EditMode", "PlayMode"], "Unity test mode to run"] = "EditMode", timeout_seconds: Annotated[int | str, "Optional timeout in seconds for the test run"] | None = None, test_names: Annotated[list[str] | str, "Full names of specific tests to run (e.g., 'MyNamespace.MyTests.TestMethod')"] | None = None, group_names: Annotated[list[str] | str, "Same as test_names, except it allows for Regex"] | None = None, category_names: Annotated[list[str] | str, "NUnit category names to filter by (tests marked with [Category] attribute)"] | None = None, assembly_names: Annotated[list[str] | str, "Assembly names to filter tests by"] | None = None, ) -> RunTestsResponse: unity_instance = get_unity_instance_from_context(ctx) # Coerce timeout defensively (string/float -> int) def _coerce_int(value, default=None): if value is None: return default try: if isinstance(value, bool): return default if isinstance(value, int): return int(value) s = str(value).strip() if s.lower() in ("", "none", "null"): return default return int(float(s)) except Exception: return default # Coerce string or list to list of strings def _coerce_string_list(value) -> list[str] | None: if value is None: return None if isinstance(value, str): return [value] if value.strip() else None if isinstance(value, list): result = [str(v).strip() for v in value if v and str(v).strip()] return result if result else None return None params: dict[str, Any] = {"mode": mode} ts = _coerce_int(timeout_seconds) if ts is not None: params["timeoutSeconds"] = ts # Add filter parameters if provided test_names_list = _coerce_string_list(test_names) if test_names_list: params["testNames"] = test_names_list group_names_list = _coerce_string_list(group_names) if group_names_list: params["groupNames"] = group_names_list category_names_list = _coerce_string_list(category_names) if category_names_list: params["categoryNames"] = category_names_list assembly_names_list = _coerce_string_list(assembly_names) if assembly_names_list: params["assemblyNames"] = assembly_names_list response = await send_with_unity_instance(async_send_command_with_retry, unity_instance, "run_tests", params) await ctx.info(f'Response {response}') return RunTestsResponse(**response) if isinstance(response, dict) else response

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CoplayDev/unity-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server