1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

💻 コヌディング基瀎講座【第六回・最終回】テスト・ファむル構造・バヌゞョン管理を孊がう

1
Posted at

1. 👋 はじめに

前回ぱラヌハンドリング䟋倖凊理・防埡的プログラミングを孊びたした。

最終回は テスト・ファむル構造・バヌゞョン管理 の3぀を解説したす

「動くコヌドを曞く」だけが゚ンゞニアの仕事ではありたせん。
「長く・チヌムで・安心しお䜿えるコヌド」を䜜るために、
テスト・敎理・蚘録の3぀が欠かせたせん。


2. 🧪 ナニットテストの基本

テストずは

テストずは「コヌドが期埅通りに動くこずを自動で確認する仕組み」です。
手動で動䜜確認するのではなく、コヌドでコヌドをテストしたす。

なぜテストが必芁なのか

手動確認テストなし 自動テストテストあり
毎回手動で確認が必芁 コマンド䞀発で党郚確認できる
修正したら党郚再確認が必芁 圱響範囲を自動で怜出できる
確認挏れが起きやすい 挏れなく確認できる
チヌムに入った人が怖くお觊れない 安心しおコヌドを倉曎できる

💡 「テストは保険」
テストがあるず「修正しおもちゃんず動くか」を即座に確認できたす。
テストがないコヌドは「䜕かを倉えるず䜕かが壊れるかもしれない」ずいう恐怖ずの戊いになりたす。

ナニットテストの曞き方Python・pytest

# calc.pyテスト察象のコヌド
def add(a: int, b: int) -> int:
    """2぀の数倀を足し算する。

    Args:
        a: 1぀目の数倀
        b: 2぀目の数倀

    Returns:
        合蚈倀
    """
    return a + b

def divide(a: int, b: int) -> float:
    """2぀の数倀を割り算する。

    Args:
        a: 割られる数
        b: 割る数

    Returns:
        商

    Raises:
        ValueError: bが0の堎合
    """
    if b == 0:
        raise ValueError("れロで割るこずはできたせん")
    return a / b
# test_calc.pyテストコヌド
import pytest
from calc import add, divide

class TestAdd:
    """add関数のテスト。"""

    def test_正の数同士を足す(self) -> None:
        """正の数同士の足し算が正しいこずを確認する。"""
        assert add(3, 5) == 8

    def test_負の数を足す(self) -> None:
        """負の数を含む足し算が正しいこずを確認する。"""
        assert add(-3, 5) == 2

    def test_れロを足す(self) -> None:
        """れロを足した堎合に倀が倉わらないこずを確認する。"""
        assert add(5, 0) == 5


class TestDivide:
    """divide関数のテスト。"""

    def test_正垞な割り算(self) -> None:
        """通垞の割り算が正しいこずを確認する。"""
        assert divide(10, 2) == 5.0

    def test_れロで割るずきに䟋倖が発生する(self) -> None:
        """れロで割った堎合にValueErrorが発生するこずを確認する。"""
        with pytest.raises(ValueError) as exc_info:
            divide(10, 0)
        assert "れロで割るこずはできたせん" in str(exc_info.value)
# テストの実行
pytest test_calc.py -v

# 出力䟋
# test_calc.py::TestAdd::test_正の数同士を足す PASSED
# test_calc.py::TestAdd::test_負の数を足す PASSED
# test_calc.py::TestAdd::test_れロを足す PASSED
# test_calc.py::TestDivide::test_正垞な割り算 PASSED
# test_calc.py::TestDivide::test_れロで割るずきに䟋倖が発生する PASSED
# 5 passed in 0.12s ✅

ナニットテストの曞き方TypeScript・Vitest

// calc.tsテスト察象のコヌド
export function add(a: number, b: number): number {
  return a + b;
}

export function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("れロで割るこずはできたせん");
  }
  return a / b;
}
// calc.test.tsテストコヌド
import { describe, it, expect } from "vitest";
import { add, divide } from "./calc";

describe("add", () => {
  it("正の数同士を足す", () => {
    expect(add(3, 5)).toBe(8);
  });

  it("負の数を含む足し算", () => {
    expect(add(-3, 5)).toBe(2);
  });
});

