Launchable Advent Calendar 23日目 - custom plugin
Launchableの各機能の利用方法を紹介する Launchable Advent Calendar 23日目です。
はじめに
launchableinc/cliは現在(12/23時点)、約20個のテストランナーをサポートしています。
しかし、使用しているテストランナーがサポートされてないなかったり、独自のテストランナーを使っている場合、出力するレポートフォーマットが独自な場合もあるかもしれません。
そのためlaunchableinc/cliは独自プラグインの利用もサポートしています。
今日は独自プラグイン(custom plugin)の作成方法と使い方を紹介します。
custom plugin
カスタムプラグインが置いてあるディレクトリを launchable
コマンドの --plugins
オプションで指定します。
指定したディレクトリの下の *.py
ファイルを launchbleinc/cliがcustom profileとして読み込み、利用可能になります。
今日はサンプルとして架空のテストランナー/テストフォーマットに対応するプラグインを作成してみます。
対応するテストランナーはE2Eテストを実行する e2e
という架空のコマンドです。
UseCase > Scenario > TestCase
という階層でテストを記述でき、UseCase名.Scenario名
のフォーマットでテストランナーに渡すことで個別にテストが実施できます。
また e2e --list
でテストの一覧が UseCase名.Scenario名
のフォーマットでテストする一覧が出力できます。
Predictive Test Selection(PTS)を行う場合はこのようなコマンドになります。
launchable --plugins custom-plugin/e2e subset e2e > launchable-subset.txt
テストレポートはXML形式で以下のフォーマットのレポートを出力します。テスト結果のレポート時はこのようなコマンドになります。
launchable --plugins custom-plugin/e2e record tests e2e ./report.xml
<result>
<UseCase name="Buy New Item">
<Scenario name="Purchase">
<TestCase name="success" time="3.6" result="success" />
<TestCase name="soldout" time="1.6" result="error" />
</Scenario>
</UseCase>
</result>
カスタムプラグイン
実際に作成したcustom pluginのファイルはこのようになります。
コードはKonboi/launchable-e2e-pluginにもアップしてあります。
このように実行します。
$ cat Konboi/launchable-e2e-plugin/test-list.txt | launchable --plugins Konboi/launchable-e2e-plugin subset --target 100% e2e
'Buy New Item'.'Purchase','Buy New Item'.'Order'
Launchable created subset 17 for build 1671608132 (test session 23) in workspace Konboi/advent-calendar-2022
| | Candidates | Estimated duration (%) | Estimated duration (min) |
|-----------|--------------|--------------------------|----------------------------|
| Subset | 2 | 100 | 3.33333e-05 |
| Remainder | 0 | 0 | 0 |
| | | | |
| Total | 2 | 100 | 3.33333e-05 |
Run `launchable inspect subset --subset-id 17` to view full subset details
$ launchable --plugins Konboi/launchable-e2e-plugin record tests e2e Konboi/launchable-e2e-plugin/example-report.xml
Launchable recorded tests for build launchable-e2e-test (test session 23) to workspace Konboi/advent-calendar-2022 from 1 files:
| Files found | Tests found | Tests passed | Tests failed | Total duration (min) |
|---------------|---------------|----------------|----------------|------------------------|
| 1 | 2 | 1 | 1 | 0.0867 |
import click
from xml.etree import ElementTree as ET
from typing import Dict, Generator, List, Optional
from ..commands.record.case_event import CaseEvent, CaseEventType
from launchable.test_runners import launchable
@launchable.subset
def subset(client):
# read lines as test file names
for t in client.stdin():
client.test_path(t.rstrip("\n"))
client.separator = ","
client.run()
@click.argument('reports', required=True, nargs=-1)
@launchable.record.tests
def record_tests(client, reports):
for r in reports:
client.report(r)
def parse_func(p: str) -> Generator[CaseEventType, None, None]:
tree = ET.parse(p)
for use_case in tree.iter("UseCase"):
if len(use_case) == 0:
continue
use_case_name = use_case.attrib.get('name')
if use_case_name is None:
continue
for scenario in use_case.iter("Scenario"):
if len(scenario) == 0:
continue
scenario_name = scenario.attrib.get('name')
for testcase in scenario.iter('TestCase'):
testcase_name = testcase.attrib.get('name')
duration = testcase.attrib.get('time')
result = testcase.attrib.get('result')
status = 0
if result == 'error':
status = 1
test_path = [
{"type": "UseCase", "name": use_case_name},
{"type": "Scenario", "name": scenario_name},
{"type": "TestCase", "name": testcase_name},
]
yield CaseEvent.create(
test_path, duration, status, None, None, None, None)
client.parse_func = parse_func
client.run()
split_subset = launchable.CommonSplitSubsetImpls(__name__).split_subset()
解説
メソッドの意味や、渡ってくる引数などの細かい説明はここではしません。
基本的には @launchable.subset
, @launchable.record.tests
デコレータを使ってcustom pluginの機能を追加していきます。
launchableinc/cliはclickを利用してコマンドラインのオプションのパースをしています。
そのためclickを利用してcustom pluginにオプションを追加できます。
@launchable.subset
def subset(client):
...
@click.argument('reports', required=True, nargs=-1)
@launchable.record.tests
Subset
subsetでは e2e --list
で実行するテスト一覧が取できるので、それをlaunchableinc/cliコマンドに改行を除いて渡しています。
これがLaunchableに渡されPTSが実行されます。
e2e
は個別テストをカンマ区切りで渡す必要があるのでデフォルト改行(\n
)の区切りを ,
に変更しています。
Record tests
Launchableはテスト情報を type
, name
で表現し、階層情報を配列で表現します。
e2eでは Usecase > Scenario > TestCase
の階層なので出力されたXMLから階層情報を test_path
のフォーマットに直してLaunchableに渡しています。
test_path = [
{"type": "UseCase", "name": use_case_name},
{"type": "Scenario", "name": scenario_name},
{"type": "TestCase", "name": testcase_name},
]
SplitSubsetも launchable subset
と同じようにコマンドを定義する必要がありますがここでは省略しています。
さいごに
今日はcustom pluginの作り方を紹介しました。自分の使っているtest runnerがサポートされていない場合は作ることも検討してみてください。
明日はraw profileについて紹介します。
Discussion