プッシュしたあとCIの完了を待ちながら、なかなか進まない進行表示を見て、あごに手を当てて考えている開発者

テストが遅い・CIが長い原因をAIと切り分ける|待ち時間を減らす手順

プッシュして、CIが回り始める。 コーヒーを淹れて戻ってきても、まだ黄色いまま。レビューの指摘を1行直して、またプッシュして、また待つ。1日のうち、待っている時間がけっこうある——そんな感覚、ありませんか。

「テストが遅いのは分かってる。でも、どこが遅いのかは測ったことがない」。現場ではよくあることです。忙しい中で後回しになるのは自然なことですし、あなたの段取りが悪いわけではありません。ただ、ここはAIが手伝いやすい所でもあります。この記事では、遅さを数字にして、AIと一緒に原因の型へ当てはめ、効く所から1つずつ直す手順を整理します。

結論:CIが遅いとき、いきなり「速くして」とAIに頼むより、先にどこに時間がかかっているかを測るほうが近道です。手順は3つ。①CI全体の時間を段取り(準備・ビルド・テスト)ごとに分け、テストは遅い順の上位10件を出す。②その数字をAIに渡し、遅さの5つの型(遅い一部のテスト/重い準備と後始末/CIの段取り/直列実行/毎回全部回す)のどれに当たるかと、直したときの効き目の見込みを出させる。③効き目が大きく、壊しにくい所から1つずつ直し、直す前と後で時間を比べる。テストを消したりスキップしたりして速くするのではなく、守りは残したまま待ち時間を削る。これが無理のない進め方です。

遅さは、たいてい少数の場所に集まっています。 全部を少しずつ速くする必要はなく、大きく時間を食っている数か所を見つけられれば十分です。今日は、その数か所を一緒に探していきましょう。

まず測る:CIの時間を「準備・ビルド・テスト」に分ける

最初にやるのは、直すことではなく、時間の内訳を出すことです。ここを飛ばすと、AIも人も「たぶんここだろう」で手を入れて、思ったほど速くならない——ということが起きがちです。

CIの所要時間を表す1本の横長の帯が、準備・ビルド・テストの3区間に分かれ、いちばん長いテストの区間を虫眼鏡で調べている図
CIの時間を段取りごとに分けると、どこから手をつければいいかが見えてくる

CIのログには、たいていステップ(段取り)ごとの所要時間が出ています。まずはそれを3つに分けて書き出します。

たとえば、こんな内訳になったとします。

CI全体:20分
  準備(依存のインストール):6分
  ビルド:3分
  テスト:11分

これだけでも見え方が変わります。テストだけを見ていたら気づかなかった「準備に6分」が浮かび上がる。もしかすると、テストより先に準備を短くしたほうが早く効くかもしれません。

次に、テストの中身を遅い順に並べます。多くのテストフレームワークには、時間のかかったテストを一覧にする機能があります(たとえばPythonのpytestなら --durations=10 で遅い順の上位10件が出ます)。使っている道具での出し方が分からなければ、それ自体をAIに聞けば大丈夫です。

使っているテストフレームワークは(名前とバージョン)です。
テストを1件ずつの所要時間つきで実行し、遅い順に上位10件を表示する方法を教えてください。
CIのログにも同じ一覧を残したいので、CI設定に足す場合の書き方もお願いします。

上位10件を出してみると、ほんの数件が全体の大半を占めていることがよくあります。先の例で、テスト11分のうち上位10件で6分なら、テスト時間の半分強はその10件に集まっている計算です。数千件のテストを全部見直さなくていい。ここが分かるだけで、ずいぶん気が楽になります。

遅さの原因は、だいたい5つの型に収まる

数字が出たら、それを原因の型に当てはめていきます。CIやテストの遅さは、多くの場合この5つのどれか(またはその組み合わせ)です。

① 遅い一部のテスト sleep で固定時間待っている、本物の外部APIやネットワークに毎回つないでいる、大量のデータを毎回作っている。上位10件に同じ傾向のテストが並んでいたら、まずここです。

② 重い準備と後始末 テストのたびにDBを作り直す、毎回大きな初期データを流し込む、アプリ全体を起動し直す。1件ごとは数秒でも、件数を掛けると大きくなります。テスト本体より「前後」が重いパターンです。

③ CIの段取り 依存ライブラリを毎回ゼロからインストールしている、ビルド結果を使い回していない、大きなコンテナイメージを毎回取得している。「準備」の区間が長いなら、ここを疑います。 キャッシュ(前回の結果を保存して使い回す仕組み)が効いていないことが多いです。

④ 直列で回している テストを1本ずつ順番に流している。マシンには余力があるのに使い切っていない状態です。並列化で短くなる余地がありますが、後で触れるとおり並列化には注意点があります。

⑤ 毎回全部回している README を1行直しただけでも、全テストとE2Eまで毎回走る。変更と関係のない重いテストまで、毎回待っている状態です。

覚えるというより、測った数字を見ながら上から当てていくチェックリストとして使ってください。この当てはめを、次の手順でAIに手伝ってもらいます。

手順①:数字をAIに渡し、型と効き目の見込みを出させる

ここはAIの得意な所です。測った内訳と遅いテストの一覧を渡し、どの型に当たりそうか、直したらどのくらい効きそうかを整理してもらいます。

渡すと話が早いのは、次の4つです。

聞き方の例:

CIの所要時間を短くしたいです。まだコードは直さないでください。
下の計測結果をもとに、時間がかかっている原因を次の5つの型に分類してください。

