QUIZ 120分

卒業クイズ:品質の番人となろう

ストーリー

「これが最終試験だ」

松本先輩が真剣な表情で言った。

「コードレビュー、テスト設計、SRE原則。 今月学んだ全ての知識を総動員して挑んでくれ。 これを突破すれば、品質の番人として認められる。 そして......L1カリキュラムの全課程修了だ」

「L0から始まって、ここまで来たんだ。 自信を持って挑め。君は確実に成長している」


クイズの説明

今月の全ステップの内容から出題します。

  • 全8問
  • 合格ライン: 80%(7問正解)
  • 不合格の場合は、該当ステップを復習してから再挑戦してください

問題

Q1. コードレビューで以下のコードを発見しました。最も重要度の高い指摘はどれですか?

typescript
async function deleteUser(req: Request, res: Response) {
  const userId = req.params.id;
  const query = `DELETE FROM users WHERE id = '${userId}'`;
  await db.execute(query);
  res.json({ message: 'User deleted' });
}
  • A) [Nit] 関数名を removeUser にした方が良い
  • B) [Should Fix] レスポンスに削除結果(件数)を含めた方が良い
  • C) [Must Fix] SQLインジェクションの脆弱性があり、認証・認可チェックも欠如している
  • D) [Should Fix] async/await の代わりに Promise を使った方が良い
<details> <summary>解答と解説</summary>

正解: C

このコードには2つの重大な問題があります: (1) ユーザー入力(userId)を直接SQLに埋め込んでおり、SQLインジェクション攻撃に対して脆弱。'; DROP TABLE users; -- のような入力でテーブルが削除される可能性があります。(2) リクエストを送信したユーザーが対象ユーザーの削除権限を持っているか確認していません。どちらもセキュリティ上の [Must Fix] です。

</details>

Q2. 以下のコードに含まれるコードスメルの組み合わせとして最も適切なものはどれですか?

typescript
function p(d: any[], t: string, n: number) {
  const r: any[] = [];
  for (let i = 0; i < d.length; i++) {
    if (d[i].status === 1) {
      if (d[i].type === t) {
        if (d[i].amount > n) {
          if (d[i].isValid === true) {
            r.push(d[i]);
          }
        }
      }
    }
  }
  return r;
}
  • A) 重複コード、Feature Envy
  • B) 深いネスト、不適切な命名、any型の使用、マジックナンバー
  • C) 神クラス、プリミティブ執着
  • D) 循環参照、密結合
<details> <summary>解答と解説</summary>

正解: B

このコードには4つのコードスメルがあります: (1) if文が4段にネストしており読みにくい(深いネスト)、(2) 関数名 p、引数名 d, t, n、変数名 r が1文字で意味不明(不適切な命名)、(3) any[] 型でTypeScriptの型安全性が無効(any型の使用)、(4) status === 1, isValid === true がマジックナンバー/マジックリテラル。早期リターン、命名改善、型定義、定数化で大幅に改善できます。

</details>

Q3. テストピラミッドに基づくテスト配分と、各テストに使用するツールの組み合わせとして正しいものはどれですか?

  • A) E2Eテスト70% (Jest) + インテグレーション20% (Playwright) + ユニットテスト10% (supertest)
  • B) ユニットテスト70% (Jest/Vitest) + インテグレーション20% (supertest) + E2Eテスト10% (Playwright)
  • C) 手動テスト50% + 自動テスト50% (Jest)
  • D) ユニットテスト100% (Jest) のみで十分
<details> <summary>解答と解説</summary>

正解: B

テストピラミッドでは、底辺のユニットテスト(70%、Jest/Vitest)を最も多く、次にインテグレーションテスト(20%、supertest等でAPI結合テスト)、最上部のE2Eテスト(10%、Playwright でブラウザ自動操作)という配分が推奨されます。ユニットテストは高速で安定、E2Eテストは遅く不安定なため、重要シナリオに限定します。

</details>

Q4. 以下のテストコードの問題点として最も適切なものはどれですか?

