はじめに

Maestro の maestro test コマンドでは、--test-output-dir--debug-output などのオプションで、スクリーンショットやログなどの artifact が出力されます。両者はどちらも「artifact の保存先を指定するオプション」に見えるのですが、実際には扱うファイルがやや異なります。

この違いを意識しないと、落ちたテストの調査で「あるはずの artifact が見つからない」ということが起こりえます。 たとえば、スクリーンショットを探していたら maestro.log しか入っていなかったり、逆にログだけ別ディレクトリに出ていたり。

そこで、この記事では maestro test の artifact 周りを整理します。また、ドキュメントとサンプルコードを頼りに、これらのオプションの違いや使用例を探ってみます。

この記事で最初に押さえたいのは、次の4点です。

  • --test-output-dir はスクリーンショットや動画の主な置き場
  • --debug-outputmaestro.log の主な置き場
  • commands-*.json は artifact 調査で見ることになる主要なファイル
  • --flatten-debug-output--debug-output の artifact 群のディレクトリ階層をフラットにする

レポート系のフォーマットは下記の2つです。

  • --format : レポートのフォーマット。
    • 例:--format junit , --format html , --format html-detailed
  • --output : 上記のレポートの出力場所。省略した場合はカレントディレクトリに出力。
    • 例:--output build/report.xml

なお、AI 系のレポートは生成条件が別なのでこの記事では深追いしません。

参考:https://docs.maestro.dev/maestro-flows/workspace-management/ai-test-analysis

1. --test-output-dir / --debug-output / --flatten-debug-output オプションの早見表

--test-output-dir / --debug-output / --flatten-debug-output オプションの早見表をご覧ください。ここでは「flag の役割」と「実際に目に入る artifact」を分けて書きます。実際の挙動を見ると、ドキュメント のように、Yes / No の二値だけで読むと誤解しやすいので、まずは役割ベースで整理するほうがよいかと思います。

オプション主な責務実測でまず確認しやすい artifact補足
--test-output-dirテスト成果物の集約先を指定Screenshots & Video, commands-*.json, AI reports--debug-output と同じ場所を指すと maestro.log も同居
--debug-outputデバッグ用ログの集約先を指定maestro.log--test-output-dir と同じ場所を指すと他の artifact も同居
--flatten-debug-output--debug-output の出力構造をフラットに保存対象は変わらない

公式 docs では、出力先が異なる場合は --debug-output 側には maestro.log のみが入り、--test-output-dir 側にはそれ以外の artifact が入ると説明されています。

Different directories: If the flags point to different directories, the --debug-output directory will receive only the maestro.log, while the –test-output-dir will receive everything else (Screenshots, Videos, Commands JSON, and AI Reports).

参考: https://docs.maestro.dev/maestro-flows/workspace-management/test-reports-and-artifacts#whats-inside-the-artifact-folder

この表からわかることは、--test-output-dir はスクリーンショット系と commands-*.json をまず見る場所で、--debug-outputmaestro.log をまず見る場所だという役割分担です。--test-output-dir--debug-output を同じ場所に向けると、artifact はひとつにまとまります。

続いて、各オプションのドキュメントとサンプルコードを追いながら、これらのユースケースについてイメージを膨らませていきましょう。

2. --test-output-dir で扱う artifact とそのユースケース

--test-output-dir の代表的な artifact は Screenshots & Video です。テストが落ちたときの画面の状態を把握するもので、commands-*.json とあわせて確認することになるでしょう。

  • 格納できる artifact
    • Screenshots & Video
    • commands-*.json
    • AI reports

3. --debug-output で扱う artifact とそのユースケース

--debug-output は、デバッグのためのログ出力先です。こちらで主役になるのは maestro.log です。画面上では再現しにくい失敗や、CLI 側の挙動を疑うときはこちらを見ることになるでしょう。

  • 格納できる artifact
    • maestro.log

4. --flatten-debug-output で扱う artifact とそのユースケース

--flatten-debug-output は、階層やタイムスタンプを持つ構成ではなく、主に debug output 側のフラットなディレクトリにまとめたいときに使います。

なお、出力先を集約したい場合は --test-output-dir--debug-output を同じパスに向けます)

5. ところで、初期値はどうなの?

--test-output-dir--debug-output の未指定時の挙動は、公式 docs では下記のように案内されています。

オプション未指定時の挙動
--test-output-dir~/.maestro/tests/<datetime>/ に artifact が保存される
--debug-output~/.maestro/tests/<datetime>/ に artifact が保存される

6. いよいよサンプルのワークフローで artifact を追ってみる

この記事のサンプルでは、artifact を複数のディレクトリに分けるケース1と、ひとつに集約するケース2の2つのワークフローを走らせます。

ケース1: artifact を複数のディレクトリに分ける

--test-output-dir--debug-output 両オプションでそれぞれパスを指定する場合です。

name: test-e2e
"on":
  workflow_dispatch:

jobs:
  maestro-test:
    runs-on: macos-26
    steps:
      - name: checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install Maestro
        run: |
          curl -Ls "https://get.maestro.mobile.dev" | bash
          echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"

      - name: Run Maestro test
        run: |
          maestro test \
            maestro/flows/test-e2e.yaml \
            --test-output-dir artifacts/test-output \
            --debug-output artifacts/debug-output

      - name: Upload test output
        uses: actions/upload-artifact@043fb46 # v7.0.1
        with:
          name: maestro-test-output
          path: artifacts/test-output

      - name: Upload debug output
        uses: actions/upload-artifact@043fb46 # v7.0.1
        with:
          name: maestro-debug-output
          path: artifacts/debug-output
          ## `--debug-output` の配下に `.maestro/tests/<timestamp>/...` のような hidden directory が作られる。
          ## そのため、`actions/upload-artifact` に `include-hidden-files: true` を付けないと、
          ## `maestro.log` などの debug output が artifact 一覧に出てこないことがあります。
          include-hidden-files: true

