DAY 2

ハンズオンガイド Day2
テスト・デバッグ・実践演習

書いたコードを守る工程に進みます。単体テストを書き、バグを直し、最後に設計書1枚から小さな機能を一気通貫で作り上げます。

2026年7月16日(木)
9:00 - 17:00
VSCode・GitHub Copilot
タイムテーブル
S1

Session 01 : 本日のゴール[10min]

Day2 が終わったときの到達状態を共有します。

S2

Session 02 : ウォームアップ[20min]

クレジット残量とモデル設定を昨日同様に確認します。

休憩

休憩[10min]

短い休憩をはさみます。

S3

Session 03 : 単体テストをゼロから[50min]

テストとは何か、なぜ書くか、どう読むかを基礎から。

S4

Session 04 : 演習(EX5・EX6)[120min]

JUnit テスト生成と、バグ7パターンのデバッグ。

休憩

昼休憩[60min]

午後の総合演習に向けて休みます。

S5

Session 05 : 総合演習(EX7)[120min]

期限切れタスクの赤色一覧を一気通貫で実装します。

休憩

休憩[10min]

短い休憩をはさみます。

S6

Session 06 : 到達チェック・ロードマップ[80min]

到達確認と配属後3か月の進め方を持ち帰ります。

SESSION 01

本日のゴール

Day1 では Copilot のインライン補完・Chat・スラッシュコマンドで Java のコードを書きました。Day2 は「書いたコードを守る」工程に進みます。手を動かすほど身につく内容なので、迷ったら止まらずまず動かしてください。

01 本日が終わったときの状態

この資料の使い方

演習は「考える→書く→実行→答え合わせ」の4段で進みます。答え合わせの参考プロンプトは配布フォルダの hints/ にあります。先に答えを見ず、自分で書いてから開いてください。すべて個人ワークで、発表やグループ作業はありません。気づいたことは memo.md に書きためてください。

SOURCES
SESSION 02

ウォームアップ

Day1 の感覚を取り戻すところから始めます。新しい操作はありません。Copilot Chat が反応すること、補完が出ることを確認しておきます。

01 クレジット残量を確認する

2026年6月から GitHub Copilot は AI Credits の従量制に移行しています。高性能モデルや重い使い方は残量を消費します。Day1 と同じ手順で、いまの残量を確認しておきます。

01
Copilot アイコンを開く

VSCode 右下のステータスバーにある Copilot アイコンをクリックします。

02
使用状況を見る

メニューから使用状況(Usage)を開くと、当月の利用量と残量の目安が表示されます。研修中は時々ここを意識します。

残量を気にせず使えるもの

インライン補完は AI Credits を消費しません。残量を気にせず使ってよいのは補完です。消費が大きいのは Chat での高性能モデル利用や、後半で紹介する Agent モードです。

02 モデル設定の再確認

本研修では、モデルピッカーで講師指定のミドルクラスのモデルを選び、effort(推論の重さ)は低めの設定のまま使います。勝手に高性能モデルへ切り替えると、残量を早く消費し、挙動も研修の説明と変わります。迷ったときの選び方は次のとおりです。

ご留意ください

モデル名や画面の表記は更新が速く、研修当日に本ガイドと表示が異なる場合があります。選び方の流れは変わりません。表示が違うときは講師に確認してください。

うまくいかない・元に戻したいとき

Copilot Chat に「今の変更を元に戻して」「さっきのコードに戻して」と頼めば戻せます。キーボードの Ctrl+Z(Mac は Cmd+Z)でも戻せます。失敗しても壊れません。気軽に試してください。

SOURCES
SESSION 03

単体テストをゼロから

今日いちばん時間をかける土台がここです。テストコードを書いたことがない前提で、何のために書くのか、どう読むのかから始めます。読み方が分かれば、Copilot が生成したテストも自分で判断できるようになります。

なぜここを丁寧にやるのか

配属後、最初に任されやすい仕事のひとつが「既存コードへのテスト追加」です。新機能をいきなり任されるより、テストを書きながらコードを理解する役割から入ることが多いためです。ここで読み方の基礎を作っておくと、配属直後に困りません。

01 単体テストとは何か

単体テスト(ユニットテスト)は、メソッド1つ程度の小さな単位が「期待どおりに動くか」を、プログラムで自動的に確かめる仕組みです。画面を開いて手で動作確認する代わりに、コードがコードを検証します。一度書けば、後からコードを直したときも同じ確認を一瞬で繰り返せます。

これまで皆さんは、テストケースを表に書き出す程度の経験はあっても、テストコードそのものはほとんど書いていないはずです。今日はその表を、動くテストコードに変えていきます。

02 なぜ書くのか

03 テストコードの読み方

初めて見ると記号が多くて身構えますが、覚えるのは3つだけです。

@Test

テストメソッドの目印

