書いたコードを守る工程に進みます。単体テストを書き、バグを直し、最後に設計書1枚から小さな機能を一気通貫で作り上げます。
Day2 が終わったときの到達状態を共有します。
クレジット残量とモデル設定を昨日同様に確認します。
短い休憩をはさみます。
テストとは何か、なぜ書くか、どう読むかを基礎から。
JUnit テスト生成と、バグ7パターンのデバッグ。
午後の総合演習に向けて休みます。
期限切れタスクの赤色一覧を一気通貫で実装します。
短い休憩をはさみます。
到達確認と配属後3か月の進め方を持ち帰ります。
Day1 では Copilot のインライン補完・Chat・スラッシュコマンドで Java のコードを書きました。Day2 は「書いたコードを守る」工程に進みます。手を動かすほど身につく内容なので、迷ったら止まらずまず動かしてください。
@Test、assertEquals、given-when-then)を読める/tests で JUnit テストのひな形を生成し、正常系・異常系・境界値を足せる演習は「考える→書く→実行→答え合わせ」の4段で進みます。答え合わせの参考プロンプトは配布フォルダの hints/ にあります。先に答えを見ず、自分で書いてから開いてください。すべて個人ワークで、発表やグループ作業はありません。気づいたことは memo.md に書きためてください。
Day1 の感覚を取り戻すところから始めます。新しい操作はありません。Copilot Chat が反応すること、補完が出ることを確認しておきます。
2026年6月から GitHub Copilot は AI Credits の従量制に移行しています。高性能モデルや重い使い方は残量を消費します。Day1 と同じ手順で、いまの残量を確認しておきます。
VSCode 右下のステータスバーにある Copilot アイコンをクリックします。
メニューから使用状況(Usage)を開くと、当月の利用量と残量の目安が表示されます。研修中は時々ここを意識します。
インライン補完は AI Credits を消費しません。残量を気にせず使ってよいのは補完です。消費が大きいのは Chat での高性能モデル利用や、後半で紹介する Agent モードです。
本研修では、モデルピッカーで講師指定のミドルクラスのモデルを選び、effort(推論の重さ)は低めの設定のまま使います。勝手に高性能モデルへ切り替えると、残量を早く消費し、挙動も研修の説明と変わります。迷ったときの選び方は次のとおりです。
モデル名や画面の表記は更新が速く、研修当日に本ガイドと表示が異なる場合があります。選び方の流れは変わりません。表示が違うときは講師に確認してください。
Copilot Chat に「今の変更を元に戻して」「さっきのコードに戻して」と頼めば戻せます。キーボードの Ctrl+Z(Mac は Cmd+Z)でも戻せます。失敗しても壊れません。気軽に試してください。
今日いちばん時間をかける土台がここです。テストコードを書いたことがない前提で、何のために書くのか、どう読むのかから始めます。読み方が分かれば、Copilot が生成したテストも自分で判断できるようになります。
配属後、最初に任されやすい仕事のひとつが「既存コードへのテスト追加」です。新機能をいきなり任されるより、テストを書きながらコードを理解する役割から入ることが多いためです。ここで読み方の基礎を作っておくと、配属直後に困りません。
単体テスト(ユニットテスト)は、メソッド1つ程度の小さな単位が「期待どおりに動くか」を、プログラムで自動的に確かめる仕組みです。画面を開いて手で動作確認する代わりに、コードがコードを検証します。一度書けば、後からコードを直したときも同じ確認を一瞬で繰り返せます。
これまで皆さんは、テストケースを表に書き出す程度の経験はあっても、テストコードそのものはほとんど書いていないはずです。今日はその表を、動くテストコードに変えていきます。
初めて見ると記号が多くて身構えますが、覚えるのは3つだけです。
このメソッドはテストだ、という宣言です。@Test が付いたメソッドが、実行時に1件ずつ自動で走ります。
第1引数が「こうなってほしい値」、第2引数が「実際にコードが返した値」です。一致すれば成功、違えば失敗として知らせます。AssertJ では assertThat(実際値).isEqualTo(期待値) と書きます。
given は前提を用意する、when は試したい処理を呼ぶ、then は結果を検証する。この順に書くと、何を確かめたいテストか読み手に伝わります。
テスト名は「メソッド名_条件_期待結果」の形にすると、失敗したときに何が起きたか一目で分かります。日本語で書いて構いません。VSCode のテストエクスプローラにも日本語で表示されます。
テストは1ケースごとに、前提の用意・処理の呼び出し・検証を書きます。正常系・異常系・境界値とそろえると、似たコードを何度も書くことになります。この繰り返しこそ Copilot が得意な部分です。/tests でひな形を生成し、足りないケースを Chat で追加していきます。
Day1 の Java 研修で触れた findAll や findById といったデータ取得メソッドは、Spring Data JPA が名前から動きを組み立てる仕組みでした。今日のテストでは、その本物のメソッドを呼ぶ代わりに偽物(モック)に差し替えて、サービス層のロジックだけを切り出して確かめます。
/tests などの出力は、コメントや説明が英語になりがちです。そのときはプロンプトの末尾に「日本語で説明してください」と添えれば日本語になります。生成後でも「テスト名とコメントを日本語にしてください」と頼めば直せます。多くの場合これで日本語になりますが、再度英語に戻ることもあるので、その都度添えます。
ここからは手を動かします。各演習は4段で進めてください。答え合わせの参考プロンプトは hints/ にあるので、自分で書いてから開きます。
作業フォルダは配布フォルダを VSCode で開いた状態です。予想や気づきは memo.md の該当見出しに書きます。新規ファイルはエクスプローラーを右クリックして「新しいファイル」から作ります。Copilot の出力は、内容を読んでから貼り付けて保存します。
対象ファイル id-task-app-starter/src/test/java/jp/idhd/taskapp/service/TaskServiceTest.java。使う機能は /tests と Copilot Chat。詳細手順は exercises/ex05-test.md にあります。
書きたいテストを4〜6個、memo.md に箇条書きします。正常系(存在するIDでタスクが返る)・異常系(存在しないIDで例外が出る)・境界値(たとえば create で status を指定しなかったときに既定値が入る)の3観点をそろえることを意識します。なお、期限切れ(findOverdue)まわりの境界値テストは演習7で扱います。
TaskService.java のクラス宣言にカーソルを置き、Copilot Chat で /tests を使ってひな形を生成します。提案を TaskServiceTest.java に貼り、Chat で境界値テストを追加します。生成された when().thenReturn() が何をしているかを Copilot Chat に日本語で説明させ、自分の言葉で言えるようにします。
./mvnw test を実行し、全件 PASS することを確認します。失敗したら、まずテストの想定が正しいかを読み直します。
hints/step05_test_hint.md を開き、参考プロンプトと自分の依頼文を見比べます。観点の抜けや import の違いを確認します。早く終わった方は ex05-test.md のチャレンジに進みます。
@ParameterizedTest の使い方を Copilot に尋ね、複数の入力を表形式でまとめる書き方を試してみてください。意図的に7種類のバグを仕込んだ id-task-app-bugged フォルダを、VSCode で開きます(同じウィンドウでも別ウィンドウでも構いません)。開いたら VSCode 左上のフォルダ名が id-task-app-bugged になっているかを確認します(starter と取り違えるとつまずきの原因になります)。各バグは // FIXME-NN: でマークしてあります。使う機能は /fix と Copilot Chat。詳細手順は exercises/ex06-debug.md にあります。
| # | 症状 | 箇所 | 学ぶ観点 |
|---|---|---|---|
| FIXME-01 | NullPointerException | TaskService.findById | Optional の扱い、スタックトレースの読み方 |
| FIXME-02 | SQLインジェクション | TaskLegacyDao.findByTitle | プリペアドステートメント、生成コードの危険性 |
| FIXME-03 | リソースリーク | TaskLegacyDao.findByTitle | try-with-resources、Connection 管理 |
| FIXME-04 | 例外握りつぶし | TaskService.delete | ログ出力・再スロー、catch の粒度 |
| FIXME-05 | 境界値バグ | TaskService.findOverdue | 境界値テストの重要性 |
| FIXME-06 | 無限ループ | TaskService.completeAll | デバッガの使い方、状況の伝え方 |
| FIXME-07 | ハードコード認証情報 | LegacyConfig・application.yml | 機密情報の扱い、ガイドラインとの接続 |
7つのうち、どれから取り組むかを3つ選んで memo.md に書きます。番号順でなくて構いません。テストで見つかるバグ(FIXME-01・05・06)と、テストでは見つからないバグ(FIXME-02・03・04・07)があることを意識します。
テストで見つかるバグは、./mvnw test の失敗スタックトレースを Copilot Chat に貼って原因を聞き、/fix で順に直します。見つからないバグは、ファイルを選択して「セキュリティとリソース管理の観点でレビューしてください」と依頼します。修正案は Apply する前に必ず読みます。
直すたびに ./mvnw test を実行し、PASS が増えることを確認します。スタックトレースは一番上が最後に起きた例外、Caused by: の下が本当の原因です。jp.idhd.taskapp を含む行から先に読みます。
hints/step06_debug_hint.md を開き、各バグの「直し方の型」と自分の修正を見比べます。テストで赤くならないバグを直したつもりで終えていないかを確認します。4つ以上直してテストが PASS すれば到達です。
2日間の集大成です。設計書1枚から「期限切れタスクを赤色で一覧表示する機能」を、Copilot を使って一気通貫で作ります。個人ワーク80分のあと、講師が解説とふりかえりを行います(発表ではありません)。
対象ファイルは TaskService.java / TaskController.java / templates/tasks/list.html / TaskServiceTest.java。使う機能はインライン補完・Copilot Chat・/tests。詳細手順は exercises/ex07-overdue.md にあります。
docs/設計書.md を開き、A4 1枚の仕様、特に受け入れ条件の表を読み込みます。どのファイルを何のために変えるかを memo.md に書き出します。進める順番は Service → Test → Controller → Template が安全です。
まず TaskService.findOverdue(LocalDate) を実装します。仕様の肝は「today より前の dueDate を返す、ただし today ちょうどは含めない」と「DONE(完了)のタスクは、期限が過ぎていても期限切れにしない」の2点です。findByDueDateBefore(today) で取得したあと、status が DONE のものを除外します。次に境界値(今日が期限を含む/含まないを明示)の JUnit テストを生成します。続けて Controller で期限切れ ID を Set<Long> にして渡し、最後に Thymeleaf の list.html で th:classappend を使って該当行に overdue クラスを付けます。CSS の .overdue は定義済みです。
./mvnw spring-boot:run で起動し、ブラウザで http://localhost:8080/tasks を開きます。期限が過去の行だけが赤背景になり、今日・未来・null・DONE(完了)の行は赤くならないことを確認します。テストも ./mvnw test で PASS させます。
hints/step07_overdue_hint.md を開き、参考プロンプトと境界値の扱いを見比べます。赤くならないときの切り分け(開発者ツールで class="overdue" の有無を見る)も確認します。
80分で完璧を目指す必要はありません。動くところまで持っていくのが優先です。「今日が期限のタスクを含めるか」を曖昧にしたまま書くと、テストと実装でズレます。先に1行で仕様を固定してから手を動かすと、Copilot への依頼もぶれません。終わらなかった部分は「次やるなら何をするか」を memo.md に残します。このあと講師が、実装の判断ポイントとつまずきやすい箇所を解説します。
2日間で身につけた使い方を、配属後にどう定着させるかの道筋です。まず今日の到達を確認し、そのうえで最初の3か月で踏むステップを示します。
@Test・assertEquals・given-when-then を読める/tests でひな形を生成し、正常系・異常系・境界値を足せる配属先の既存コードを /explain で読み解きます。いきなり書くより、Copilot に説明させながらコードベースの地図を作る時期です。機密情報を貼らない、出力は必ずレビューする、という社内ガイドラインの線引きを体に入れます。
既存コードへのテスト追加や小さなバグ修正を、/tests と /fix で進めます。今日の演習5・6 がそのまま実務の形です。提案は実装前に理解し、動作確認してから採用します。
関連ファイルを開いてから依頼する、要求を小さく刻む、入出力例を添えるといった「文脈の渡し方」で出力の質が変わることを実感します。チームのコーディング規約を .github/copilot-instructions.md にまとめる動きにも触れていきます。
あなたが主役で、Copilot は道具です。生成されたコードは、同僚のコードをレビューするのと同じ目で、機能・セキュリティ・可読性・保守性を見てから採用してください。
研修中によく出る質問をまとめました。手が止まったらここを先に見てください。
Q. テストは何件書けば「足りる」のですか。
件数より観点です。正常系・異常系・境界値の3つがそろっているかを基準にします。今日の演習では1メソッドあたり3観点を目安にしています。
Q. Copilot が生成したテストをそのまま信じてよいですか。
そのままは避けます。テストは「仕様の宣言」なので、期待値が本当に正しいかは人が判断します。生成されたテストが緩すぎて、バグがあっても PASS してしまうことがあります。
Q. /fix と Chat への質問は、どう使い分けますか。
コンパイルエラーや例外のように「壊れている箇所が明確」なときは /fix が速いです。SQLインジェクションのように「動くけれど危険」なコードは、/fix のきっかけがないので、Chat にレビューを依頼して気づかせます。
Q. 出力が英語で返ってきます。
プロンプト末尾に「日本語で説明してください」を足します。生成後でも「コメントとテスト名を日本語にしてください」で直せます。多くの場合これで日本語になりますが、再度英語に戻ることもあるので、その都度添えます。
Q. 総合演習が80分で終わりませんでした。
問題ありません。動くところまでを優先し、残りは「次やるなら何をするか」をメモに残します。配属後の自分への引き継ぎになります。
Q. モデルを高性能なものに変えたら速く解けますか。
研修中は講師指定のミドルクラス・低effort のまま使ってください。高性能モデルは AI Credits の消費が大きく、挙動も説明と変わります。配属後に必要に応じて選ぶ判断を、まず今の設定で身につけます。
よくあるつまずきと、その切り分け手順です。順番に試してください。
テストが赤いまま直らない。
まず assertThat の左右(実際値と期待値)が逆になっていないかを見ます。次にテストの想定そのものが正しいかを読み直します。それでも分からなければ、テストコードを Copilot Chat に貼り「このテストが失敗する理由を教えてください」と聞きます。
bugged 版が起動しない。
意図的なバグでビルドや起動が止まることがあります。./mvnw test の出力を上から読み、jp.idhd.taskapp を含む行を探します。それでも進まないときは ./mvnw clean test でキャッシュを更新してから試します。
ポート8080 が使われていると言われる。
別のサーバーが起動したままの可能性があります。前のサーバーを止めるか、application.yml の server.port を 8081 に変えて起動します。
Thymeleaf の変更が画面に反映されない。
ブラウザのキャッシュが残っていることがあります。Ctrl+Shift+R(Mac は Cmd+Shift+R)でキャッシュ無視リロードします。それでも変わらなければ、サーバーを止めて起動し直します。
期限切れの行が赤くならない。
開発者ツール(F12)で該当行に class="overdue" が付いているかを見ます。付いていなければ Controller 側で overdueIds に値が入っているか、付いているのに色が出なければ CSS 側を疑います。
Copilot の出力が英語のまま。
「日本語で説明してください」を依頼に足します。すでに貼り付けたコードのコメントを日本語化したいときは「このコードのコメントを日本語に書き換えてください」と頼みます。