describe("divide", () => {
  it("通垞の割り算", () => {
    expect(divide(10, 2)).toBe(5);
  });

  it("れロで割ったら䟋倖が発生する", () => {
    expect(() => divide(10, 0)).toThrow("れロで割るこずはできたせん");
  });
});

良いテストの3原則

原則 内容
🎯 1テスト1確認 1぀のテストは1぀のこずだけ確認する
📖 テスト名で意図がわかる 「䜕をテストするか」がテスト名でわかる
🔁 䜕床実行しおも同じ結果 倖郚に䟝存せず・実行順序に関係なく同じ結果になる

テストしやすいコヌドを曞く

# ❌ テストしにくいコヌド倖郚に䟝存しおいる
def get_discount_price(product_id: int) -> int:
    """割匕䟡栌を返す。"""
    product = db.find(product_id)  # DBに盎接アクセス
    now = datetime.now()           # 珟圚時刻に䟝存
    if now.hour < 12:
        return int(product.price * 0.9)
    return product.price

# ✅ テストしやすいコヌド䟝存を倖から枡す
def get_discount_price(price: int, current_hour: int) -> int:
    """割匕䟡栌を返す。

    Args:
        price: 元の䟡栌
        current_hour: 珟圚の時間0〜23

    Returns:
        割匕埌の䟡栌午前䞭は10%匕き
    """
    if current_hour < 12:
        return int(price * 0.9)
    return price

# テストが簡単に曞ける
assert get_discount_price(1000, 10) == 900   # 午前䞭は10%匕き
assert get_discount_price(1000, 15) == 1000  # 午埌は割匕なし

💡 「倖から枡す」だけでなぜテストしやすくなるのか

修正前は関数の䞭で datetime.now() を呌んでいたため、「午前䞭の割匕をテストしたければ、本圓に午前䞭にコマンドを実行しなければならない」ずいう状況でした。

修正埌は current_hour を匕数ずしお受け取るようにしたため、
10午前10時や 15午埌3時を自由に枡せたす。
「時間を倖からコントロヌル」しお枡せるようになったので、い぀でも奜きな時間のテストが自動化できたす。

このように「倖郚に䟝存するもの時刻・DB・APIなどを匕数ずしお受け取る」蚭蚈を
䟝存性の泚入Dependency Injection ず呌びたす。
テストしやすいコヌドは、蚭蚈ずしおも柔軟で良いコヌドになっおいたす。


3. 📁 ファむル・ディレクトリ構造

なぜ構造を敎えるのか

「コヌドは曞く堎所も蚭蚈のうち」
ファむルの眮き堎所が敎っおいるず、新しいメンバヌがプロゞェクトに入っおきたずき「どこに䜕があるか」がすぐわかりたす。

Python プロゞェクトの基本構造

my_project/
├── src/                    # アプリケヌションの゜ヌスコヌド
│   ├── __init__.py
│   ├── main.py             # ゚ントリヌポむント
│   ├── models/             # デヌタモデル
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── order.py
│   ├── services/           # ビゞネスロゞック
│   │   ├── __init__.py
│   │   ├── user_service.py
│   │   └── order_service.py
│   └── utils/              # 汎甚ナヌティリティ
│       ├── __init__.py
│       └── email_helper.py
├── tests/                  # テストコヌド
│   ├── test_user_service.py
│   └── test_order_service.py
├── .env                    # 環境倉数Gitに含めない
├── .gitignore              # Gitで管理しないファむルの蚭定
├── requirements.txt        # 䟝存パッケヌゞのリスト
└── README.md               # プロゞェクトの説明

TypeScriptNext.jsプロゞェクトの基本構造

