[JavaScript講座] コード品質とテスト

当ページのリンクには広告が含まれています。
目次

コード品質とは何か

ざっくり分けると、コード品質には以下のような要素があります:

  1. 正しさ(バグが少ないこと)
  2. 読みやすさ・一貫性(他人&未来の自分が読めること)
  3. 変更のしやすさ(機能追加やリファクタリングがしやすいこと)

JavaScript の世界ではこれを支えるために以下のようなツールがあります:

  • コーディング規約・スタイルガイド(Airbnb, Google, StandardJS など)
  • 静的解析ツール(ESLint)
  • 自動整形ツール(Prettier)
  • テストフレームワーク(Jest など)

ESLint:静的解析+ルールでバグと“悪い書き方”を防ぐ

ESLint は何をする?

一言でいうと、「JSコードを“実行せずに”読み、ルールに違反している箇所を教えてくれるツール」です。

例:

  • 典型的なバグの芽
    • 未使用の変数
    • 定義されていない変数への参照
    • 到達不能コード(return のあとに書かれた処理 など)
  • 仕様的に危険な書き方
    • ===== の混在
    • 暗黙の eval 的な構文
  • プロジェクトのスタイルルール
    • セミコロン有り無し
    • シングルクォート / ダブルクォート
    • インデント幅 など

ESLint は 「ルールセット」+「パーサ」 で動いていて、
eslint . のように実行すると、違反箇所を一覧で教えてくれます。

ルールの種類のイメージ

大まかに:

  1. 可能なバグ
    • no-undef, no-unused-vars, no-unreachable など
  2. ベストプラクティス
    • eqeqeq(==禁止)、no-implied-eval など
  3. スタイル
    • semi, quotes, indent など(これは後述するように Prettier に任せることも多い)

ルールは .eslintrc などの設定でオン/オフ・厳しさ(off / warn / error)を決められます。

設定ファイルの構造

.eslintrc.json の設定例:

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended"
  ],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
    "no-unused-vars": "warn",
    "eqeqeq": "error"
  }
}

ポイント:

  • env:ブラウザ・Node・ESバージョンなど、環境に応じてグローバル変数を定義
  • extends:既存ルールセットを継承(eslint:recommended, Airbnb 等)
  • rules:プロジェクト固有のカスタマイズ

実務では:

  • eslint --init で対話的に設定生成
  • eslint:recommended +α
  • React / TypeScript を使うなら、対応プラグイン・パーサを追加

という流れが多いです。

Prettier:スタイルを「考えなくていい」世界にする

Prettier は何をする?

一言でいうと、「コードをパースしてASTにし、“自分のルール”で書き直すフォーマッタ」です。

特徴:

  • インデント・改行位置・括弧の折り返しなどを 完全自動で決める
  • カスタマイズはかなり少なめ(80〜120文字の行長、セミコロン有無、クォートなど)
  • 「人間が細かいスタイルで悩む時間をゼロにする」が思想

結果として:

  • 「こう書くべきか、こう改行するべきか…」と悩む必要がなくなる
  • チームでコードの“見た目”が完全に統一される
  • レビュー時に「フォーマットの話」をほぼしなくて済む

ESLint と Prettier の役割分担

典型的な考え方:

  • ESLint:ロジック面・バグ予防・ベストプラクティス
    • 例:no-undef, no-unused-vars, no-console
  • Prettier:フォーマット(インデント・改行・クォート)
    • ESLint側のスタイル系ルールは無効化して、競合を避ける

よくある構成:

  • Prettier を導入
  • ESLint を導入
  • eslint-config-prettier を入れて、「Prettierが面倒を見るスタイルルール」をESLint側でオフにする

こうしておくと:

  • eslint で「バグっぽさ」「危険な書き方」をチェック
  • prettier で「見た目」を自動整形
  • VS Code などでは「保存時にフォーマット+lint」もできる

という、割とストレスの少ない開発体験になります。

単体テスト(ユニットテスト)の基本

何のためにテストを書くのか

主な目的:

  1. バグを早期に見つける
  2. リファクタリングしても壊れていない(レベルダウンしていない)ことを自動チェック
  3. 関数/モジュールの“コードレベルの仕様書”として機能する

JS の世界だと、特に:

  • ビジネスロジック(計算・変換)
  • 日付処理・フォーマット
  • APIレスポンスをパースするロジック
  • バリデーションロジック

など、純粋にデータ → データ の処理はユニットテストと相性が良いです。

ユニットテストのパターン(AAA)

AAAパターン(Arrange-Act-Assert) で考えます。

  1. Arrange:準備
    • 必要な入力・前提条件・モックなどを用意
  2. Act:実行
    • テスト対象の関数・メソッドを呼ぶ
  3. Assert:検証
    • 戻り値や副作用が期待通りかアサーション(expect(...) など)で確認

Jestの概要(テストフレームワークの代表)

Jest は何をしてくれる?

Jest は、Node.js 環境で動く テストランナー+アサーション+モック機能 をまとめたフレームワークです。

ざっくり言うと:

  • テストを見つけて実行するランナー
  • test, it, describe などのDSL
  • expect(value).toBe(...) などのアサーション
  • モック(関数・モジュール・タイマー)
  • カバレッジ計測

「とりあえず JS のユニットテストしたい」ときのオールインワンな選択肢です。

ごく基本的なテストコードの形

対象コード sum.js

// sum.js
export function sum(a, b) {
  return a + b;
}

テスト sum.test.js

// sum.test.js
import { sum } from "./sum";

test("1 + 2 = 3 になること", () => {
  const result = sum(1, 2);
  expect(result).toBe(3);
});

よく出てくる構文:

  • describe("グループ名", () => { ... })
  • test("ケース名", () => { ... }) or it(...)
  • expect(値).toBe(期待値);
  • 他にも toEqual, toBeNull, toContain, toThrow など豊富な matcher

非同期処理のテスト

Promise を返す関数のテスト例:

// fetchUser.js
export async function fetchUserName(api, id) {
  const res = await api.get(`/users/${id}`);
  return res.data.name;
}
// fetchUser.test.js
import { fetchUserName } from "./fetchUser";

test("ユーザー名を返すこと", async () => {
  const fakeApi = {
    get: async (path) => ({
      data: { name: "Taro" }
    })
  };

  const name = await fetchUserName(fakeApi, 1);
  expect(name).toBe("Taro");
});
  • テスト関数を async にして await を使う
  • 実際のHTTP通信は行わず、モックした api を渡す
  • 「テストでは外部依存を切り離す」が基本方針

実務的なワークフローの例

ここまでの要素をまとめると、開発フローはこんな感じになります:

  1. エディタに ESLint + Prettier を統合
    • 保存時フォーマット(Prettier)
    • リアルタイムlint(ESLint)
  2. 日常開発:
    • コードを書く → 自動整形 → lint 警告を見て修正
  3. 機能追加時:
    • 先にユニットテストを書く(or 同時)
    • テストを npm test などで回しつつ実装
  4. リファクタ時:
    • 仕様を変えない範囲で書き換える
    • テストが通ることを確認する
  5. CI(GitHub Actions 等)で:
    • プッシュやPR時に npm run lint && npm test を自動実行
    • 品質基準(全テスト成功、lintエラー0)を満たさないとマージ不可、など

ここまでやると、「バグが入りにくく、後から安心していじれるコードベース」にかなり近づきます。


<<前へ(弱参照(WeakRef / FinalizationRegistry))

>>次へ(パフォーマンスとメモリ)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次