ワークフローの実行ログ:https://github.com/gkzz/Maestro/actions/runs/30105746100

この検証では、artifact の階層構造は下記のようになりました。出力先を検討する際には、実際に maestro test コマンドを実行し、生成された artifact をダウンロードして確認することをおすすめします。

artifacts/
├── test-output/
│   ├── commands-*.json
│   ├── screenshots/
│   └── video/
└── debug-output/
    └── .maestro/
        └── tests/
            └── <datetime>/
                └── <flow-name>/
                    └── maestro.log

ケース2: artifact をひとつに集約する

--test-output-dir--debug-output を同じパスに向け、さらに --flatten-debug-output フラグでその中身をフラットにする場合です。

Same directory: If both flags point to the same location, all artifacts are consolidated into that single folder.

参考: https://docs.maestro.dev/maestro-flows/workspace-management/test-reports-and-artifacts#whats-inside-the-artifact-folder

name: test-e2e
"on":
  workflow_dispatch:

jobs:
  maestro-test:
    runs-on: macos-26
    steps:
      - name: checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install Maestro
        run: |
          curl -Ls "https://get.maestro.mobile.dev" | bash
          echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"

      - name: Run Maestro test
        run: |
          maestro test \
            maestro/flows/test-e2e.yaml \
            --test-output-dir artifacts/all \
            --debug-output artifacts/all \
            --flatten-debug-output

      - name: Upload artifacts
        uses: actions/upload-artifact@043fb46 # v7.0.1
        with:
          name: maestro-artifacts
          path: artifacts/all
          # flatten-debug-output で同一ディレクトリへ集約されるため hidden-files は不要

ワークフローの実行ログ: https://github.com/gkzz/Maestro/actions/runs/30138495653

ここでは、--test-output-dir--debug-output の両方を同じ artifacts/all に向けています。--flatten-debug-output は、その同一ディレクトリをフラットに保つためのフラグです。 GitHub Actions の artifact としても、同じディレクトリにまとまって確認しやすい構成になっています。

maestro-artifacts-web-flatten/
└── artifacts/all/
    ├── maestro.log
    ├── commands-*.json
    ├── screenshots/
    └── video/

7. テストが落ちたら見るべき artifact の役割を考えてみる

ここまで、artifact を出力するディレクトリの指定方法についてお話ししました。各 artifact のユースケースについて整理します。

テストが失敗した際、初手としては Screenshots & Video で見た目の状態を確認し、commands-*.json でどの操作で失敗したのかを確認するのがいいのではないでしょうか。詳細を追いたい場合、maestro.log を確認するのがいいかと思います。

commands-*.json に書かれていること

commands-*.json は、各コマンドの実行結果を記録した JSON の配列です。実例ベースで見ると、各レコードは少なくとも次の2つを持っています。

  • command
    • 実行したコマンド本体
    • たとえば tapOnElement のように、実際に実行された操作が入る
  • metadata
    • 実行状態や計測情報
    • たとえば statustimestampduration
    • 失敗時は error が入り、messagestackTrace が追える

実際の出力は、下記のとおりでした。

{
  "command": {
    "takeScreenshotCommand": {
      "path": "blog_artifact_capture",
      "optional": false
    }
  },
  "metadata": {
    "status": "COMPLETED",
    "timestamp": 1784907474987,
    "duration": 447,
    "sequenceNumber": 4,
    "depth": 0,
    (略)
    "artifacts": [
      {
        "type": "TAKE_SCREENSHOT",
        "path": "takeScreenshot/blog_artifact_capture.png"
      }
    ]
  }
}
  • 失敗時( status = FAILED )の場合
{
  "command": {
    "assertConditionCommand": {
      "condition": {
        "visible": {
          "textRegex": "THIS_TEXT_DOES_NOT_EXIST",
          "optional": false
        }
      },
      "optional": false
    }
  },
  "metadata": {
    "status": "FAILED",
    "timestamp": 1784945013607,
    "duration": 14051,
    "error": {
      "message": "Assertion is false: \"THIS_TEXT_DOES_NOT_EXIST\" is visible",
      "debugMessage": "Assertion '\"THIS_TEXT_DOES_NOT_EXIST\" is visible' failed. Check the UI hierarchy in debug artifacts to verify the element state and properties.\n\nPossible causes:\n- Element selector may be incorrect - check if there are similar elements with slightly different names/properties.\n- Element may be temporarily unavailable due to loading state\n- This could be a real regression that needs to be addressed"
    },
    "sequenceNumber": 6,
    "depth": 0,
    (略)
    "artifacts": [
      {
        "type": "SCREEN_HIERARCHY",
        "path": "screen-hierarchy/step-007-assertCondition-THIS_TEXT_DOES_NOT_EXIST.json"
      },
      {
        "type": "SCREENSHOT",
        "path": "screenshots/step-007-assertCondition-THIS_TEXT_DOES_NOT_EXIST.png"
      }
    ]
  }
}

まとめ: 各 artifact のユースケース

  1. --test-output-dir 配下のスクリーンショットや動画で、見た目の状態を把握する
  2. commands-*.json で、どの操作で落ちたかを確認する
    • テストが落ちている場合、metadata.errormessagedebugMessage を読む
  3. 必要なら maestro.log で、CLI 側の詳細な流れを追う

意図は、見た目の状態、失敗した操作、CLI 側の詳細を分けて追えるようにすることです。スクリーンショットや動画は人間が速く状況を把握しやすく、commands-*.json は操作単位で失敗箇所を絞り込みやすいです。maestro.log は最後に細部を確認するために使うと、調査の負担が軽くなりそうです。