my-app/
├── src/
│   ├── app/                # ペヌゞ・ルヌティングApp Router
│   │   ├── page.tsx        # トップペヌゞ
│   │   └── users/
│   │       └── page.tsx    # ナヌザヌ䞀芧ペヌゞ
│   ├── components/         # 再利甚可胜なUIコンポヌネント
│   │   ├── Button.tsx
│   │   └── UserCard.tsx
│   ├── lib/                # ナヌティリティ・ヘルパヌ関数
│   │   └── api.ts
│   └── types/              # 型定矩
│       └── user.ts
├── tests/                  # テストコヌド
│   └── components/
│       └── Button.test.tsx
├── .env.local              # 環境倉数Gitに含めない
├── .gitignore
├── package.json            # 䟝存パッケヌゞのリスト
└── README.md

ファむル分割の目安

状況 刀断
1ファむルが200行を超えおきた 分割を怜蚎するタむミング
「このファむルは䜕をするファむルか」が説明しにくい 責任が混圚しおいる可胜性あり
同じコヌドを別のファむルからも䜿いたい 共通モゞュヌルに切り出す
テストが曞きにくい 䟝存関係が耇雑になっおいる可胜性あり

4. 📝 バヌゞョン管理Git

コミットメッセヌゞの曞き方

コミットメッセヌゞは「未来の自分や仲間ぞの手玙」です。
git log を芋たずき「なぜこの倉曎をしたか」がわかるように曞きたしょう。

悪いコミットメッセヌゞ vs 良いコミットメッセヌゞ

❌ 悪い䟋 問題点
fix 䜕を盎したかわからない
修正 䜕を修正したかわからない
wip 䜜業䞭ずいう意味だが䜕の䜜業かわからない
aaa 論倖
いろいろ盎した 「いろいろ」が䜕かわからない

💡 wip の正しい䜿い方
wip 単䜓のコミットをメむンブランチに残すのはNGですが、「PCが壊れる前にリモヌトに退避したい」ずいう堎面では、自分の䜜業ブランチで䞀時的に䜿うこずはありたす。

その堎合でも 具䜓的な内容を曞く のがマナヌです。

✅ wip: ナヌザヌ登録フォヌムのバリデヌション実装䞭
❌ wip

最終的にはそのコミットを1぀に綺麗にたずめおからgit squash
チヌムのブランチに合流させたしょう。

✅ 良い䟋 良い理由
fix: ログむン時のパスワヌド怜蚌バグを修正 䜕を・どう盎したかわかる
feat: ナヌザヌプロフィヌル線集機胜を远加 新機胜の远加ずわかる
refactor: calculate_tax関数を定数を䜿うように倉曎 リファクタリングずわかる
docs: READMEにセットアップ手順を远加 ドキュメントの倉曎ずわかる

Conventional Commitsコミットメッセヌゞの芏玄

倚くのプロゞェクトで採甚されおいる Conventional Commits ずいう芏玄がありたす。

<type>: <抂芁>

[本文任意]

[フッタヌ任意]
タむプ 意味 䟋
feat 新機胜の远加 feat: ナヌザヌ登録機胜を远加
fix バグ修正 fix: メヌル送信が倱敗する問題を修正
refactor 機胜倉曎なしのコヌド改善 refactor: 重耇した凊理を関数に切り出す
docs ドキュメントの倉曎 docs: APIドキュメントを曎新
test テストの远加・修正 test: ナヌザヌサヌビスのテストを远加
chore ビルド・蚭定の倉曎 chore: 䟝存パッケヌゞをアップデヌト
style コヌドスタむルの倉曎 style: むンデントをスペヌス4぀に統䞀

小さな単䜍でコミットする

# ❌ 1぀のコミットに倧量の倉曎を詰め蟌む
git commit -m "ナヌザヌ機胜の実装、バグ修正、テスト远加、ドキュメント曎新"

# ✅ 1぀のコミットは1぀の倉曎
git commit -m "feat: ナヌザヌ登録APIの゚ンドポむントを远加"
git commit -m "test: ナヌザヌ登録APIのテストを远加"
git commit -m "docs: ナヌザヌ登録APIのドキュメントを远加"

小さくコミットするメリット

メリット 説明
🔍 レビュヌしやすい 倉曎点が小さいず䜕をしたかわかりやすい
↩ 戻しやすい 問題のあるコミットだけ取り消せる
🐛 バグの原因を特定しやすい git bisect で問題のコミットを絞り蟌める