typescript
describe('UserService', () => {
  it('should work', async () => {
    const user = await userService.createUser({
      name: 'Test',
      email: 'test@example.com',
      password: 'pass',
    });
    expect(user).toBeDefined();

    const found = await userService.findById(user.id);
    expect(found).toBeDefined();

    await userService.updateUser(user.id, { name: 'Updated' });
    const updated = await userService.findById(user.id);
    expect(updated.name).toBe('Updated');

    await userService.deleteUser(user.id);
    const deleted = await userService.findById(user.id);
    expect(deleted).toBeNull();
  });
});
  • A) async/await の使い方が間違っている
  • B) テスト名が曖昧で、1つのテストに複数の操作が詰め込まれており、テストの独立性が欠如している
  • C) expect のマッチャーの使い方が間違っている
  • D) describe のネストが足りない
<details> <summary>解答と解説</summary>

正解: B

このテストには複数の問題があります: (1) テスト名 "should work" が曖昧で、何を検証しているか分からない、(2) 1つのテストケースに create、find、update、delete の4つの操作と検証が詰め込まれている(1テスト1アサーション の原則に違反)、(3) 後半のテスト(update、delete)が前半のテスト(create)の結果に依存しており、独立性がない。テストは分割し、各テストケースに独立したセットアップを持たせるべきです。

</details>

Q5. TDD の Red-Green-Refactor サイクルにおいて、Green フェーズで行うべきことはどれですか?

  • A) テストを書かずに最終的な実装コードを書く
  • B) 失敗するテストを書く
  • C) テストを通す最小限の実装を書く
  • D) コードの構造を改善する
<details> <summary>解答と解説</summary>

正解: C

TDDのGreenフェーズでは、直前のRedフェーズで書いた失敗するテストを通すための、最小限の実装コードを書きます。この段階では美しいコードを書く必要はなく、テストが通ることだけを目的とします。コードの改善はRefactorフェーズで行います。Redは失敗テストの作成(B)、Refactorはコード改善(D)です。

</details>

Q6. SLO が 99.95% のサービスの月間エラーバジェット(30日間)はどれに最も近いですか?

  • A) 約4.3分
  • B) 約21.6分
  • C) 約43.2分
  • D) 約7.2時間
<details> <summary>解答と解説</summary>

正解: B

エラーバジェット = 1 - 0.9995 = 0.0005 = 0.05%。30日の総分数 = 30 x 24 x 60 = 43,200分。許容ダウンタイム = 43,200 x 0.0005 = 21.6分。99.9%の場合は43.2分、99.95%はその半分の約21.6分です。SLOが1ナイン上がるごとに許容ダウンタイムは約10分の1になる点を覚えておきましょう。

</details>

Q7. 以下のうち、「トイル」に該当しないものはどれですか?

  • A) 毎日のログ手動チェック
  • B) SSL証明書の手動更新
  • C) SLO目標値の見直しと再設計
  • D) 手動でのステージング環境デプロイ
<details> <summary>解答と解説</summary>

正解: C

SLO目標値の見直しと再設計は、創造的な知的作業であり、長期的な価値を生むエンジニアリング活動です。トイルの定義(手動、反復的、自動化可能、戦術的、サービス成長に比例)に当てはまりません。A(ログチェック)、B(証明書更新)、D(手動デプロイ)はいずれも手動で反復的な作業であり、自動化が可能なトイルです。

</details>

Q8. 品質の番人としてチームに貢献するために、コードレビュー・テスト・SREの3つを統合した取り組みとして最も効果的なものはどれですか?

  • A) コードレビューを厳格にし、全ての変更を上級者だけがレビューする
  • B) テストカバレッジを100%にすることだけを目標にする
  • C) レビュー体制の構築、テストのCI統合、SLI/SLOに基づく運用を組み合わせ、開発から本番運用まで品質を継続的に守る仕組みを構築する
  • D) 全ての運用をSREチームに任せ、開発チームは機能開発に専念する
<details> <summary>解答と解説</summary>

正解: C

品質の番人として最も効果的なのは、開発プロセスの各段階に品質保証の仕組みを組み込むことです: (1) コードレビューで開発段階の品質を確保し、(2) テストのCI統合で変更の安全性を自動検証し、(3) SLI/SLOに基づく運用で本番環境の品質を継続的に監視する。これら3つの仕組みが連携して初めて、「品質の番人」として機能します。A は属人化、B はカバレッジの数字だけに偏り、D は開発と運用の分断を招きます。

