Coverage for tests / unit / utils / async_tool_executor / test_run_tool_async.py: 100%
46 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for AsyncToolExecutor.run_tool_async method."""
3from __future__ import annotations
5import asyncio
6from typing import Any, cast
8from assertpy import assert_that
10from lintro.enums.action import Action
11from lintro.models.core.tool_result import ToolResult
12from lintro.plugins.base import BaseToolPlugin
13from lintro.utils.async_tool_executor import AsyncToolExecutor
15from .conftest import MockToolDefinition, MockToolPlugin
18def test_run_tool_async_check_success(executor: AsyncToolExecutor) -> None:
19 """Test successful async execution of check action.
21 Args:
22 executor: AsyncToolExecutor fixture.
23 """
24 tool = MockToolPlugin(
25 definition=MockToolDefinition(name="test_tool"),
26 )
28 async def run_test() -> Any:
29 # MockToolPlugin implements the same interface as BaseToolPlugin for testing
30 return await executor.run_tool_async(
31 cast(BaseToolPlugin, tool),
32 paths=["."],
33 action=Action.CHECK,
34 )
36 result = asyncio.run(run_test())
38 assert_that(result.success).is_true()
39 assert_that(result.name).is_equal_to("test_tool")
40 assert_that(tool.check_called).is_true()
41 assert_that(tool.fix_called).is_false()
44def test_run_tool_async_fix_success(executor: AsyncToolExecutor) -> None:
45 """Test successful async execution of fix action.
47 Args:
48 executor: AsyncToolExecutor fixture.
49 """
50 tool = MockToolPlugin(
51 definition=MockToolDefinition(name="fix_tool"),
52 )
54 async def run_test() -> Any:
55 # MockToolPlugin implements the same interface as BaseToolPlugin for testing
56 return await executor.run_tool_async(
57 cast(BaseToolPlugin, tool),
58 paths=["."],
59 action=Action.FIX,
60 )
62 result = asyncio.run(run_test())
64 assert_that(result.success).is_true()
65 assert_that(tool.fix_called).is_true()
66 assert_that(tool.check_called).is_false()
69def test_run_tool_async_with_options(executor: AsyncToolExecutor) -> None:
70 """Test async execution passes options correctly.
72 Args:
73 executor: AsyncToolExecutor fixture.
74 """
75 received_options: dict[str, Any] = {}
77 def check_with_capture(
78 paths: list[str],
79 options: dict[str, Any] | None = None,
80 ) -> ToolResult:
81 nonlocal received_options
82 received_options = options or {}
83 return ToolResult(
84 name="capture_tool",
85 success=True,
86 output="",
87 issues_count=0,
88 )
90 tool = MockToolPlugin(definition=MockToolDefinition(name="capture_tool"))
91 # Use object.__setattr__ to bypass dataclass method assignment restriction
92 object.__setattr__(tool, "check", check_with_capture)
94 async def run_test() -> Any:
95 # MockToolPlugin implements the same interface as BaseToolPlugin for testing
96 return await executor.run_tool_async(
97 cast(BaseToolPlugin, tool),
98 paths=["."],
99 action=Action.CHECK,
100 options={"verbose": True, "fix": False},
101 )
103 asyncio.run(run_test())
105 assert_that(received_options).contains_key("verbose")
106 assert_that(received_options["verbose"]).is_true()
109def test_run_tool_async_with_failure(executor: AsyncToolExecutor) -> None:
110 """Test async execution handles tool failure.
112 Args:
113 executor: AsyncToolExecutor fixture.
114 """
115 failed_result = ToolResult(
116 name="failing_tool",
117 success=False,
118 output="Error occurred",
119 issues_count=5,
120 )
121 tool = MockToolPlugin(
122 definition=MockToolDefinition(name="failing_tool"),
123 check_result=failed_result,
124 )
126 async def run_test() -> Any:
127 # MockToolPlugin implements the same interface as BaseToolPlugin for testing
128 return await executor.run_tool_async(
129 cast(BaseToolPlugin, tool),
130 paths=["."],
131 action=Action.CHECK,
132 )
134 result = asyncio.run(run_test())
136 assert_that(result.success).is_false()
137 assert_that(result.issues_count).is_equal_to(5)