自然言語テストシナリオランナーエージェント「Aethr」を触ってみた

Autifyから面白そうなのが公開されていたので触ってみました。
https://github.com/autifyhq/aethr

# 概要
[README](https://github.com/autifyhq/aethr/blob/main/README.md#overview)に以下のように記載されています。（拙訳）
> LLMとMCPを用いて自然言語テストシナリオを実行する、リアルタイムのターミナルフィードバックを提供するコマンドラインAIエージェントです。Aethrは、単純な自然言語テスト記述と自動テストの間のギャップを埋めます。

# 使用方法

使用するLLMのAPIキーを取得して、 ```.env``` に設定します。以下はGPT-4o miniの場合です。[README](https://github.com/autifyhq/aethr/blob/main/README.md#prerequisites)に対応しているLLMの記載方法が載っています。
```bash
OPENAI_MODEL=gpt-4o-mini
OPENAI_API_KEY=<APIキー>
```

以下のコマンドを実行すると、指定したテストシナリオが実行されます。
```bash
npx -y aethr@latest run <テストシナリオのファイル>
```

テストシナリオの実行には、Playwright MCPにいくつか機能追加したものが使われています。詳しくは[README](https://github.com/autifyhq/aethr/blob/main/README.md#usage)に書いてあります。

実行すると、設定ファイル ```aethr.config.mjs``` がデフォルトの内容で作成されます。
今回は、Chromeの日本語環境でテストしてみるために、少し設定を変えて行いました。
```js
/** @type {import("aethr/dist/config/schema.js").ConfigSchema} */
export default {
  profiles: {
    default: {
      mcpServers: {
        playwright: {
          command: "npx",
          args: [
            "-y",
            "@aethr/playwright-mcp@latest",
            ...["--browser", "chrome"], // ブラウザをChromeに変更
            ...["--headless"],
            ...["--user-data-dir", "${TEMP_DIR}"], // ${TEMP_DIR} is given by Aethr per run and cleared after the run
          ],
          env: {
            FORCE_COLOR: "0", // To avoid unnecessary color codes in the assertion failure message
            TRACE: "./trace.zip", // Location to store the trace file
            LANG: "ja_JP.UTF-8" // 日本語環境で実行
          },
        },
      },
      runOptions: {
        recursionLimit: 50,
        temperature: 0.7,
        thinkTool: false,
        reasoning: false,
      },
    },
  },
};
```


# テスト対象
簡単なTODOアプリを作って、READMEにあるようなログインのテストシナリオを作成しました。

## TODOアプリ
* https://v0-todo-app-for-testing.vercel.app/
* 以下のユーザーでログインできます。<br>
    |名前|ID|PASS|
    |---|---|---|
    |織田信長|oda|nobunaga|
    |豊臣秀吉|toyotomi|hideyoshi|
    |徳川家康|tokugawa|ieyasu|

# 試した内容
GPT-o4 miniのモデルで試しました。
（ローカルLLMの ```llama3.2``` 、 ```qwen3``` でもやってみましたが、私の環境では以下のシナリオは正しく実行できませんでした）

## 環境
* Windows 11 Pro 24H2
    * Ubuntu 22.04 on WSL2
    * Node.js v23.5.0

## シナリオ1: 織田信長でログインできる

### テストシナリオ
```md:success-by-oda.md
# テストケースID
TEST-LOGIN-001

# テストケース名
織田信長でログインできる。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    oda
3. 「パスワード」に以下を入力する。
    nobunaga
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    織田信長のToDo
```

### 実行

<details><summary>実行時のログ</summary>

```
$ npx -y aethr@latest run success-by-oda.md 
[2025-05-04 17:53:47.263 +0900] INFO: Debug logs are saved in /home/hoge/fuga/logs/2025-05-04-08-53-47-9f6ff45f.(txt|jsonl)
(node:11770) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[2025-05-04 17:53:47.600 +0900] INFO: Aethr v1.3.0
[2025-05-04 17:53:47.601 +0900] INFO: Run command: success-by-oda.md {"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 17:53:47.606 +0900] INFO: Profile: default {"mcpServers":{"playwright":{"command":"npx","args":["-y","@aethr/playwright-mcp@latest","--browser","chrome","--headless","--user-data-dir","${TEMP_DIR}"],"env":{"FORCE_COLOR":"0","TRACE":"./trace.zip","LANG":"ja_JP.UTF-8"}}},"runOptions":{"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false}}
[2025-05-04 17:53:47.607 +0900] INFO: Run options {"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false,"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 17:53:47.608 +0900] INFO: Reading test file from path: success-by-oda.md
[2025-05-04 17:53:47.608 +0900] INFO: Test file:
# テストケースID
TEST-LOGIN-001

# テストケース名
織田信長でログインできる。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    oda
3. 「パスワード」に以下を入力する。
    nobunaga
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    織田信長のToDo

[2025-05-04 17:53:47.610 +0900] INFO: Starting MCP client stdio - playwright: npx -y @aethr/playwright-mcp@latest --browser chrome --headless --user-data-dir /tmp/c907c03d2af5cc6e9628910ad74b096e
[2025-05-04 17:53:49.205 +0900] INFO: Loaded MCP tools {"tools":"playwright__browser_close, playwright__browser_wait, playwright__browser_resize, playwright__browser_console_messages, playwright__browser_handle_dialog, playwright__browser_file_upload, playwright__browser_install, playwright__browser_press_key, playwright__browser_navigate, playwright__browser_navigate_back, playwright__browser_navigate_forward, playwright__browser_network_requests, playwright__browser_pdf_save, playwright__browser_snapshot, playwright__browser_click, playwright__browser_drag, playwright__browser_hover, playwright__browser_type, playwright__browser_select_option, playwright__browser_take_screenshot, playwright__browser_tab_list, playwright__browser_tab_new, playwright__browser_tab_select, playwright__browser_tab_close, playwright__browser_generate_playwright_test, playwright__browser_assert_contain_text"}
[2025-05-04 17:53:49.231 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":2}
[2025-05-04 17:53:50.194 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00016) Call playwright__browser_navigate({ url: 'https://v0-todo-app-for-testing.vercel.app/' })
[2025-05-04 17:53:50.195 +0900] INFO: LLM end:   1:llm:ChatOpenAI (964ms) {"tokenUsage":{"promptTokens":1742,"completionTokens":31,"totalTokens":1773}}
[2025-05-04 17:53:50.199 +0900] INFO: MCP start: playwright__browser_navigate {"input":{"name":"playwright__browser_navigate","args":{"url":"https://v0-todo-app-for-testing.vercel.app/"},"id":"call_AZ8fqOEtKHRUygwQdVg1ppsK","type":"tool_call"}}
[2025-05-04 17:53:50.832 +0900] INFO: MCP end:   playwright__browser_navigate (630ms) {"content":"\"- Ran Playwright code:\n```js\n// Navigate to https://v0-todo-app-for-testing.vercel.app/\nawait page.goto('https://v0-todo-app-for-testing.vercel.app/');\n```\n\n- Page URL: https://v0-todo-app-for…"}
[2025-05-04 17:53:50.837 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":4}
[2025-05-04 17:53:51.626 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00018) Call playwright__browser_type({ element: 'ユーザー名', ref: 's1e15', text: 'oda' })
[2025-05-04 17:53:51.627 +0900] INFO: LLM end:   1:llm:ChatOpenAI (791ms) {"tokenUsage":{"promptTokens":2028,"completionTokens":31,"totalTokens":2059}}
[2025-05-04 17:53:51.630 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"ユーザー名","ref":"s1e15","text":"oda"},"id":"call_z7rxjt7YnkXckcv6GZLU5Kxc","type":"tool_call"}}
[2025-05-04 17:53:52.703 +0900] INFO: MCP end:   playwright__browser_type (1.07s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"oda\\" into \\"ユーザー名\\"\nawait page.getByRole('textbox', { name: 'ユーザー名' }).fill('oda');\n```\n\n- Page URL: https://v0-todo-app-for-testing.vercel.ap…"}
[2025-05-04 17:53:52.708 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":6}
[2025-05-04 17:53:53.999 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00020) Call playwright__browser_type({ element: 'パスワード', ref: 's2e18', text: 'nobunaga' })
[2025-05-04 17:53:54.000 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.29s) {"tokenUsage":{"promptTokens":2314,"completionTokens":35,"totalTokens":2349}}
[2025-05-04 17:53:54.004 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"パスワード","ref":"s2e18","text":"nobunaga"},"id":"call_C6cF8fZQK1iKh3UQdybpYRia","type":"tool_call"}}
[2025-05-04 17:53:55.054 +0900] INFO: MCP end:   playwright__browser_type (1.05s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"nobunaga\\" into \\"パスワード\\"\nawait page.getByRole('textbox', { name: 'パスワード' }).fill('nobunaga');\n```\n\n- Page URL: https://v0-todo-app-for-testing…"}
[2025-05-04 17:53:55.059 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":8}
[2025-05-04 17:53:55.952 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00022) Call playwright__browser_click({ element: 'ログイン', ref: 's3e19' })
[2025-05-04 17:53:55.953 +0900] INFO: LLM end:   1:llm:ChatOpenAI (895ms) {"tokenUsage":{"promptTokens":2616,"completionTokens":26,"totalTokens":2642}}
[2025-05-04 17:53:55.956 +0900] INFO: MCP start: playwright__browser_click {"input":{"name":"playwright__browser_click","args":{"element":"ログイン","ref":"s3e19"},"id":"call_XQ6uIYyneWJRSlTPgD7SXiDO","type":"tool_call"}}
[2025-05-04 17:53:57.052 +0900] INFO: MCP end:   playwright__browser_click (1.10s) {"content":"\"- Ran Playwright code:\n```js\n// Click ログイン\nawait page.getByRole('button', { name: 'ログイン' }).click();\n```\n\n- Page URL: https://v0-todo-app-for-testing.vercel.app/tasks\n- Page Title: To…"}
[2025-05-04 17:53:57.057 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":10}
[2025-05-04 17:53:58.182 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00025) Call playwright__browser_assert_contain_text({ element: '織田信長のToDo', ref: 's4e8', against: 'element', expected: '織田信長のToDo' })
[2025-05-04 17:53:58.183 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.13s) {"tokenUsage":{"promptTokens":2898,"completionTokens":50,"totalTokens":2948}}
[2025-05-04 17:53:58.186 +0900] INFO: MCP start: playwright__browser_assert_contain_text {"input":{"name":"playwright__browser_assert_contain_text","args":{"element":"織田信長のToDo","ref":"s4e8","against":"element","expected":"織田信長のToDo"},"id":"call_wQPbNDPNtNgtW1K59cxCON9G","type":"tool_call"}}
[2025-05-04 17:53:58.213 +0900] INFO: MCP end:   playwright__browser_assert_contain_text (27ms) {"content":"[{\"type\":\"text\",\"text\":\"{\\"result\\":\\"PASS\\",\\"against\\":\\"element\\"}\"},{\"type\":\"text\",\"text\":\"- Ran Playwright code:\n```js\n// Assert 織田信長のToDo contains 織田信長のToDo\nawait expect(page.getBy…"}
[2025-05-04 17:53:58.218 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
テストケースTEST-LOGIN-001が成功しました。
[2025-05-04 17:53:58.874 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00025) Text {"textLength":28}
[2025-05-04 17:53:58.875 +0900] INFO: LLM end:   1:llm:ChatOpenAI (657ms) {"tokenUsage":{"promptTokens":3070,"completionTokens":14,"totalTokens":3084}}
[2025-05-04 17:53:58.880 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
{"summary":"1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開く。2. 「ユーザー名」のフィールドに 'oda' を入力する。3. 「パスワード」のフィールドに 'nobunaga' を入力する。4. 「ログイン」ボタンを押す。5. ページが '織田信長のToDo' という文言を含むことを検証する。","result":"PASS"}
[2025-05-04 17:54:01.942 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00020) Text {"textLength":214}
[2025-05-04 17:54:01.943 +0900] INFO: LLM end:   1:llm:ChatOpenAI (3.06s) {"tokenUsage":{"promptTokens":1603,"completionTokens":115,"totalTokens":1718}}
[2025-05-04 17:54:01.948 +0900] INFO: Test result: PASS, Summary:
1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開く。2. 「ユーザー名」のフィールドに 'oda' を入力する。3. 「パスワード」のフィールドに 'nobunaga' を入力する。4. 「ログイン」ボタンを押す。5. ページが '織田信長のToDo' という文言を含むことを検証する。
[2025-05-04 17:54:01.949 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00145) Total input: $0.00010/655tk output: $0.00018/302tk cachedRead: $0.00117/15,616tk cachedWrite: $0.00000/0tk
[2025-05-04 17:54:01.949 +0900] INFO: Closing MCP client: playwright
```
</details>

ログを見ると、Playwright MCPを動かして、テストシナリオを実行しているのが分かります。
```
[2025-05-04 17:53:51.630 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"ユーザー名","ref":"s1e15","text":"oda"},"id":"call_z7rxjt7YnkXckcv6GZLU5Kxc","type":"tool_call"}}
```

最後のほうでテストが成功したことも出力されています。
```
テストケースTEST-LOGIN-001が成功しました。
```
jsonでの結果も出ており、```result```が```PASS```になっています。
```json
{"summary":"1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開く。2. 「ユーザー名」のフィールドに 'oda' を入力する。3. 「パスワード」のフィールドに 'nobunaga' を入力する。4. 「ログイン」ボタンを押す。5. ページが '織田信長のToDo' という文言を含むことを検証する。","result":"PASS"}
```


## シナリオ2: 徳川慶喜はログインできない

アカウントがあるのは**徳川家康**なので、慶喜はできません :(

### テストシナリオ
```fail-by-yoshinobu.md
# テストケースID
TEST-LOGIN-002

# テストケース名
徳川慶喜でログインできない。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    tokugawa
3. 「パスワード」に以下を入力する。（このパスワードは間違っている）
    yoshinobu
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    ユーザー名またはパスワードが正しくありません
```

### 実行

<details><summary>実行時のログ</summary>

```
$ npx -y aethr@latest run fail-by-yoshinobu.md 
[2025-05-04 18:40:06.261 +0900] INFO: Debug logs are saved in /home/hoge/fuga/logs/2025-05-04-09-40-06-f39826c8.(txt|jsonl)
(node:31462) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[2025-05-04 18:40:06.878 +0900] INFO: Aethr v1.3.0
[2025-05-04 18:40:06.879 +0900] INFO: Run command: fail-by-yoshinobu.md {"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 18:40:06.885 +0900] INFO: Profile: default {"mcpServers":{"playwright":{"command":"npx","args":["-y","@aethr/playwright-mcp@latest","--browser","chrome","--headless","--user-data-dir","${TEMP_DIR}"],"env":{"FORCE_COLOR":"0","TRACE":"./trace.zip","LANG":"ja_JP.UTF-8"}}},"runOptions":{"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false}}
[2025-05-04 18:40:06.886 +0900] INFO: Run options {"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false,"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 18:40:06.887 +0900] INFO: Reading test file from path: fail-by-yoshinobu.md
[2025-05-04 18:40:06.888 +0900] INFO: Test file:
# テストケースID
TEST-LOGIN-002

# テストケース名
徳川慶喜でログインできない。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    tokugawa
3. 「パスワード」に以下を入力する。（このパスワードは間違っている）
    yoshinobu
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    ユーザー名またはパスワードが正しくありません

[2025-05-04 18:40:06.889 +0900] INFO: Starting MCP client stdio - playwright: npx -y @aethr/playwright-mcp@latest --browser chrome --headless --user-data-dir /tmp/b27b9556361be23de106f1b7e6375933
[2025-05-04 18:40:08.773 +0900] INFO: Loaded MCP tools {"tools":"playwright__browser_close, playwright__browser_wait, playwright__browser_resize, playwright__browser_console_messages, playwright__browser_handle_dialog, playwright__browser_file_upload, playwright__browser_install, playwright__browser_press_key, playwright__browser_navigate, playwright__browser_navigate_back, playwright__browser_navigate_forward, playwright__browser_network_requests, playwright__browser_pdf_save, playwright__browser_snapshot, playwright__browser_click, playwright__browser_drag, playwright__browser_hover, playwright__browser_type, playwright__browser_select_option, playwright__browser_take_screenshot, playwright__browser_tab_list, playwright__browser_tab_new, playwright__browser_tab_select, playwright__browser_tab_close, playwright__browser_generate_playwright_test, playwright__browser_assert_contain_text"}
[2025-05-04 18:40:08.802 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":2}
[2025-05-04 18:40:09.790 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00016) Call playwright__browser_navigate({ url: 'https://v0-todo-app-for-testing.vercel.app/' })
[2025-05-04 18:40:09.791 +0900] INFO: LLM end:   1:llm:ChatOpenAI (989ms) {"tokenUsage":{"promptTokens":1761,"completionTokens":31,"totalTokens":1792}}
[2025-05-04 18:40:09.796 +0900] INFO: MCP start: playwright__browser_navigate {"input":{"name":"playwright__browser_navigate","args":{"url":"https://v0-todo-app-for-testing.vercel.app/"},"id":"call_qZJ1EcFIAwVHAMMwz1gSSiDP","type":"tool_call"}}
[2025-05-04 18:40:10.977 +0900] INFO: MCP end:   playwright__browser_navigate (1.18s) {"content":"\"- Ran Playwright code:\n```js\n// Navigate to https://v0-todo-app-for-testing.vercel.app/\nawait page.goto('https://v0-todo-app-for-testing.vercel.app/');\n```\n\n- Page URL: https://v0-todo-app-for…"}
[2025-05-04 18:40:10.982 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":4}
[2025-05-04 18:40:11.923 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00018) Call playwright__browser_type({ element: 'ユーザー名', ref: 's1e15', text: 'tokugawa' })
[2025-05-04 18:40:11.924 +0900] INFO: LLM end:   1:llm:ChatOpenAI (942ms) {"tokenUsage":{"promptTokens":2047,"completionTokens":33,"totalTokens":2080}}
[2025-05-04 18:40:11.927 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"ユーザー名","ref":"s1e15","text":"tokugawa"},"id":"call_4eebiD2uRY6tekWTlMsFmbWw","type":"tool_call"}}
[2025-05-04 18:40:13.026 +0900] INFO: MCP end:   playwright__browser_type (1.10s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"tokugawa\\" into \\"ユーザー名\\"\nawait page.getByRole('textbox', { name: 'ユーザー名' }).fill('tokugawa');\n```\n\n- Page URL: https://v0-todo-app-for-testing…"}
[2025-05-04 18:40:13.030 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":6}
[2025-05-04 18:40:14.020 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00020) Call playwright__browser_type({ element: 'パスワード', ref: 's2e18', text: 'yoshinobu' })
[2025-05-04 18:40:14.021 +0900] INFO: LLM end:   1:llm:ChatOpenAI (992ms) {"tokenUsage":{"promptTokens":2341,"completionTokens":35,"totalTokens":2376}}
[2025-05-04 18:40:14.024 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"パスワード","ref":"s2e18","text":"yoshinobu"},"id":"call_caOqGL73qqNboAweC0PoeNIN","type":"tool_call"}}
[2025-05-04 18:40:15.080 +0900] INFO: MCP end:   playwright__browser_type (1.06s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"yoshinobu\\" into \\"パスワード\\"\nawait page.getByRole('textbox', { name: 'パスワード' }).fill('yoshinobu');\n```\n\n- Page URL: https://v0-todo-app-for-testi…"}
[2025-05-04 18:40:15.085 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":8}
[2025-05-04 18:40:15.842 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00022) Call playwright__browser_click({ element: 'ログイン', ref: 's3e19' })
[2025-05-04 18:40:15.843 +0900] INFO: LLM end:   1:llm:ChatOpenAI (759ms) {"tokenUsage":{"promptTokens":2645,"completionTokens":26,"totalTokens":2671}}
[2025-05-04 18:40:15.846 +0900] INFO: MCP start: playwright__browser_click {"input":{"name":"playwright__browser_click","args":{"element":"ログイン","ref":"s3e19"},"id":"call_CvLUiXf4FBzy7NcPfo9z8yzG","type":"tool_call"}}
[2025-05-04 18:40:16.925 +0900] INFO: MCP end:   playwright__browser_click (1.08s) {"content":"\"- Ran Playwright code:\n```js\n// Click ログイン\nawait page.getByRole('button', { name: 'ログイン' }).click();\n```\n\n- Page URL: https://v0-todo-app-for-testing.vercel.app/\n- Page Title: ToDoア…"}
[2025-05-04 18:40:16.929 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":10}
[2025-05-04 18:40:17.919 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00025) Call playwright__browser_assert_contain_text({ element: 'alert', ref: 's4e12', against: 'element', expected: 'ユーザー名またはパスワードが正しくありません' })
[2025-05-04 18:40:17.919 +0900] INFO: LLM end:   1:llm:ChatOpenAI (991ms) {"tokenUsage":{"promptTokens":2970,"completionTokens":48,"totalTokens":3018}}
[2025-05-04 18:40:17.922 +0900] INFO: MCP start: playwright__browser_assert_contain_text {"input":{"name":"playwright__browser_assert_contain_text","args":{"element":"alert","ref":"s4e12","against":"element","expected":"ユーザー名またはパスワードが正しくありません"},"id":"call_nv1klg6s66SJ5PSi07e8Nih8","type":"tool_call"}}
[2025-05-04 18:40:17.952 +0900] INFO: MCP end:   playwright__browser_assert_contain_text (30ms) {"content":"[{\"type\":\"text\",\"text\":\"{\\"result\\":\\"PASS\\",\\"against\\":\\"element\\"}\"},{\"type\":\"text\",\"text\":\"- Ran Playwright code:\n```js\n// Assert alert contains ユーザー名またはパスワードが正しくありません\naw…"}
[2025-05-04 18:40:17.956 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
テストケースは成功しました。
[2025-05-04 18:40:18.575 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00025) Text {"textLength":14}
[2025-05-04 18:40:18.576 +0900] INFO: LLM end:   1:llm:ChatOpenAI (620ms) {"tokenUsage":{"promptTokens":3149,"completionTokens":9,"totalTokens":3158}}
[2025-05-04 18:40:18.581 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
{"summary":"1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開きました。 \n2. 「ユーザー名」に 'tokugawa' を入力しました。 \n3. 「パスワード」に間違った値 'yoshinobu' を入力しました。 \n4. 「ログイン」ボタンをクリックしました。 \n5. アラートに 'ユーザー名またはパスワードが正しくありません' という文言が表示されることを確認しました。","result":"PASS"}
[2025-05-04 18:40:24.464 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00021) Text {"textLength":257}
[2025-05-04 18:40:24.465 +0900] INFO: LLM end:   1:llm:ChatOpenAI (5.88s) {"tokenUsage":{"promptTokens":1677,"completionTokens":130,"totalTokens":1807}}
[2025-05-04 18:40:24.471 +0900] INFO: Test result: PASS, Summary:
1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開きました。 
2. 「ユーザー名」に 'tokugawa' を入力しました。 
3. 「パスワード」に間違った値 'yoshinobu' を入力しました。 
4. 「ログイン」ボタンをクリックしました。 
5. アラートに 'ユーザー名またはパスワードが正しくありません' という文言が表示されることを確認しました。
[2025-05-04 18:40:24.472 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00148) Total input: $0.00009/590tk output: $0.00019/312tk cachedRead: $0.00120/16,000tk cachedWrite: $0.00000/0tk
[2025-05-04 18:40:24.472 +0900] INFO: Closing MCP client: playwright
```
</details>

最後のほうを見ると、今回は
```
テストケースは成功しました。
```
と出力されています。シナリオ1の時と微妙に違うところがLLMで処理している感が出ています。
jsonの結果はちゃんと ```result```が```PASS```になっています。
```json
{"summary":"1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開きました。 \n2. 「ユーザー名」に 'tokugawa' を入力しました。 \n3. 「パスワード」に間違った値 'yoshinobu' を入力しました。 \n4. 「ログイン」ボタンをクリックしました。 \n5. アラートに 'ユーザー名またはパスワードが正しくありません' という文言が表示されることを確認しました。","result":"PASS"}
```
また、シナリオ1のときよりも、丁寧な説明もついています。
```
[2025-05-04 18:40:24.471 +0900] INFO: Test result: PASS, Summary:
1. ブラウザで指定されたURL (https://v0-todo-app-for-testing.vercel.app/) を開きました。 
2. 「ユーザー名」に 'tokugawa' を入力しました。 
3. 「パスワード」に間違った値 'yoshinobu' を入力しました。 
4. 「ログイン」ボタンをクリックしました。 
5. アラートに 'ユーザー名またはパスワードが正しくありません' という文言が表示されることを確認しました。
```



## シナリオ3: 豊臣秀吉でログインしたのに、徳川家康でログインされる

最後に、テストが失敗するパターンです。
豊臣秀吉でログインするので、**徳川家康と表示はされない**ため、このテストシナリオは失敗します。

### テストシナリオ
```toyotomi-is-not-tokugawa.md
# テストケースID
TEST-LOGIN-003

# テストケース名
豊臣秀吉でログインできる。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    toyotomi
3. 「パスワード」に以下を入力する。（このパスワードは間違っている）
    hideyoshi
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    徳川家康のToDo
```

### 実行

<details><summary>実行時のログ</summary>

```
$ npx -y aethr@latest run toyotomi-is-not-tokugawa.md 
[2025-05-04 18:47:44.254 +0900] INFO: Debug logs are saved in /home/hoge/fuga/logs/2025-05-04-09-47-44-583f0475.(txt|jsonl)
(node:34598) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[2025-05-04 18:47:44.861 +0900] INFO: Aethr v1.3.0
[2025-05-04 18:47:44.862 +0900] INFO: Run command: toyotomi-is-not-tokugawa.md {"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 18:47:44.868 +0900] INFO: Profile: default {"mcpServers":{"playwright":{"command":"npx","args":["-y","@aethr/playwright-mcp@latest","--browser","chrome","--headless","--user-data-dir","${TEMP_DIR}"],"env":{"FORCE_COLOR":"0","TRACE":"./trace.zip","LANG":"ja_JP.UTF-8"}}},"runOptions":{"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false}}
[2025-05-04 18:47:44.869 +0900] INFO: Run options {"recursionLimit":50,"temperature":0.7,"thinkTool":false,"reasoning":false,"configFile":"/home/hoge/fuga/aethr.config.mjs","profile":"default"}
[2025-05-04 18:47:44.870 +0900] INFO: Reading test file from path: toyotomi-is-not-tokugawa.md
[2025-05-04 18:47:44.871 +0900] INFO: Test file:
# テストケースID
TEST-LOGIN-003

# テストケース名
豊臣秀吉でログインできる。

# テスト手順と検証
1. ブラウザで以下のURLを開く。
    https://v0-todo-app-for-testing.vercel.app/
2. 「ユーザー名」に以下を入力する。
    toyotomi
3. 「パスワード」に以下を入力する。（このパスワードは間違っている）
    hideyoshi
4. 「ログイン」ボタンを押す。
5. 検証: 以下の文言が表示されている。
    徳川家康のToDo

[2025-05-04 18:47:44.872 +0900] INFO: Starting MCP client stdio - playwright: npx -y @aethr/playwright-mcp@latest --browser chrome --headless --user-data-dir /tmp/8a62f298d7122ae38c740c1c002a5d87
[2025-05-04 18:47:47.429 +0900] INFO: Loaded MCP tools {"tools":"playwright__browser_close, playwright__browser_wait, playwright__browser_resize, playwright__browser_console_messages, playwright__browser_handle_dialog, playwright__browser_file_upload, playwright__browser_install, playwright__browser_press_key, playwright__browser_navigate, playwright__browser_navigate_back, playwright__browser_navigate_forward, playwright__browser_network_requests, playwright__browser_pdf_save, playwright__browser_snapshot, playwright__browser_click, playwright__browser_drag, playwright__browser_hover, playwright__browser_type, playwright__browser_select_option, playwright__browser_take_screenshot, playwright__browser_tab_list, playwright__browser_tab_new, playwright__browser_tab_select, playwright__browser_tab_close, playwright__browser_generate_playwright_test, playwright__browser_assert_contain_text"}
[2025-05-04 18:47:47.463 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":2}
[2025-05-04 18:47:48.935 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00017) Call playwright__browser_navigate({ url: 'https://v0-todo-app-for-testing.vercel.app/' })
[2025-05-04 18:47:48.937 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.47s) {"tokenUsage":{"promptTokens":1753,"completionTokens":31,"totalTokens":1784}}
[2025-05-04 18:47:48.943 +0900] INFO: MCP start: playwright__browser_navigate {"input":{"name":"playwright__browser_navigate","args":{"url":"https://v0-todo-app-for-testing.vercel.app/"},"id":"call_w2D3lzmO4NtdzAffR7GbZDB1","type":"tool_call"}}
[2025-05-04 18:47:50.190 +0900] INFO: MCP end:   playwright__browser_navigate (1.24s) {"content":"\"- Ran Playwright code:\n```js\n// Navigate to https://v0-todo-app-for-testing.vercel.app/\nawait page.goto('https://v0-todo-app-for-testing.vercel.app/');\n```\n\n- Page URL: https://v0-todo-app-for…"}
[2025-05-04 18:47:50.195 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":4}
[2025-05-04 18:47:51.577 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00020) Call playwright__browser_type({ element: 'ユーザー名', ref: 's1e15', text: 'toyotomi' })
[2025-05-04 18:47:51.579 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.38s) {"tokenUsage":{"promptTokens":2039,"completionTokens":33,"totalTokens":2072}}
[2025-05-04 18:47:51.582 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"ユーザー名","ref":"s1e15","text":"toyotomi"},"id":"call_BWSdZwEmL7Vtb4nymOh5HXCF","type":"tool_call"}}
[2025-05-04 18:47:52.674 +0900] INFO: MCP end:   playwright__browser_type (1.09s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"toyotomi\\" into \\"ユーザー名\\"\nawait page.getByRole('textbox', { name: 'ユーザー名' }).fill('toyotomi');\n```\n\n- Page URL: https://v0-todo-app-for-testing…"}
[2025-05-04 18:47:52.679 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":6}
[2025-05-04 18:47:54.592 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00022) Call playwright__browser_type({ element: 'パスワード', ref: 's2e18', text: 'hideyoshi' })
[2025-05-04 18:47:54.593 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.92s) {"tokenUsage":{"promptTokens":2333,"completionTokens":34,"totalTokens":2367}}
[2025-05-04 18:47:54.597 +0900] INFO: MCP start: playwright__browser_type {"input":{"name":"playwright__browser_type","args":{"element":"パスワード","ref":"s2e18","text":"hideyoshi"},"id":"call_hnJuUaJWMsUs5tEQtkFziWMZ","type":"tool_call"}}
[2025-05-04 18:47:55.655 +0900] INFO: MCP end:   playwright__browser_type (1.06s) {"content":"\"- Ran Playwright code:\n```js\n// Fill \\"hideyoshi\\" into \\"パスワード\\"\nawait page.getByRole('textbox', { name: 'パスワード' }).fill('hideyoshi');\n```\n\n- Page URL: https://v0-todo-app-for-testi…"}
[2025-05-04 18:47:55.660 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":8}
[2025-05-04 18:47:56.854 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00024) Call playwright__browser_click({ element: 'ログイン', ref: 's3e19' })
[2025-05-04 18:47:56.855 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.20s) {"tokenUsage":{"promptTokens":2634,"completionTokens":26,"totalTokens":2660}}
[2025-05-04 18:47:56.858 +0900] INFO: MCP start: playwright__browser_click {"input":{"name":"playwright__browser_click","args":{"element":"ログイン","ref":"s3e19"},"id":"call_GL9a4nNnWYJeLgvIq6CCaDPN","type":"tool_call"}}
[2025-05-04 18:47:57.966 +0900] INFO: MCP end:   playwright__browser_click (1.11s) {"content":"\"- Ran Playwright code:\n```js\n// Click ログイン\nawait page.getByRole('button', { name: 'ログイン' }).click();\n```\n\n- Page URL: https://v0-todo-app-for-testing.vercel.app/tasks\n- Page Title: To…"}
[2025-05-04 18:47:57.971 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":10}
[2025-05-04 18:47:59.609 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00027) Call playwright__browser_assert_contain_text({ element: 'main', ref: 's4e5', against: 'page', expected: '徳川家康のToDo' })
[2025-05-04 18:47:59.610 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.64s) {"tokenUsage":{"promptTokens":2915,"completionTokens":42,"totalTokens":2957}}
[2025-05-04 18:47:59.613 +0900] INFO: MCP start: playwright__browser_assert_contain_text {"input":{"name":"playwright__browser_assert_contain_text","args":{"element":"main","ref":"s4e5","against":"page","expected":"徳川家康のToDo"},"id":"call_E5ZfdFiChu27HRF3nlnwchC9","type":"tool_call"}}
[2025-05-04 18:48:04.643 +0900] INFO: MCP end:   playwright__browser_assert_contain_text (5.03s) {"content":"[{\"type\":\"text\",\"text\":\"{\\"result\\":\\"FAIL\\",\\"error\\":\\"Timed out 5000ms waiting for expect(locator).toContainText(expected)\\n\\nLocator: locator('body')\\nExpected string: \\\\"徳川家康のToDo\\\\"\\…"}
[2025-05-04 18:48:04.647 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
Assertion failed against the page for the expected text "徳川家康のToDo".
[2025-05-04 18:48:05.786 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00027) Text {"textLength":68}
[2025-05-04 18:48:05.787 +0900] INFO: LLM end:   1:llm:ChatOpenAI (1.14s) {"tokenUsage":{"promptTokens":3207,"completionTokens":20,"totalTokens":3227}}
[2025-05-04 18:48:05.793 +0900] INFO: LLM start: 1:llm:ChatOpenAI {"messagesLength":12}
{"summary":"1. ブラウザでURL https://v0-todo-app-for-testing.vercel.app/ を開く。ページタイトルは「ToDoアプリ（テスト用）」で、ログインフォームが表示された。2. 「ユーザー名」に'toyotomi'を入力。3. 「パスワード」に間違ったパスワード'hideyoshi'を入力。4. 「ログイン」ボタンを押す。5. ページが遷移し、「豊臣秀吉のToDo」が表示されたが、期待した文言「徳川家康のToDo」は表示されなかった。","result":"FAIL"}
[2025-05-04 18:48:12.436 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00035) Text {"textLength":263}
[2025-05-04 18:48:12.437 +0900] INFO: LLM end:   1:llm:ChatOpenAI (6.64s) {"tokenUsage":{"promptTokens":1746,"completionTokens":146,"totalTokens":1892}}
[2025-05-04 18:48:12.444 +0900] INFO: Test result: FAIL, Summary:
1. ブラウザでURL https://v0-todo-app-for-testing.vercel.app/ を開く。ページタイトルは「ToDoアプリ（テスト用）」で、ログインフォームが表示された。2. 「ユーザー名」に'toyotomi'を入力。3. 「パスワード」に間違ったパスワード'hideyoshi'を入力。4. 「ログイン」ボタンを押す。5. ページが遷移し、「豊臣秀吉のToDo」が表示されたが、期待した文言「徳川家康のToDo」は表示されなかった。
[2025-05-04 18:48:12.445 +0900] INFO: LLM usage: OpenAI/gpt-4o-mini ($0.00171) Total input: $0.00054/3,571tk output: $0.00020/332tk cachedRead: $0.00098/13,056tk cachedWrite: $0.00000/0tk
[2025-05-04 18:48:12.445 +0900] INFO: Closing MCP client: playwright
```
</details>

最後のほうを見ると、今回は
```
Assertion failed against the page for the expected text "徳川家康のToDo".
```
と出力されており、検証に失敗していることが分かります。
JSONの箇所の```result```は```FAIL```となっています。
```json
{"summary":"1. ブラウザでURL https://v0-todo-app-for-testing.vercel.app/ を開く。ページタイトルは「ToDoアプリ（テスト用）」で、ログインフォームが表示された。2. 「ユーザー名」に'toyotomi'を入力。3. 「パスワード」に間違ったパスワード'hideyoshi'を入力。4. 「ログイン」ボタンを押す。5. ページが遷移し、「豊臣秀吉のToDo」が表示されたが、期待した文言「徳川家康のToDo」は表示されなかった。","result":"FAIL"}
```

# まとめ
READMEに書いてあるログインのシナリオのレベルなら、比較的簡単に動かせました。 
モデルを変えたり、もう少し難しいシナリオを試したりもしてみたいなと思います