</details>

結果

7問以上正解の場合

合格です。おめでとうございます。ミッション完了です!

「品質の番人となろう」ミッションを完了しました。

松本先輩が立ち上がり、深く頷いた。

「やったな。これで全ての課題をクリアした。 コードレビュー、テスト設計、SRE原則...... 品質を守るための武器を全て手に入れたんだ」

「ありがとうございます、松本先輩」

「でもな、本当の番人になるのはここからだ。 知識を持っているだけじゃ意味がない。 日々の開発の中で実践し、チームに文化として根付かせていく。 それが品質の番人の本当の仕事だ」

松本先輩が手を差し出した。

「一人前のエンジニアとして、自信を持って歩んでいけ。 L1カリキュラムの全課程修了だ。おめでとう」

6問以下の場合

もう少し復習しましょう。

問題復習セクション
Q1Step 1 - コードレビューの心得(チェックリスト・コメント)
Q2Step 2 - コードスメルの検出
Q3Step 3 - テストの種類と戦略
Q4Step 4 - ユニットテストの実践
Q5Step 3 - TDDの基本
Q6Step 5 - エラーバジェットの運用
Q7Step 5 - トイル削減の実践
Q8Step 6 - 総合演習

ミッション完了

お疲れさまでした。

今月学んだこと

ステップ内容
Step 1コードレビューの心得(マインドセット、チェックリスト、コメント、ツール、文化)
Step 2コードレビュー実践(レビュー手法、コードスメル、リファクタリング、ペア/モブレビュー)
Step 3テスト設計の基本(テストの重要性、種類と戦略、設計技法、TDD、カバレッジ)
Step 4テスト実践(Jest/Vitest、インテグレーション、Playwright、CI統合)
Step 5SRE原則(SLI/SLO、エラーバジェット、トイル削減)
Step 6品質改善プロジェクト(コードレビュー体制、テスト戦略、SRE運用計画)

身についたスキル

  • 他者のコードを建設的にレビューし、コードスメルを検出できる
  • テストピラミッドに基づいた体系的なテスト戦略を設計できる
  • Jest/Vitest でユニットテスト、Playwright でE2Eテストを実装できる
  • TDD の Red-Green-Refactor サイクルを実践できる
  • SLI/SLO を設計し、エラーバジェットで運用判断ができる
  • トイルを特定し、自動化による削減計画を立てられる

L1カリキュラム修了

おめでとうございます。L1カリキュラムの全10ヶ月を修了しました。

L1カリキュラム 修了証

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Month 1:  Linux/CLI           ✅ 修了
  Month 2:  Git/GitHub          ✅ 修了
  Month 3:  データベース         ✅ 修了
  Month 4:  セキュリティ基礎     ✅ 修了
  Month 5:  API設計             ✅ 修了
  Month 6:  クラウド基礎         ✅ 修了
  Month 7:  CI/CD + IaC         ✅ 修了
  Month 8:  コンテナ技術         ✅ 修了
  Month 9:  監視・ログ           ✅ 修了
  Month 10: 品質管理・SRE        ✅ 修了

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  あなたは「一人前のエンジニア」として
  認められました。

  次のステップ:
  L2カリキュラム(一人前→チームリーダー)
  または、各スキルの深掘り学習

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

L1で身についた総合スキル

カテゴリスキル
インフラLinux、Docker、Kubernetes、AWS、Terraform
開発基盤Git、GitHub、CI/CD、GitHub Actions
データSQL、RDB設計、ORM
セキュリティOWASP Top 10、認証認可、暗号化
APIREST API設計、OpenAPI、認証
品質管理コードレビュー、テスト設計、Jest/Playwright
運用監視、ログ、SRE原則、SLI/SLO

次のステップ(推奨学習)

  • L2カリキュラム: チームリーダーとしてのスキル
  • マイクロサービスアーキテクチャの設計
  • ドメイン駆動設計(DDD)の深掘り
  • パフォーマンスチューニング
  • チーム開発のマネジメント手法
  • OSS へのコントリビューション

推定所要時間: 120分