このメソッドはテストだ、という宣言です。@Test が付いたメソッドが、実行時に1件ずつ自動で走ります。

assertEquals(期待値, 実際値)

期待と実際を突き合わせる

第1引数が「こうなってほしい値」、第2引数が「実際にコードが返した値」です。一致すれば成功、違えば失敗として知らせます。AssertJ では assertThat(実際値).isEqualTo(期待値) と書きます。

given-when-then

テストの3段構え

given は前提を用意する、when は試したい処理を呼ぶ、then は結果を検証する。この順に書くと、何を確かめたいテストか読み手に伝わります。

// given-when-then の最小例(JUnit 5 + AssertJ) @Test void findById_存在するID_タスクが返る() { // given : 前提を用意する when(taskRepository.findById(1L)).thenReturn(Optional.of(sample)); // when : 試したい処理を呼ぶ Task result = taskService.findById(1L); // then : 結果を検証する assertThat(result.getTitle()).isEqualTo("設計書を読む"); }
テスト名の付け方

テスト名は「メソッド名_条件_期待結果」の形にすると、失敗したときに何が起きたか一目で分かります。日本語で書いて構いません。VSCode のテストエクスプローラにも日本語で表示されます。

04 手で書くと面倒、だから Copilot で

テストは1ケースごとに、前提の用意・処理の呼び出し・検証を書きます。正常系・異常系・境界値とそろえると、似たコードを何度も書くことになります。この繰り返しこそ Copilot が得意な部分です。/tests でひな形を生成し、足りないケースを Chat で追加していきます。

Day1 の Java 研修で触れた findAllfindById といったデータ取得メソッドは、Spring Data JPA が名前から動きを組み立てる仕組みでした。今日のテストでは、その本物のメソッドを呼ぶ代わりに偽物(モック)に差し替えて、サービス層のロジックだけを切り出して確かめます。

出力が英語になったとき

/tests などの出力は、コメントや説明が英語になりがちです。そのときはプロンプトの末尾に「日本語で説明してください」と添えれば日本語になります。生成後でも「テスト名とコメントを日本語にしてください」と頼めば直せます。多くの場合これで日本語になりますが、再度英語に戻ることもあるので、その都度添えます。

SOURCES
SESSION 04

演習

ここからは手を動かします。各演習は4段で進めてください。答え合わせの参考プロンプトは hints/ にあるので、自分で書いてから開きます。

ハンズオン共通ルール

作業フォルダは配布フォルダを VSCode で開いた状態です。予想や気づきは memo.md の該当見出しに書きます。新規ファイルはエクスプローラーを右クリックして「新しいファイル」から作ります。Copilot の出力は、内容を読んでから貼り付けて保存します。

HANDS-ON演習5 : JUnit テストを Copilot で生成する [30min]

対象ファイル id-task-app-starter/src/test/java/jp/idhd/taskapp/service/TaskServiceTest.java。使う機能は /tests と Copilot Chat。詳細手順は exercises/ex05-test.md にあります。

1
考える

書きたいテストを4〜6個、memo.md に箇条書きします。正常系(存在するIDでタスクが返る)・異常系(存在しないIDで例外が出る)・境界値(たとえば create で status を指定しなかったときに既定値が入る)の3観点をそろえることを意識します。なお、期限切れ(findOverdue)まわりの境界値テストは演習7で扱います。

2
書く

TaskService.java のクラス宣言にカーソルを置き、Copilot Chat で /tests を使ってひな形を生成します。提案を TaskServiceTest.java に貼り、Chat で境界値テストを追加します。生成された when().thenReturn() が何をしているかを Copilot Chat に日本語で説明させ、自分の言葉で言えるようにします。

3
実行する

./mvnw test を実行し、全件 PASS することを確認します。失敗したら、まずテストの想定が正しいかを読み直します。

4
答え合わせ・比較

hints/step05_test_hint.md を開き、参考プロンプトと自分の依頼文を見比べます。観点の抜けや import の違いを確認します。早く終わった方は ex05-test.md のチャレンジに進みます。

早く終わった人は
  • null・空・境界値などの異常系テストを追加で生成させる指示を、自分でプロンプトとして考えて試してみてください。
  • 同じ入力パターンをまとめて検証する @ParameterizedTest の使い方を Copilot に尋ね、複数の入力を表形式でまとめる書き方を試してみてください。
HANDS-ON演習6 : バグ7パターンを Copilot で直す [50min]

意図的に7種類のバグを仕込んだ id-task-app-bugged フォルダを、VSCode で開きます(同じウィンドウでも別ウィンドウでも構いません)。開いたら VSCode 左上のフォルダ名が id-task-app-bugged になっているかを確認します(starter と取り違えるとつまずきの原因になります)。各バグは // FIXME-NN: でマークしてあります。使う機能は /fix と Copilot Chat。詳細手順は exercises/ex06-debug.md にあります。

