Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
差分ベースで効率的にテストを実行してみる
Search
Shia
October 21, 2022
Technology
1
650
差分ベースで効率的にテストを実行してみる
Kaigi on Rails 2022
https://kaigionrails.org/2022/talks/riseshia/
Shia
October 21, 2022
Tweet
Share
More Decks by Shia
See All by Shia
スパイクアクセス対策としての pitchfork 導入
riseshia
0
240
NewEngineering 2024 - 繋がっていくサービスを支える開発環境作り
riseshia
0
710
Hotspot on Coverage
riseshia
0
160
Cookpad internship 2020 summer - web
riseshia
0
7.5k
マイクロサービス化を支える継続的切り替え術
riseshia
0
470
Cleaning up a huge ruby application
riseshia
3
11k
Find out potential dead codes from diff
riseshia
0
6.9k
Other Decks in Technology
See All in Technology
20241220_S3 tablesの使い方を検証してみた
handy
4
660
型情報を用いたLintでコード品質を向上させる
sansantech
PRO
2
120
株式会社ログラス − エンジニア向け会社説明資料 / Loglass Comapany Deck for Engineer
loglass2019
3
32k
Qiita埋め込み用スライド
naoki_0531
0
5.2k
プロダクト開発を加速させるためのQA文化の築き方 / How to build QA culture to accelerate product development
mii3king
1
280
組織に自動テストを書く文化を根付かせる戦略(2024冬版) / Building Automated Test Culture 2024 Winter Edition
twada
PRO
18
5.2k
NW-JAWS #14 re:Invent 2024(予選落ち含)で 発表された推しアップデートについて
nagisa53
0
270
マイクロサービスにおける容易なトランザクション管理に向けて
scalar
0
170
AWS re:Invent 2024で発表された コードを書く開発者向け機能について
maruto
0
210
LINEスキマニにおけるフロントエンド開発
lycorptech_jp
PRO
0
340
10個のフィルタをAXI4-Streamでつなげてみた
marsee101
0
180
React Routerで実現する型安全なSPAルーティング
sansantech
PRO
2
210
Featured
See All Featured
How GitHub (no longer) Works
holman
311
140k
How to Think Like a Performance Engineer
csswizardry
22
1.2k
A Modern Web Designer's Workflow
chriscoyier
693
190k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Fireside Chat
paigeccino
34
3.1k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
BBQ
matthewcrist
85
9.4k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Transcript
STORES 株式会社 @shia 差分ベースで 効率的にテストを実行してみる
SIM SANGYONG (@shia) - STORES株式会社 CTO室 - GitHub: @riseshia -
Twitter: @riseshia 自己紹介
本題に入る前に - 対象者 関わっているプロジェクトが - テスト数が多く、全体を実行するのに時間がかかる - CI のテストの実行時間が長く開発体験に悪影響を与えてる -
主要な仕様の変更にテストの変更を伴う必要があるくらいにはテスト が充実してる
本題に入る前に - 話すこと - 変更の影響を受けるテストのみを選択して実行する手法の紹介 - テストセレクションの実験とその結果の紹介 - 考えられる利用ケースの考察
モチベーション - 長生きしているサービスのテストは多い・遅い - 仕様の複雑度とテストの数・実行時間は比例する - テストが遅いと実行完了待ちで集中力が分散しがち - サービスがでかくなっても開発の速度を維持したい -
なんだったら高速にしたい => テスト実行時間を短くしたい
テスト実行時間を短くするのは難しい 難しい -> 費用対効果の観点で割に合わない - テスト実行を早くする - 不要なテストを消す - 並列で実行する
<- よく使われる - 本当に必要なテストだけを実行する <- 今回の話
order_spec.rb - テストとテスト実行に使用されるロジックの依存を計算 (事前処理) - 差分からの実行すべきテストを算出する (毎テスト実行) 本当に必要なテストだけを実行する Commit A
Commit B book.rb order.rb book_spec.rb order_spec.rb テストとテスト実行に使用される ロジックの依存情報 order.rb +++--- テスト選択機 book.rb order.rb book_spec.rb order_spec.rb
テストが依存しているロジックをどういう解像度で表すか - method based - 1 test associated to n
methods - 粒度が小さい代わりにテスト選択が複雑 - コアロジックに絡む場合の効率がいい - file based <- 今回の話 - 1 test file to n source files - 粒度が大きい代わりにテスト選択が簡単 - コアロジックに絡む場合の効率が悪い 依存情報の解像度
手法候補 - 静的分析ベース - Ruby だとヒューリスティックがたくさんになりメンテコストが現実味 がない。 Ruby 3.0 で入った型に期待。
- 動的分析ベース <- 今回の話 - 速度面で不安があるけどとにかく楽 - 機械学習ベース - モデルの精度を実用段階まであげるところから始めないといけないので 検証の道のりが長い
動的分析をする 実は事例がある - https://shopify.engineering/spark-joy-by-running-fewer-te sts - メソッドコールを記録して依存グラフを作ってそれと変更差分をみてテ ストを選択したら効率良くなりました - いくつか不明な点があった
- 依存情報の解像度がわからなかった - Shopify よりは小さいが並列テストが必要なくらいには大きいシステム では有効か?
- rotoscope - Shopify で使ってるらしい。採択 - calleree - ko1 さんが作ったもの
- 呼び出し先のローケーションが取れて嬉しい - 実験時点では今回のテスト環境である Ruby 2.7 ではバグがあったため 未採択 - coverage - 実行したコードを記録するためのライブラリ - erb などのテンプレートのロギングができない - 実験終わってから気づいてしまったので未採択(速度計測はあり) 依存情報ロギングに使えるツール
実験 - 知りたいこと - 事前に計算しておくコストの重さ - 10倍遅くなるとかなら話にならない - 実際どれくらいテストを絞れますか -
絞れたとして選択した数が平均で全体数の 80% ならあまり嬉しくない - 絞れないケースが多くても微妙 - 正しいテストが選ばれてますか - 選ばれるべきだが選ばれてないと困る - 正しいか人の確認が必要
- 普通の Rails アプリケーション - テストの数は 10k+ で全体実行だと手元(MBP 14' 2021)で
2hr+ - file based 依存情報を利用 実験 - 対象プロジェクト
- 1. 計算した依存情報から PR ごとに選択されたテストの数 - 障害を起こしていない連続している PR 30件 -
base branch … pr branch の差分を利用 - 2. 依存情報を作るのにかかる時間測定 - 有効にしている時とそうじゃない時の比較 - 3. 選択されるべきテストの選択漏れはないか 実験用で作った gem: https://github.com/riseshia/affected_tests 最小 poc: https://github.com/riseshia/test-filtering-poc 実験 - 計測対象
実験 - 実験結果1(テスト選択効率) - 全件実行されるものが 50% - 5%以下を選択するものが 40% -
40%以上を選択するものが 10%
実験 - 実験結果1(テスト選択効率) - 全件実行になったもの - テストなしのワンショット用コード / アセット /
設定の変更 - bundle update PR(ボットからの定期実行) - 40% 以上選択したもの - ビジネスロジックのコアにあるものが変更されている Shopify で出している結果とあまり変わらない。つまりこのサイズでも アプローチそのものは有効っと考えられる
全体テストの一部だけを数回実行して平均をだし比較 - ロギングなし -> 8min - rotoscope -> 10.5min (31%増加)
- coverage -> 8.5min (6%増加) 実験 - 実験結果2(依存情報ロギングによる速度低下)
知りたいこと、わかった? - 事前に計算しておくコストの重さ - 実行速度面では大丈夫そう - インフラコスト面では 1 依存情報生成に対して 2-3回実行テスト数を絞
れたらが取れそう - 実際どれくらいテストを絞れますか - 開発体験という意味だともう少し効率あげたいかも - 正しいテストが選ばれてますか - 少なくとも実験上で選ばれた差分では問題のある事例は見つからず - 動的分析でも安全!という保証はできない
動的分析の感想 - 実用上呼び出し元側のローケーションだけを収集してもほぼ問題ない - ほとんどの最終的な辿り着き先は別の gem/標準 lib メソッド - rotoscope
はデフォルトでは呼び出したメソッドは教えてくれが、その ローケーション情報を提供しない - 検知できないものは確かにあるが、実用上でクリティカルとは思えない - e.g. モジュール内部の定数参照 - e.g. ActiveRecord モデルの属性参照 - 頑張れば全体選択の頻度は下げられそう - アセットへの参照...
2. 全件実行する 最新のコミットへの依存情報を計算してる間はどうするか決める必要があ る 利用体験への感想 Commit A Commit B Commit
C 依存情報持ち 計算中... 1. Commit A との差分で テストを選択するしかない
利用体験への感想 - テスト環境セットアップにかかる速度の重要性があがる - e.g. セットアップに3分かけてテストが 10秒で終わってしまうと結局体 感として遅いまま - CI
が並列数を実行中に変更可能じゃなければテスト数によって並列 数を変更できないのでやや非効率 - e.g. 選択したテストファイル数がノード数より少ないとなんもしない ノードが発生する
1. ベースブランチの CI/CD および PR 上のテストで運用する - デプロイまでの時間は短縮できる - テストセレクションが間違っていると障害に繋がる可能性が上がるの
でリスクマネージメントが大事になる 使い道への考察
使い道への考察 2. PR のテスト実行時にだけ運用する - 開発中の間のテストの実行時間が短くなる - マージからデプロイまでの時間が短縮される可能性あり - ベースブランチでは全テストが動くのでデプロイのリスクは使わない
場合と同じ
使い道への考察 3. 手元で PR を提出する前に利用する - 変更の影響範囲を調べるために使える - 選択されたテスト数が少ない -
PR で意図してないところへの影響によるテスト失敗が見つかったが CI 待ちで開発速度が落ちるのはよくあるケース - 手元で完結できて便利 - 選択されるテスト数が多い - CI 上の並列実行に任せる - プロジェクトによって手軽に実行できるテスト数は違うので価値があ るかは試してみるしかない
- 差分によるテスト選択手法の紹介 - 実際使うとしたらどういう使い方ができるのか ありがとうございました 終わり