動作チェックスクリプト

このレッスンでできるようになること

家計簿の主要な関数が正しく動いているかを、assert で自動的に確かめるスクリプトを書けるようになります。

手で確かめるのは続きません

ここまで家計簿を何度も書き換えてきました。集計を内包表記に直し、保存を JSON にし、辞書を Expense クラスにしました。そのたびに画面に出して目で確かめていたはずです。

この確認のしかたには2つの弱点があります。1つは、直した場所と関係ないところが壊れても気付けないことです。もう1つは、面倒なのでだんだんやらなくなることです。

そこで確認そのものをコードにします。走らせるだけで全部見てくれるなら、書き換えるたびに実行できます。

assert は前提が崩れたら止まる

第5章で出てきた assert を思い出します。

assert total_amount(expenses) == 6130, "合計が合いません"

条件が真なら何も起きません。偽なら AssertionError が投げられ、後ろのメッセージが添えられます。「ここは必ずこうなっているはず」を1行で書ける道具です。

落ちて終わらせずに、結果を集める

assert をそのまま並べると、最初の1つが失敗した時点でプログラムが止まります。1件目が壊れているせいで、2件目以降が通るかどうか分からないまま終わってしまいます。

そこで AssertionError を捕まえて、次のチェックに進みます。

def check(label, body): try: body() except AssertionError as e: print(f"NG {label} {e}") return False print(f"OK {label}") return True

body関数そのものを受け取ります。第4章でやった「関数は値として渡せる」がここで効いています。呼び出しの結果ではなく、呼び出す前の関数を渡すのがポイントです。渡すときは check("合計金額", check_total) のように、括弧を付けずに名前だけを書きます。

try が最後まで通ったときだけ print("OK ...") に進むので、else を使わずにこの形でも書けます。finally を足せば、成功でも失敗でも最後にやりたい後始末を書けます。

何をチェックするか

チェックは「よくある入力」だけでは足りません。次の3種類をそろえておくと、たいていの崩れを拾えます。

  • ふつうの入力 — 4件の支出の合計が想定どおりか
  • 端の入力 — 空のリストを渡しても落ちずに0を返すか
  • 境目の入力 — 1000円以上を高額とするなら、ちょうど1000円が入るか

最後に「何件中何件が通ったか」を出しておくと、目で1行ずつ追わなくても状態が分かります。ここまで全部、第4章と第5章の道具だけで書けています。

要件

  1. total_amount(expenses) は amount の合計を返す
  2. category_totals(expenses) は Counter でカテゴリ別の合計を返す
  3. expensive(expenses, border) は amount が border 以上の支出の name を元の順で並べたリストを返す
  4. check(label, body) を書く。body を呼び、AssertionError を捕まえたら NG 行を、通ったら OK 行を表示する
  5. チェックは 合計金額 / カテゴリ別集計 / 空のリスト / 高額の抽出 の4つをこの順で行う
  6. OK の行は OK 合計金額 の形にする
  7. 最後の行に 4件中4件OKでした の形で結果をまとめる

入出力例

出力: "OK 合計金額 OK カテゴリ別集計 OK 空のリスト OK 高額の抽出 4件中4OKでした"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.py
学習モード

メモ

動作チェックスクリプト

⌘S で保存