#症状箇所学ぶ観点
FIXME-01NullPointerExceptionTaskService.findByIdOptional の扱い、スタックトレースの読み方
FIXME-02SQLインジェクションTaskLegacyDao.findByTitleプリペアドステートメント、生成コードの危険性
FIXME-03リソースリークTaskLegacyDao.findByTitletry-with-resources、Connection 管理
FIXME-04例外握りつぶしTaskService.deleteログ出力・再スロー、catch の粒度
FIXME-05境界値バグTaskService.findOverdue境界値テストの重要性
FIXME-06無限ループTaskService.completeAllデバッガの使い方、状況の伝え方
FIXME-07ハードコード認証情報LegacyConfig・application.yml機密情報の扱い、ガイドラインとの接続
1
考える

7つのうち、どれから取り組むかを3つ選んで memo.md に書きます。番号順でなくて構いません。テストで見つかるバグ(FIXME-01・05・06)と、テストでは見つからないバグ(FIXME-02・03・04・07)があることを意識します。

2
書く

テストで見つかるバグは、./mvnw test の失敗スタックトレースを Copilot Chat に貼って原因を聞き、/fix で順に直します。見つからないバグは、ファイルを選択して「セキュリティとリソース管理の観点でレビューしてください」と依頼します。修正案は Apply する前に必ず読みます。

3
実行する

直すたびに ./mvnw test を実行し、PASS が増えることを確認します。スタックトレースは一番上が最後に起きた例外、Caused by: の下が本当の原因です。jp.idhd.taskapp を含む行から先に読みます。

4
答え合わせ・比較

hints/step06_debug_hint.md を開き、各バグの「直し方の型」と自分の修正を見比べます。テストで赤くならないバグを直したつもりで終えていないかを確認します。4つ以上直してテストが PASS すれば到達です。

早く終わった人は
  • 直したバグについて「同じバグを二度と起こさないためのテスト」を1つ、自分で考えて書いてみてください。
  • なぜそのバグが起きたのかを Copilot に説明させ、自分の理解と照らし合わせてみてください。
SOURCES
SESSION 05

総合演習

2日間の集大成です。設計書1枚から「期限切れタスクを赤色で一覧表示する機能」を、Copilot を使って一気通貫で作ります。個人ワーク80分のあと、講師が解説とふりかえりを行います(発表ではありません)。

HANDS-ON演習7 : 期限切れタスク表示機能を作る [80min+解説30min]

対象ファイルは TaskService.java / TaskController.java / templates/tasks/list.html / TaskServiceTest.java。使う機能はインライン補完・Copilot Chat・/tests。詳細手順は exercises/ex07-overdue.md にあります。

1
考える

docs/設計書.md を開き、A4 1枚の仕様、特に受け入れ条件の表を読み込みます。どのファイルを何のために変えるかを memo.md に書き出します。進める順番は Service → Test → Controller → Template が安全です。

2
書く

まず TaskService.findOverdue(LocalDate) を実装します。仕様の肝は「today より前の dueDate を返す、ただし today ちょうどは含めない」と「DONE(完了)のタスクは、期限が過ぎていても期限切れにしない」の2点です。findByDueDateBefore(today) で取得したあと、status が DONE のものを除外します。次に境界値(今日が期限を含む/含まないを明示)の JUnit テストを生成します。続けて Controller で期限切れ ID を Set<Long> にして渡し、最後に Thymeleaflist.htmlth:classappend を使って該当行に overdue クラスを付けます。CSS の .overdue は定義済みです。

3
実行する

./mvnw spring-boot:run で起動し、ブラウザで http://localhost:8080/tasks を開きます。期限が過去の行だけが赤背景になり、今日・未来・null・DONE(完了)の行は赤くならないことを確認します。テストも ./mvnw test で PASS させます。

4
答え合わせ・比較

hints/step07_overdue_hint.md を開き、参考プロンプトと境界値の扱いを見比べます。赤くならないときの切り分け(開発者ツールで class="overdue" の有無を見る)も確認します。

早く終わった人は
  • 「期限が今日ちょうどのタスク」をどう扱うか自分で仕様を決め、その判断をプロンプトで Copilot に伝えて実装してみてください。
  • 一覧の並び順や表示文言など、小さな表示の改善を1つ自分で考えて追加してみてください(赤色一覧の本筋は壊さない範囲で行います)。
80分の使い方

80分で完璧を目指す必要はありません。動くところまで持っていくのが優先です。「今日が期限のタスクを含めるか」を曖昧にしたまま書くと、テストと実装でズレます。先に1行で仕様を固定してから手を動かすと、Copilot への依頼もぶれません。終わらなかった部分は「次やるなら何をするか」を memo.md に残します。このあと講師が、実装の判断ポイントとつまずきやすい箇所を解説します。