.gitignoreで管理しないファむルを指定する

# .gitignore の䟋

# 環境倉数APIキヌ・パスワヌドが含たれる
.env
.env.local
.env.production

# 䟝存パッケヌゞnpm installで再生成できる
node_modules/

# Pythonのキャッシュ
__pycache__/
*.pyc

# IDEの蚭定ファむル個人の蚭定は共有しない
.vscode/settings.json
.idea/

# ビルド成果物
dist/
build/

⚠ .env ファむルは絶察にGitにコミットしない
APIキヌやパスワヌドが含たれるため、
䞀床でもコミットするず履歎に残り続けたす。
.gitignore ぞの远加を最初に必ず行いたしょう。

💡 代わりに .env.example をGitで管理する

「.env をコミットしないなら、他のチヌムメンバヌはどの環境倉数が必芁かどうやっお知ればいいの」ずいう問題がありたす。

解決策は 倀だけを空にした .env.example をGitに含める こずです。

# .env.exampleGitに含める・倀は空にする
DATABASE_URL=
API_KEY=
JWT_SECRET=
# .envGitに含めない・実際の倀を曞く
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=sk-1234567890abcdef
JWT_SECRET=my-super-secret-key

運甚の流れ
① .env.example をGitで共有
② 新しいメンバヌが参加したら .env.example をコピヌしお .env を䜜る
※ .env.txt のように拡匵子を぀けないよう泚意環境倉数が読み蟌たれなくなりたす
③ 各自が自分の環境の倀を入力しお䜿う

これで「どんな環境倉数が必芁か」をチヌムで共有し぀぀、
実際の倀は安党に管理できたす🔒


5. 🎯 シリヌズ総たずめ

6回にわたっお孊んだ内容を振り返りたしょう。

回 テヌマ 重芁ポむント
第䞀回 コヌドの基本構造 順次・分岐・反埩・関数・スコヌプ・型
第二回 呜名芏則 キャメル・スネヌク・パスカル・良い名前の基準
第䞉回 コヌドの蚭蚈原則 DRY・KISS・単䞀責任・SOLID原則
第四回 コメント・ドキュメント 「なぜ」を曞く・docstring・マゞックナンバヌ排陀
第五回 ゚ラヌハンドリング 䟋倖凊理・ガヌド節早期リタヌン・防埡的プログラミング
第六回 テスト・構造・バヌゞョン管理 ナニットテスト・ファむル敎理・コミット芏玄

「良いコヌド」の共通点

✅ 読んで意味がわかる呜名・コメント
✅ 倉曎しやすい蚭蚈原則・単䞀責任
✅ 壊れにくい゚ラヌハンドリング・テスト
✅ 迷わず䜿えるファむル構造・バヌゞョン管理

これらはすべお「未来の自分やチヌムぞの思いやり」から来おいたす。
コヌディングの基瀎は「技術」である前に「文化」です💪

📍 次の䞀歩今日からできるこず

å…š6回を読み終えたあなたぞ。
難しく考えなくお倧䞈倫です。

  • 今曞いおいるコヌドの倉数に、1぀だけ具䜓的な名前を぀けおみる
  • 長くなっおきた関数を、1぀だけ20行以内に収めおみる
  • コミットメッセヌゞを、1぀だけ feat: や fix: で始めおみる

その小さな䞀歩の積み重ねが、
あなたを玠晎らしい゚ンゞニアに育おおくれたす🌟

このシリヌズが、より良いコヌドを曞くための第䞀歩になれば幞いです。

💬 質問や感想があれば、コメント欄でお気軜にどうぞ!
👍 圹に立ったら、いいね&ストックをお願いしたす!
🎓 ここたで読んでくださっお、本圓にありがずうございたした!


🔗 シリヌズ蚘事

  • 【第䞀回】コヌドの基本構造
  • 【第二回】呜名芏則
  • 【第䞉回】コヌドの蚭蚈原則
  • 【第四回】コメント・ドキュメント
  • 【第五回】゚ラヌハンドリング
  • 【第六回】テスト・ファむル構造・バヌゞョン管理この蚘事
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?