テストは大事だと分かっていても、受託開発では工数が限られます。
「全部書く」は非現実的なので、書けば必ず元が取れる場所から書いています。
1. 権限のテスト(最優先)
事故ったときの被害が最大なので、ここだけは必ず書きます。
class OrderAccessTest(TestCase):
def setUp(self):
self.a = User.objects.create_user("a", password="x")
self.b = User.objects.create_user("b", password="x")
self.order_a = Order.objects.create(user=self.a, total=1000)
def test_others_order_is_not_visible(self):
self.client.force_login(self.b)
res = self.client.get(f"/orders/{self.order_a.id}/")
self.assertEqual(res.status_code, 404)
def test_anonymous_is_redirected(self):
res = self.client.get(f"/orders/{self.order_a.id}/")
self.assertEqual(res.status_code, 302)
403 ではなく 404 を返すのがおすすめです。
403 だと「そのIDのデータは存在する」と教えることになります。
2. 金額計算のテスト
計算がズレると信用を失います。境界値を必ず入れます。
def test_tax_rounding(self):
self.assertEqual(calc_total(100, rate=0.1), 110)
self.assertEqual(calc_total(101, rate=0.1), 111) # 端数の丸め
self.assertEqual(calc_total(0, rate=0.1), 0)
3. 状態遷移のテスト
「キャンセル済みの注文を再度キャンセルできてしまう」系のバグは、
テストが無いと必ず後から出ます。
def test_cannot_cancel_twice(self):
order = Order.objects.create(status="cancelled")
with self.assertRaises(InvalidTransition):
order.cancel()
4. 主要画面が 200 を返すこと(スモークテスト)
網羅性は低いですが、費用対効果が最も高いテストです。
テンプレートの構文ミスや、参照している変数の消失を確実に捕まえます。
class SmokeTest(TestCase):
def test_public_pages(self):
for path in ["/", "/about/", "/magazine/"]:
with self.subTest(path=path):
self.assertEqual(self.client.get(path).status_code, 200)
subTest を使うと、どのパスで落ちたかが明確に出ます。
書かないと決めているもの
- 単純なモデルの getter / setter
- Django 本体の機能(ORM が保存できることのテストなど)
- 画面の見た目(CSS の当たり方)
ここに時間を使うと、本当に守るべき場所が手薄になります。
実行を習慣にする
python manage.py test --parallel --keepdb
--keepdb でDB作成をスキップすると、実行時間が大幅に短くなります。
速いテストしか習慣にはなりません。
まとめ
優先順位は「権限 → 金額 → 状態遷移 → スモーク」。
この4つだけでも、引き渡し後に発覚する事故はかなり減らせます。