テスト実行の標準メカニズムを目指す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
を対象にecho
とuname -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