単体テスト。なんだろう、これ。よく聞くけど。
プログラムが、ちゃんと動くか確かめること…らしい。 小さい単位で。 関数とか、メソッドとか。 うん、わかるような、わからないような。
とりあえず、結論から言うと
単体テストは、「未来の自分を助けるための保険」みたいなもの、かな。コードを触るのが怖くなくなる、お守り。
これを書いておけば、後で何か変更したときに、意図せず何かを壊してないかすぐわかる。その安心感が、たぶん一番大事。
なんでテストが必要に感じたか
昔、ちょっとした修正のつもりが、全然関係ない場所の機能を壊したことがあって。それに気づいたのが、ずっと後になってからで…。もう、最悪だった。
あの時、もしテストがあれば。「この変更で、ここが動かなくなりましたよ」って、すぐに教えてくれたはず。後工程での手戻りを減らせる、っていうのはこういうことか。
バグが見つかるのが早ければ早いほど、修正は楽。 これは本当にそう思う。だから、品質のため、というより、自分の精神衛生のために必要、って感じてる。
じゃあ、どう書くの? 基本の考え方
なんか、3つのステップがあるらしい。「準備・実行・検証」。英語だと Arrange, Act, Assert って言うみたい。
- 準備 (Arrange): テストしたい関数を動かすための、お膳立て。データとか、オブジェクトとかを用意する。
- 実行 (Act): 実際に、その関数を呼び出す。
- 検証 (Assert): 実行した結果が、期待通りだったかチェックする。ここで「こうなるはずだ」っていうのを書く。
この「検証」がキモだよね。結果が期待通りならテストは成功。違ったら失敗。すごくシンプル。
あと、テスト駆動開発(TDD)っていう考え方もあるらしい。 これは、先に失敗するテストを書いて、そのテストをパスするために最小限のコードを書いて、きれいにしていく…っていうサイクルを回す開発手法。 Red/Green/Refactorって呼ばれてる。 うーん、これはちょっと上級者向けかな。まずは動くコードにテストを書くところから始めたい。
試しに書いてみる(Pythonの場合)
日本の記事だとJavaのJUnitが多い気がするけど、ここではPythonの`pytest`を使ってみる。こっちのほうがシンプルに書けるらしいから。
# product.py
# これがテスト対象のコード
def add(a, b):
"""二つの数を足し算する関数"""
return a + b
# test_product.py
# こっちがテストコード
import pytest
from product import add
def test_add_positive_numbers():
# 準備 (Arrange) は特にないけど、心の中では。
# 実行 (Act) と 検証 (Assert) を一緒に
assert add(2, 3) == 5
def test_add_negative_numbers():
# 期待値がマイナスになるケースも試す
assert add(-1, -1) == -2
def test_add_with_zero():
# ゼロを足すケースも大事
assert add(5, 0) == 5
これだけ。すごく短い。`test_`で始まる関数を書いて、その中で`assert`を使って「`add(2, 3)`の結果は`5`であるべき」と書くだけ。 JUnitみたいに、`assertEqual`とか専用のメソッドを覚える必要がないのが、個人的には楽。
フレームワークによる考え方の違い (JUnit vs pytest)
ちょっと調べてみたら、Javaでよく使われるJUnitとPythonのpytestでは、書き方だけじゃなくて、思想も少し違うみたいで面白い。 日本だとやっぱりJavaの情報が多いから、こういう違いを知っておくといいかも。
| 項目 | JUnit (Java) | pytest (Python) |
|---|---|---|
| 書き方の印象 | クラスベース。ちょっと「かっちり」してる感じ。 | シンプルな関数で書ける。始めやすい。 ボイラープレートコードが少ないっていうのは、こういうことか。 |
| アサーション(検証) | `assertEquals(5, result)` みたいな専用メソッドを使う。 | `assert result == 5` みたいに、普通のPythonの`assert`文。直感的。 |
| テストの発見 | 特定の命名規則(`@Test`アノテーションとか)が必要。明示的。 | `test_`で始まるファイルや関数を自動で見つけてくれる。楽ちん。 |
| セットアップ/後処理 | `@BeforeEach`, `@AfterEach` アノテーション。わかりやすいルール。 | 「フィクスチャ」っていう仕組みが強力らしい。まだよくわかってないけど、もっと柔軟なことができるっぽい。 |
どっちが良い悪いじゃないけど、pytestの手軽さは初心者にはありがたいかも。
でも、大変なこともある
もちろん、いいことばかりじゃない。デメリットもちゃんとある。
- 手間がかかる: 当然だけど、テストコードを書く時間は増える。 短期的には開発スピードが落ちると感じるかも。
- スキルが必要: どんなテストを書けばいいか考えるのは、結構スキルがいる。 境界値とか異常系とか、考えることは多い。
- メンテナンス: プロダクトコードを変えたら、テストコードも直さないといけない。これが地味に面倒くさい。
だから、なんでもかんでも100%テストを書く、っていうのは現実的じゃないかもしれない。 特に、UIとか、外部のDBに接続する部分とかは、テストが書きにくい。 まずは、ビジネスロジックの核となる部分から始めるのが良さそう。
まとめ、というか今の気持ち
単体テストは、完璧を目指すためのものじゃなくて、最低限の品質と、未来の開発者の安心を担保するためのもの、っていう感じかな。
最初は面倒だけど、一度あの「バグを早期発見できた」っていう快感を味わうと、やめられなくなるかもしれない。 これから書くコードには、少しずつでもテストを書いていこうと思う。
あなたのプロジェクトで、一番変更するのが怖い関数はどれですか?たぶん、そこが最初の単体テストの書きどころです。
