🔎

テスト実行の標準メカニズムを目指すOpenTestFactoryの調査・実験

に公開

目的

このドキュメントはテストを計画,実行,結果の公開のための標準メカニズムをめざすOpenTestFactoryについて調査・実験した結果を記す。

実際に構築したOpenTestFactoryのテスト実行環境は以下で確認できる。
https://github.com/mima3/research_tms/tree/main/annex/opentestfactory

OpenTestFactoryの概要

OpenTestFactoryでは、YAML または JSON で PEaC (Planned Execution as Code) を記述し、テスト実行ジョブを定義する。
このファイルをPEaC (Planned Execution as Code) ファイルといい、以下のようにコマンドをジョブと、そのジョブで実行するコマンドを記載する。

metadata:
  name: test-agent
jobs:
  unit_test:
    runs-on: [linux,pytest]
    steps:
      - name: ソースコードの取得
        uses: "actions/checkout@v2"
        with:
          repository: "https://github.com/mima3/test_asyncio"
          ref: "main"
      - name: 初期設定
        run: pip install --no-input -q aiofiles
      - name: テスト実行
        run: |
          cd test_asyncio/py313
          pytest -q --junitxml=junit.xml -o junit_family=xunit2 -o junit_duration_report=call test
      - name: 結果のアップロード
        run: |
          echo "::upload type=application/xml,name=junit.xml::`pwd`/test_asyncio/py313/junit.xml"

詳しい構文についてはワークフローの構文を参照する。

PEaC がどのように実行されるかを示す図を以下に示す。

PEaCファイルはOpenTestFactory Orchestrator内のReceptionist serviceに送信される。
Receptionist service は PEaC を受け付け、Arranger が runs-on・tags・namespaces を考慮して実行先の Agent を選択する。
Agentはジョブの内容を実行したのち、その結果をResults publishersに送る。

詳しくは以下を参照のこと。

OpenTestFactoryの実験

以下はOpenTestFactoryの環境をDocker環境に構築して実験を行う。

https://github.com/mima3/research_tms/tree/main/annex/opentestfactory/docker

環境作成

今回の実験では以下のコンテナを起動した。

  • orchestrator(opentestfactory/allinone:latest)
    • 7774 receptionist ワークフローを受け付けるサービス
    • 7775 observer ワークフローの進捗情報を監視するサービス
    • 7776 killswitch ワークフローを停止するサービス
    • 7796 insightcollector 実行イベントを集計してサマリーを作るサービス
    • 38368 eventbus サービス間のイベント配信(pub/sub)の土台
    • 34537 localstore Agentがアップロードする添付ファイルの保管
    • 24368 agent channel Arranger↔Agent間のハブ。runs-on×tags×namespacesでマッチしたAgentにジョブを渡す。
  • pytest-agent
    • pythonとpytestが入っているAgent
  • playwright-agent
    • pythonとplaywright(node.js)が入っている環境

agentは起動時に以下のコマンドを実行して、自身をorchestratorに登録する

opentf-agent --tags linux,pytest --host http://orchestrator --port 24368
      --token \"$TOKEN\" --verify false --script_path /tmp

opentf-ctlのインストールと設定

opentf-ctlはOpenTestFactoryのコマンドラインツールで指定のOpenTestFactory Orchestratorに対して、ワークフローの登録、ワークフローの結果確認、添付ファイルの取得を行う。

まず、configファイルを用意する。これには接続先情報やtoken情報が記載されている。

#
# Generated opentfconfig
# (generated by opentf-ctl version 0.54.0)
#
apiVersion: opentestfactory.org/v1alpha1
contexts:
- context:
    orchestrator: default
    user: default
  name: default
current-context: default
kind: CtlConfig
orchestrators:
- name: default
  orchestrator:
    insecure-skip-tls-verify: false
    server: http://localhost
    services:
      agentchannel:
        port: 24368
      eventbus:
        port: 38368
      insightcollector:
        port: 7796
      killswitch:
        port: 7776
      localstore:
        port: 34537
      observer:
        port: 7775
      qualitygate:
        port: 12312
      receptionist:
        port: 7774