SOURCES
SESSION 06

到達チェックと配属後3か月ロードマップ

2日間で身につけた使い方を、配属後にどう定着させるかの道筋です。まず今日の到達を確認し、そのうえで最初の3か月で踏むステップを示します。

01 今日の到達チェック

02 配属後3か月ロードマップ

1か月目 読むことに使う
2か月目 小さく書く・直す
3か月目 文脈を渡す工夫
1
最初の1か月 — 読むことに使う

配属先の既存コードを /explain で読み解きます。いきなり書くより、Copilot に説明させながらコードベースの地図を作る時期です。機密情報を貼らない、出力は必ずレビューする、という社内ガイドラインの線引きを体に入れます。

2
2か月目 — 小さく書く・小さく直す

既存コードへのテスト追加や小さなバグ修正を、/tests/fix で進めます。今日の演習5・6 がそのまま実務の形です。提案は実装前に理解し、動作確認してから採用します。

3
3か月目 — 文脈を渡す工夫を覚える

関連ファイルを開いてから依頼する、要求を小さく刻む、入出力例を添えるといった「文脈の渡し方」で出力の質が変わることを実感します。チームのコーディング規約を .github/copilot-instructions.md にまとめる動きにも触れていきます。

大事なこと

あなたが主役で、Copilot は道具です。生成されたコードは、同僚のコードをレビューするのと同じ目で、機能・セキュリティ・可読性・保守性を見てから採用してください。

SOURCES
SESSION 07

よくある質問

研修中によく出る質問をまとめました。手が止まったらここを先に見てください。

01 テストの考え方

Q. テストは何件書けば「足りる」のですか。

件数より観点です。正常系・異常系・境界値の3つがそろっているかを基準にします。今日の演習では1メソッドあたり3観点を目安にしています。

Q. Copilot が生成したテストをそのまま信じてよいですか。

そのままは避けます。テストは「仕様の宣言」なので、期待値が本当に正しいかは人が判断します。生成されたテストが緩すぎて、バグがあっても PASS してしまうことがあります。

Q. /fix と Chat への質問は、どう使い分けますか。

コンパイルエラーや例外のように「壊れている箇所が明確」なときは /fix が速いです。SQLインジェクションのように「動くけれど危険」なコードは、/fix のきっかけがないので、Chat にレビューを依頼して気づかせます。

02 進め方とモデル

Q. 出力が英語で返ってきます。

プロンプト末尾に「日本語で説明してください」を足します。生成後でも「コメントとテスト名を日本語にしてください」で直せます。多くの場合これで日本語になりますが、再度英語に戻ることもあるので、その都度添えます。

Q. 総合演習が80分で終わりませんでした。

問題ありません。動くところまでを優先し、残りは「次やるなら何をするか」をメモに残します。配属後の自分への引き継ぎになります。

Q. モデルを高性能なものに変えたら速く解けますか。

研修中は講師指定のミドルクラス・低effort のまま使ってください。高性能モデルは AI Credits の消費が大きく、挙動も説明と変わります。配属後に必要に応じて選ぶ判断を、まず今の設定で身につけます。

SOURCES
SESSION 08

うまくいかないとき

よくあるつまずきと、その切り分け手順です。順番に試してください。

01 テスト・ビルドが止まる

テストが赤いまま直らない。

まず assertThat の左右(実際値と期待値)が逆になっていないかを見ます。次にテストの想定そのものが正しいかを読み直します。それでも分からなければ、テストコードを Copilot Chat に貼り「このテストが失敗する理由を教えてください」と聞きます。

bugged 版が起動しない。

意図的なバグでビルドや起動が止まることがあります。./mvnw test の出力を上から読み、jp.idhd.taskapp を含む行を探します。それでも進まないときは ./mvnw clean test でキャッシュを更新してから試します。

ポート8080 が使われていると言われる。

別のサーバーが起動したままの可能性があります。前のサーバーを止めるか、application.ymlserver.port8081 に変えて起動します。

02 画面・出力が思った通りにならない

Thymeleaf の変更が画面に反映されない。

ブラウザのキャッシュが残っていることがあります。Ctrl+Shift+R(Mac は Cmd+Shift+R)でキャッシュ無視リロードします。それでも変わらなければ、サーバーを止めて起動し直します。

期限切れの行が赤くならない。

開発者ツール(F12)で該当行に class="overdue" が付いているかを見ます。付いていなければ Controller 側で overdueIds に値が入っているか、付いているのに色が出なければ CSS 側を疑います。

Copilot の出力が英語のまま。

「日本語で説明してください」を依頼に足します。すでに貼り付けたコードのコメントを日本語化したいときは「このコードのコメントを日本語に書き換えてください」と頼みます。

SOURCES