目次
コード品質とは何か
ざっくり分けると、コード品質には以下のような要素があります:
- 正しさ(バグが少ないこと)
- 読みやすさ・一貫性(他人&未来の自分が読めること)
- 変更のしやすさ(機能追加やリファクタリングがしやすいこと)
JavaScript の世界ではこれを支えるために以下のようなツールがあります:
- コーディング規約・スタイルガイド(Airbnb, Google, StandardJS など)
- 静的解析ツール(ESLint)
- 自動整形ツール(Prettier)
- テストフレームワーク(Jest など)
ESLint:静的解析+ルールでバグと“悪い書き方”を防ぐ
ESLint は何をする?
一言でいうと、「JSコードを“実行せずに”読み、ルールに違反している箇所を教えてくれるツール」です。
例:
- 典型的なバグの芽
- 未使用の変数
- 定義されていない変数への参照
- 到達不能コード(
returnのあとに書かれた処理 など)
- 仕様的に危険な書き方
==と===の混在- 暗黙の
eval的な構文
- プロジェクトのスタイルルール
- セミコロン有り無し
- シングルクォート / ダブルクォート
- インデント幅 など
ESLint は 「ルールセット」+「パーサ」 で動いていて、eslint . のように実行すると、違反箇所を一覧で教えてくれます。
ルールの種類のイメージ
大まかに:
- 可能なバグ
no-undef,no-unused-vars,no-unreachableなど
- ベストプラクティス
eqeqeq(==禁止)、no-implied-evalなど
- スタイル
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」もできる
という、割とストレスの少ない開発体験になります。
単体テスト(ユニットテスト)の基本
何のためにテストを書くのか
主な目的:
- バグを早期に見つける
- リファクタリングしても壊れていない(レベルダウンしていない)ことを自動チェック
- 関数/モジュールの“コードレベルの仕様書”として機能する
JS の世界だと、特に:
- ビジネスロジック(計算・変換)
- 日付処理・フォーマット
- APIレスポンスをパースするロジック
- バリデーションロジック
など、純粋にデータ → データ の処理はユニットテストと相性が良いです。
ユニットテストのパターン(AAA)
AAAパターン(Arrange-Act-Assert) で考えます。
- Arrange:準備
- 必要な入力・前提条件・モックなどを用意
- Act:実行
- テスト対象の関数・メソッドを呼ぶ
- Assert:検証
- 戻り値や副作用が期待通りかアサーション(
expect(...)など)で確認
- 戻り値や副作用が期待通りかアサーション(
Jestの概要(テストフレームワークの代表)
Jest は何をしてくれる?
Jest は、Node.js 環境で動く テストランナー+アサーション+モック機能 をまとめたフレームワークです。
ざっくり言うと:
- テストを見つけて実行するランナー
test,it,describeなどのDSLexpect(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("ケース名", () => { ... })orit(...)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を渡す - 「テストでは外部依存を切り離す」が基本方針
実務的なワークフローの例
ここまでの要素をまとめると、開発フローはこんな感じになります:
- エディタに ESLint + Prettier を統合
- 保存時フォーマット(Prettier)
- リアルタイムlint(ESLint)
- 日常開発:
- コードを書く → 自動整形 → lint 警告を見て修正
- 機能追加時:
- 先にユニットテストを書く(or 同時)
- テストを
npm testなどで回しつつ実装
- リファクタ時:
- 仕様を変えない範囲で書き換える
- テストが通ることを確認する
- CI(GitHub Actions 等)で:
- プッシュやPR時に
npm run lint && npm testを自動実行 - 品質基準(全テスト成功、lintエラー0)を満たさないとマージ不可、など
- プッシュやPR時に
ここまでやると、「バグが入りにくく、後から安心していじれるコードベース」にかなり近づきます。
コメント