users:
- name: default
  user:
    token: eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ5b3VyIGNvbXBhbnkiLCJzdWIiOiJ5b3VyIG5hbWUifQ.FL_1O3Z6X5oDwl9cs9njKu6xnL6wkjQ1-BnZZoDDr1OExBWZZR0BrfUrim9mel08WaKQz0cZBaEMdikSQ3GkqJKtTpMxUPHvMtkk4RAa3DgiuC1oH-hidhHPe8mVRfWipP33L1mWuRfjdcX0vMAsKU1v0hRMjUyl-l_1Gj4EcSsXeZZmuFK1HDDsL0PtQXt5b0gxpZXbZOZa2tTajC80uvbCJ0uQZImEPNhvabh90T-qMw_tkgQmEPMyFsiZ-tw7oCl7tUoeukgQIt1uR2ul77cMZhVzrVnWL2l7w70cyH8M0S7sCQjrZbT2O_IA5-GD9swummDq70J_oWuGR5NhynQi2lZh0vCoRlp1m9ULXFhQ1-60l2SgCne2FV1pTl3Etr9Qw0hqVGmeANTI78XpMTtgHJrUUCLfLLg6WcCtoPAxfwNeAkJX62GKQU8rzQLSLhHEIqjCwyIxJCQaVAIEeB9cPXWdAo_5iFosxBI5VApDMOTBBffxbaJuVErhkcxUa_nPfjF7FPDlVZESHON1XGmjakFQhupkRzMhsf9UDeHcZCI63mDvT9h_cB7POAHrdCkeC0ufVQMv5j4NutZPsFOkzkvbIIeD1ol0LH0M2I1ZjQd7Gpzha51NOTFAVkXGc6p4blVrxKnrKjXgogvPNBvzVVguof-oAqX_eLSg1j8

ここで指定したTOKENはorchestratorが使用するtrusted_key.pemとtrusted_key.pubから作成されたものである。
実際の作り方はmake_token.pyを参照のこと。

たとえば、ワークフローの実行する場合は以下のようなコマンドとなる。

opentf-ctl --opentfconfig ./config run workflow workflow/hello.yml

単純なワークフローの実行例

以下の単純なワークフローを実行する例を示す。

metadata:
  name: hello-from-agent
jobs:
  echo1:
    runs-on: [linux]
    steps:
      - run: echo "Hello from OpenTestFactory agent 1"
      - run: uname -a
  echo2:
    runs-on: [linux]
    steps:
      - run: echo "Hello from OpenTestFactory agent 2"
      - run: uname -a

このワークフローは2つのジョブがlinuxを対象にechouname -aを実行するだけである。
これを実行するにはrun workflowコマンドを実行する。

% pipenv shell # pythonの仮想環境に入る
% opentf-ctl --opentfconfig ./config  run workflow workflow/hello.yml                 
Workflow 7916bfb1-11c9-41d3-98c3-886abc425e5f is running.

ここで実行したワークフローの実行状況を見るには以下のコマンドを実行する。
まず、最近実行したワークフローの一覧はget workflowsコマンドを実行する。

% opentf-ctl --opentfconfig ./config get workflows                   
WORKFLOW_ID                           STATUS  NAME
a6dce077-4b68-4511-a823-ef7278c7a00b  DONE    test-agent
fdc9f83c-4502-4336-b475-cb9c918eac4d  DONE    hello-from-agent
57088f1f-e5cb-4eb1-bfd7-f313e51c100c  DONE    Playwright (Node) with provider demo
7916bfb1-11c9-41d3-98c3-886abc425e5f  DONE    hello-from-agent

7916bfb1-11c9-41d3-98c3-886abc425e5fが実行されていることが確認できる。
この実行ログを取得するには、get workflow <ワークフローID>を実行する。

% opentf-ctl --opentfconfig ./config get workflow 7916bfb1-11c9-41d3-98c3-886abc425e5f
Workflow  hello-from-agent
(running in namespace "default")
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Requesting execution environment providing "linux" in namespace "default" for job "echo1"
[2025-09-21T16:31:25] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Requesting execution environment providing "linux" in namespace "default" for job "echo2"
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Running command: echo "Hello fro...
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Hello from OpenTestFactory agent 1
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Running command: uname -a
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Linux 9889c29332ef 6.10.14-linuxkit #1 SMP PREEMPT_DYNAMIC Wed Sep  3 15:37:39 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
[2025-09-21T16:31:25] [Job 61d2eba7-ed93-4278-8a43-d3bd2d4faaeb] Releasing execution environment for job "echo1"
[2025-09-21T16:31:25] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Running command: echo "Hello fro...
[2025-09-21T16:31:30] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Hello from OpenTestFactory agent 2
[2025-09-21T16:31:30] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Running command: uname -a
[2025-09-21T16:31:30] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Linux 9889c29332ef 6.10.14-linuxkit #1 SMP PREEMPT_DYNAMIC Wed Sep  3 15:37:39 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
[2025-09-21T16:31:30] [Job 96e2a315-2715-45aa-ba78-0022f4f8f43b] Releasing execution environment for job "echo2"
Workflow completed successfully.

job で指定したコマンドが実行されていることが確認できる。

Playwrightによるテストの実行例

