様々な環境へコマンドラインツールを提供する上での苦労とその対策YAPC::Kyoto 20232023.03.19Presented by Ryosuke Yabuki a.k.a Konboi
View Slide
自己紹介▶ 矢吹 遼介 (Ryosuke Yabuki)▶ Senior Software Engineer (Launchable, Inc.)▶ 福島県在住▶ SNS▶ ブログ: https://blog.konboi.com▶ Github: Konboi▶ Twitter: Konboi 22
今日話す内容▶ Launchableについて▶ launchableinc/cli (launchable command)▶ 苦労とその対策▶ まとめ▶ 今後33
Launchableについて4
Launchableについて▶ テスト結果および傾向の可視化/分析▶ Test Suite Insights▶ テスト実行の効率化▶ Predictive Test Selection (a.k.a PTS)▶ ※ここでの”テスト”はUnitTestやE2E Testなどの自動テストを指します55
Launchableについて▶ テスト結果&傾向の可視化/分析 / Test Suite Insights66
Launchableについて▶ テスト実行の効率化 / Predictive Test Selection (a.k.a PTS)77
Launchableについて▶ ユーザーはサービスを利用するために88
Launchableについて▶ ユーザーはサービスを利用するために▶ テスト結果のレポート▶ Test Suite Insight, PTS99
Launchableについて▶ ユーザーはサービスを利用するために▶ テスト結果のレポート▶ Test Suite Insight, PTS▶ テスト対象を送る/テストすべきリストを受け取る▶ PTS101046 test files36 test files
Launchableについて▶ ユーザーはサービスを利用するために▶ テスト結果のレポート▶ Test Suite Insight, PTS▶ テスト対象を送る/テストすべきリストを受け取る▶ PTS▶ Launchable側はマッピングする必要がある1111
launchableinc/cli12
launchableinc/cli▶ Python製▶ $ pip install launchable▶ 17のテストランナー(TR)/テストフレームワーク(TF)をサポート▶ Linux/Windows/Mac▶ Python 3.5 ~3.10 をサポート▶ テスト結果を送る / テスト対象をやりとりする▶ CI環境で利用されることを想定1313
launchableinc/cli▶ テスト結果のレポート / launchable record tests1414
launchableinc/cli▶ テスト対象の選定 / launchable subset151546 test files36 test files
launchableコマンドの苦労とその対策16
苦労17
苦労: 複数TR/TFのサポート18
複数TR/TFのサポート▶ TR/TFによって▶ レポートの出力内容 /フォーマットが異なる▶ 実行可能な単位が異なる▶ test case, class, file, etc▶ テスト対象を取得できるもの /できないものがある▶ 結果: 17のテストランナー(TR)/テストフレームワーク(TF)をサポート1919
複数TR/TFのサポート▶ Perlの場合▶ Test Anything Protocol (TAP)▶ テスト実行時間はSpecには含まれず▶ 実行時間はテストの分析やテストを効率よく実行する上では欠かせないデータ▶ TAP::Formatter::JUnitのレポートに実行時間は含まれないがTAP::Harness::JUnitのレポートには含まれる2020
複数TR/TFのサポート▶ TAP::Harness::JUnit のデフォルトのレポートフォーマット▶ t/00_compile.t → t_00_compile_t▶ t/00/compile.t, t_00/compile.t▶ “t/00_compile.t” で受け取りたい▶ prove▶ ファイル名/ディレクトリ単位で個別実行が可能だがテスト対象を返す機能はない▶ launchable command が指定されたディレクトリからテストファイルを取得 2121
複数TR/TFのサポート▶ Goの場合▶ 標準のコマンドでテスト一覧が取得可能▶ go test -list="Test|Example" ./…▶ 標準でのテストレポートは▶ カバレッジレポートは標準でサポート▶ Launchableでは jstemmer/go-junit-report を利用2222
複数TR/TFのサポート▶ Goの場合▶ -run optionに対応したフォーマットでテスト対象を出力する必要が▶ go test -run “^TestExampl1$|^TestExample2$|^ExampleGreeting$”2323
(再掲)複数TR/TFのサポート▶ TR/TFによって▶ レポートの出力内容 /フォーマットが異なる▶ 実行可能な単位が異なる▶ test case, class, file, etc▶ テスト対象を取得できるもの /できないものがある▶ 結果: 17のテストランナー(TR)/テストフレームワーク(TF)をサポート2424
複数TR/TFのサポート▶ 利用者の多いTR/TFはLaunchableが公式でサポート▶ 全てのTR/TFをサポートするは難しい▶ TR/TFの中には使用している Pluginによってレポートのフォーマットが変わるものも▶ 他にも2525
社内TR/TF26
複数TR/TFのサポート▶ 社内TR/TF▶ スクラッチ▶ OSSをforkして独自に機能を追加している▶ etc▶ 仕様を聞いてサポートすることもあるが...▶ 社内TR/TFサポート用のコードをメインストリームに入れるのは難しい2727
苦労: 複数環境のサポート28
(再掲)launchableinc/cli▶ Python製▶ $ pip install launchable▶ 17のテストランナー(TR)/テストフレームワーク(TF)をサポート▶ Linux/Windows/Mac▶ Python 3.5 ~3.10 をサポート▶ テストの結果を送る / テスト対象をやりとりする▶ CI環境で多く利用されることを想定2929
複数環境のサポート▶ OS▶ Linux/Window/Mac▶ e.g) pathの扱い▶ Linux/Mac: foo/bar/hoge.txt▶ Windows: foo\bar\hoge.txt3030
Cygwin対応▶ 稀にCygwin(ローカルの開発)環境で動かない問い合わせ▶ 担当チケットをCTOにアサインするとシュッと解決▶3131
複数環境のサポート▶ Python3.5~3.10▶ EOL▶ Python 3.5: 2020/09/13▶ Python 3.6: 2021/12/23▶ Python 3.7: 2023/06/27▶ なぜ古いバージョンを切らないのか?3232
複数環境のサポート▶ 開発者向けツールの宿命▶ e.g)▶ 我々のユーザーのユーザーが 3.5をサポートして欲しい▶ 我々のユーザーはユーザーのために 3.5をサポート▶ 我々はユーザーのために 3.5をサポート▶ CTO曰く▶ 我々はマラソンで一番後ろを走る人の伴走者 3333
複数環境のサポート▶ OS × Python バージョンの組み合わせでサポートが必要▶ 古いバージョンをサポートするために新しい機能を使えないことも ...▶ 更にCI環境による違いも▶ GitHub Actions, CircleCI, GitLab CI/CD, Jenkins▶ ビルド番号やビルドURLを取得するための環境変数の違いなど3434
閑話休題: なぜPythonなのか35
なぜPythonなのか▶ 最初に担当したエンジニアが最も得意だったのがPython▶ Perlも選択肢にあったが Windows対応を考えるとPythonに軍配▶ Go/Rustならよかったのか?▶ 配布方法/アップデートの仕組みを考える必要がある▶ plugin 機構をどう提供するのか悩ましい3636
苦労: エラーハンドリング37
エラーハンドリング▶ CIに組み込む都合上サービス側(Launchable)の都合で止めてはいけない▶ テストはPASSしているのにLaunchableへのリクエストがエラーで FAILに...はNG▶ Launchableがシステム障害で落ちていても動作させる必要があります▶ エラーにすべきものもある▶ 設定ミス▶ 不正なパラメーターの組み合わせ▶ etc 3838
苦労▶ 複数TR/TFのサポート▶ 複数環境へのサポート▶ エラーハンドリング3939
対策40
対策▶ plugin 機構▶ raw profile▶ テスト & ドッグフーディング▶ エラーメッセージ4141
plugin 機構▶ plugin機構をサポート▶ plugin ファイル (Pythonファイル)を任意のディレクトリに設置▶ 実行時にディレクトリを指定▶ launchable –plugin plugin-dr/▶ 社内TR/TFなどに対応▶ plugin作成方法のドキュメントは不十分▶ Launchable Advent Calendar 23日目 - custom plugin4242
raw profile▶ 個別にpluginを提供するのはコストが高い▶ 入出力フォーマットを定義しユーザー側で対応してもらう▶ サポートコストは減る▶ 複雑なフォーマットではないがユーザー側の対応コストが増える▶ plugin 機構/ raw profile よりも良いアイディアがあれば採用したい4343
テスト & ドッグフーディング▶ 実装中に気を付ける には限界がある▶ Matrix test▶ Windows/Linux▶ Python version 3.5 ~ 3.10▶ E2Eテスト▶ launchable コマンドのリリース前に複数の主要プロファイルでベースシナリオを実行▶ 定期実行を行いAPI側が互換性を崩してないかもチェック4444
テスト & ドッグフーディング▶ Launchableの開発環境では最新版(main branch)を使用▶ API側の開発ブランチがmainにマージされる度に開発環境へE2Eを実施▶ launchable commandの大きい機能をリリースする際はマージ後開発環境で数日様子をみてからリリースすることも▶ ミスを100%防ぐことは不可能なので早く気付ける仕組みを厚くしている4545
エラーメッセージ▶ エラーメッセージを分かりやすく▶ なぜエラーになっているのか▶ どうやったら解決するのか▶ ユーザー側で解決できるのが理想▶ 地味。だが効果大4646
まとめ▶ 様々な環境へ提供する上での苦労について紹介▶ TR/TFの差、OSの差、エラーハンドリング▶ 残念ながら解決方法に銀の弾丸は無い▶ 問い合わせや起こしてしまったエラーに対して一つ一つ対策していく▶ 抽象度のレベルをあげて解決できるように気をつけている4747
今後▶ 中期的▶ EOLバージョンのサポートコストと plugin機構の提供方法を踏まえて脱 Python▶ 長期的(野望)▶ テストレポートフォーマットの標準化▶ 各テストランナーへの機能提案4848
Thank you!49
Questions50
51We’re hiring
Thank you!52