① 遅い一部のテスト(sleep・外部通信・大量データ)
② 重い準備と後始末(毎回のDB作り直し・初期データ投入)
③ CIの段取り(依存インストール・ビルドの使い回し・キャッシュ)
④ 直列で回している
⑤ 変更に関係ないテストまで毎回回している

それぞれについて、
- そう判断した理由(計測結果のどこから読み取ったか)
- 直し方の候補
- 直したときに短くなりそうな時間の見込みと、その根拠
- 直すことで壊れやすくなる所(テストの信頼性への影響)
を挙げ、「効き目が大きく、壊しにくい順」に並べてください。
数字はこちらが渡した計測結果だけを根拠にし、推測の部分は推測と書いてください。

--- CI全体の内訳 ---
(貼る)
--- 遅いテスト上位10件 ---
(貼る)
--- 上位のテストコード ---
(貼る)
--- CI設定(秘密情報は伏せ済み) ---
(貼る)

ポイントは2つあります。 1つ目は、「直して」ではなく「分類して、順番をつけて」と頼むこと。いきなり修正を頼むと、AIは計測を見ないまま一般論の高速化(とりあえず全部並列にする、など)を返しがちです。 2つ目は、見込みの根拠を言わせること。「30%速くなります」のような数字が出てきても、それは見積もりです。どこから読み取った数字なのかを書いてもらえば、こちらで確かめる手がかりになります。AIの出す数字の扱いはAIにパフォーマンス改善の候補を出させる|推測で直さない手順の考え方とも同じです。

手順②:効き目が大きく、壊しにくい所から1つずつ直す

AIの整理が出たら、上から1つずつ直していきます。ここで大事なのは、一度に1つだけ直して、前後で時間を比べること。まとめて直すと、どれが効いたのか、どれが何かを壊したのかが分からなくなります。

型ごとの、比較的安全な直し方の向きは次のとおりです。

そして直すたびに、最初に測った数字と比べます。

直す前:CI全体 20分(準備 6分 / ビルド 3分 / テスト 11分)
キャッシュ導入後:CI全体 _分(準備 _分 / ビルド _分 / テスト _分)

キャッシュは2回目以降の実行で効いてくるものなので、1回だけでなく数回分を見て判断するのがおすすめです。CIの時間はその日の混み具合でもぶれるので、1回の結果で一喜一憂しないくらいがちょうどいいです。

ありがちな落とし穴と、その回避

遅さをAIと一緒に削るとき、つまずきやすい所を先に置いておきます。

落とし穴の多くは、「早く速くしたい」気持ちから、測る・比べるを飛ばす所で生まれます。 測る一手を挟むだけで、遠回りに見えて、いちばん早く待ち時間が減ります。

明日からやること(小さく始める3つ)

全部を一度にやらなくて大丈夫です。まずはこの3つから。

  1. CIのログから、準備・ビルド・テストの時間を書き出す:5分で終わります。それだけで「どこが重いか」の見当がつきます。
  2. 遅いテストの上位10件を出してみる:出し方が分からなければAIに聞けば大丈夫です。数件に偏っていないかを見ます。
  3. その2つをAIに渡し、5つの型への分類と「効き目が大きく、壊しにくい順」を出してもらう:いちばん上の1つだけ、まず試してみます。

この3つで、「なんとなく遅い」が「ここが何分かかっている」に変わります。そこまで来れば、もう半分は解けたようなものです。

コピーして使う「CIの遅さ切り分けシート」

CIが遅いと感じたら、上から順に埋めてください。分かる所からで十分です。

# CIの遅さ 切り分けシート

## 1. 測る
- [ ] CI全体:_分
- [ ] 準備(依存インストール・コンテナ起動):_分
- [ ] ビルド:_分
- [ ] テスト:_分
- [ ] 遅いテスト上位10件を出した(合計_分 / テスト全体の_%)

## 2. 型に当てはめる(AIと一緒に)
- [ ] ① 遅い一部のテスト(sleep・外部通信・大量データ)
- [ ] ② 重い準備と後始末(毎回のDB作り直し・初期データ)
- [ ] ③ CIの段取り(キャッシュ・ビルドの使い回し)
- [ ] ④ 直列で回している
- [ ] ⑤ 変更に関係ないテストまで毎回回している

## 3. 1つずつ直す
- [ ] 効き目が大きく、壊しにくい順に並べた
- [ ] 一度に直すのは1つだけにした
- [ ] テストを消す・スキップする以外の手を先に考えた
- [ ] CI設定をAIに渡すとき、秘密情報を伏せた

## 4. 比べる
- [ ] 直す前と後の時間を、数回分で比べた
- [ ] 並列化した場合、たまに落ちるテストが増えていないか確かめた
- [ ] 報告には、見込みではなく実測の前後を書いた

最後に

CIを待つ時間は、1回ずつなら数分です。 でも、それが1日に何度も、チーム全員に積み重なっている。そこに気づいて「少しでも短くしたい」と思えるのは、自分の時間だけでなく、チームの時間も大事にしているからです。それは、ちゃんと価値のある仕事です。

CIの待ち時間が短くなり、すぐに結果が返ってきて、同僚と穏やかに次の作業の話をしている開発者

一度に何十分も削らなくて大丈夫です。今日は、CIのログから3つの時間を書き出すだけ。数字が見えれば、AIは頼もしい相談相手になってくれます。測るのはあなた、型に当てはめて順番を考えるのはAIと一緒に。その分担で、待ち時間は少しずつ、確実に短くなっていきます。

よければ、こちらも

関連用語