3秒でわかる
空の入力や 1 件だけ、上限ぎりぎりの値など、想定の端にある入力のこと。普通の値では動くコードが落ちる場所で、テストで真っ先に確かめる対象になる。
もう少し詳しく
どういうものか
想定している入力の範囲の、端やそのすぐ外側にあたる入力や状態のことです。空の配列、要素が 1 件だけの配列、0 や負の数、扱える最大値、空文字列、null や undefined などが代表例です。
真ん中あたりの値では素直に動くコードが、端の入力だけで落ちる、という形で表面化します。書いた本人は真ん中の値しか試していないことが多いため、テストや他人のレビューで初めて見つかることも珍しくありません。
なぜ必要か
実際の障害の多くがここで起きるからです。商品が 1 件も無い日、まだ注文したことがない新規ユーザー、名前が空欄のまま送られたフォーム。開発中のテストデータには出てこないのに、本番では必ず現れる状況です。
境界を先に洗い出しておくと、コードを書く前に必要な分岐が決まるという効果もあります。「空のときは何を返すのか」を実装前に決めておけば、後から例外処理を継ぎ足して複雑になるのを避けられます。テストケースを作るときも、端の値を並べるだけで有効なケースが揃います。
具体例
平均点を出す関数を素直に書くと、要素が 0 件のときに壊れます。
def average(scores):
return sum(scores) / len(scores)
print(average([80, 60, 70])) # 70.0
print(average([])) # ZeroDivisionError端の入力を先に決めてから書き直すと次のようになります。
def average(scores):
if not scores:
return 0.0
return sum(scores) / len(scores)
# 端の入力を並べて確かめる
print(average([])) # 0.0 空
print(average([50])) # 50.0 1 件だけ
print(average([0, 0])) # 0.0 全部ゼロ
print(average([-10, 10])) # 0.0 負の数を含む空のときに 0 を返すのか、None を返すのか、例外を投げるのかは仕様の判断です。大事なのは、書く前にどれかを決めておくことです。
つまずきやすいところ
覚え方
「無い、1 つ、いっぱい」の 3 つを口癖にすると漏れが減ります。ここに「マイナス」と「未入力」を足せば、日常のコードで踏む端はおおむね網羅できます。