Playwrightによるテストの実行例を示す。
まず以下のようなワークフローを作成する

apiVersion: opentestfactory.org/v1
kind: Workflow
metadata:
  name: "Playwright (Node) with provider demo"
jobs:
  e2e:
    runs-on: [linux,playwright] 
    steps:
      - name: ソースコードの取得
        uses: "actions/checkout@v2"
        with:
          repository: "https://github.com/mima3/research_tms"
          ref: "main"

      - name: Install deps
        variables:
          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "0"
        run: |
          cd research_tms/annex/opentestfactory/docker/playwright/workspace
          ls -lt
          pwd
          echo ${OPENTF_WORKSPACE}
          npm ci || npm i
          npx playwright install --with-deps

      # 公式 Playwright プロバイダーで実行
      - uses: playwright/npx@v1
        with:
          test: ${OPENTF_WORKSPACE}/research_tms/annex/opentestfactory/docker/playwright/workspace/tests/*.spec.ts
          reporters: ['junit','html']   # pw_junit_report.xml と index.html を自動添付
        working-directory: ${OPENTF_WORKSPACE}/research_tms/annex/opentestfactory/docker/playwright/workspace

今回の例ではActionsプロバイダーを使用してGitHubからコードを取得後、Playwrightの場合はPlaywright プロバイダーを使用してテストをしている。

ワークフローを実行するにはrun workflowコマンド

% opentf-ctl --opentfconfig ./config  run workflow workflow/playwright.yml            
Workflow e7676b27-bff3-4f68-91e4-ccb9b0d3360e is running.

進捗の確認にはget workflow <ワークフローID>コマンドを実行する。

 % opentf-ctl --opentfconfig ./config get workflow e7676b27-bff3-4f68-91e4-ccb9b0d3360e

ブラウザのインストールなどの作業があるため、このテストには時間がかかる。
このテストについてはテスト中に添付ファイルが作成される。これをローカルにコピーするにはcp <ワークフローID> <ローカルフォルダ>コマンドを実行する。

% opentf-ctl --opentfconfig ./config cp "e7676b27-bff3-4f68-91e4-ccb9b0d3360e:*" ./tmp
Attachment index.html (389d5947-1c77-426a-b214-116b54508add) is downloaded at tmp/e2e/3_*.spec.ts/index.html.
Attachment pw_junit_report.xml (df49af20-3ae9-4b0d-84f1-6d9cc663ef0c) is downloaded at tmp/e2e/3_*.spec.ts/pw_junit_report.xml.
Attachment executionlog.txt (ce790a7e-bc3c-4818-b7be-9e829a217451) is downloaded at tmp/executionlog.txt.
Attachment executionreport.html (b678c2c2-ba29-425b-a480-a73f1208e3ff) is downloaded at tmp/executionreport.html.
Attachment executionreport.xml (8f9cdaf4-1cae-4ce0-83ab-587085e08e8e) is downloaded at tmp/executionreport.xml.

いくつかのファイルがダウンロードされ、その中のexecutionreport.htmlには、このワークフローのテスト結果がグラフなどでわかりやすく可視化される。

pytestによるテストの実行例

以下のようにpytestによるテストも行える。

metadata:
  name: test-agent
jobs:
  unit_test:
    runs-on: [linux,pytest]
    steps:
      - name: ソースコードの取得
        uses: "actions/checkout@v2"
        with:
          repository: "https://github.com/mima3/test_asyncio"
          ref: "main"
      - name: 初期設定
        run: pip install --no-input -q aiofiles
      - name: テスト実行
        run: |
          cd test_asyncio/py313
          pytest -q --junitxml=junit.xml -o junit_family=xunit2 -o junit_duration_report=call test
      - name: 結果のアップロード
        run: |
          echo "::upload type=application/xml,name=junit.xml::`pwd`/test_asyncio/py313/junit.xml"

テストも実行し、結果もJUnit形式でアップロードしているが、executionreport.htmlは作成されない。
これはpytesttがProvidersとして作成されていないためである。
Providersでサポートされていない場合、テストの実行自体はできるが、そのレポートは作成されない。そのため、自分でProviderを作成するか、レポートを諦める必要がある。

まとめ

今回は OpenTestFactory について調査・検証した結果をまとめた。実験を通じて テスト実行基盤として動作することは確認できたが、他の CI/CD ツールに対する顕著な優位性は見いだせなかった。
また、知名度が低く、トラブル発生時の情報収集や解決は 相応に困難だったため、積極採用には慎重な判断が必要だろう。

しかし、SquashTMというテスト管理ツールとの連携や、テスト実行の起動コスト最小化を重視する用途では、引き続き検討の余地がある。

Discussion