第6回|Pythonのテストを実行して修正を確かめる|unittest を確認コマンドとして使う|UNIX Cafe

* 当サイトでは、コンテンツの一部に広告を掲載しています。

System Note $ cat /proc/ai-disclosure

本記事の構成および論理分析にはAI(人工知能)を使用しています。情報の正確性は、システム管理者(UNIXユーザー)による手動検証済みです。

第6回|Pythonのテストを実行して修正を確かめる|unittest を確認コマンドとして使う|UNIX Cafe

CLIで開発する | 第6回

アプリが動いたからといって、すべての処理が正しいとは限りません。画面を目で見るだけでは気づきにくい間違いもあります。

今回は、Python標準の unittest を使い、注文金額の計算ミスを確認します。最初はテストの書き方を詳しく覚えるより、「期待した結果になっているかを確かめるコマンド」と考えると入りやすいです。

この記事で学べること

  • python3 -m unittest でテストを実行する方法
  • 失敗結果から期待値と実際の値を読む方法
  • grep で計算処理を探す方法
  • 修正後にテストとアプリ実行の両方で確認する流れ
目次

練習を始める前の準備

第5回まで使った unix_cafe_order ディレクトリで作業を再開します。別の場所にいる場合は、作業の前に unix_cafe_order に移動してください。今回も、修正前の不具合を自分で作ってから学習を始めます。

cat src/calculator.py

まず最初に、cat を使って現在のファイルの中身を確かめます。

def calculate_total(orders):
    total = 0
    for order in orders:
        total += int(order["price"]) * int(order["quantity"])
    return total

内容が確認できたら、次に vi でファイルを開き、テストでエラーを起こすためにコードを変更します。

vi src/calculator.py

数量を掛けている * int(order["quantity"]) を削除し、次の形にします。入力できたら、Esc:wqEnter の順に操作して保存します。

def calculate_total(orders):
    total = 0
    for order in orders:
        total += int(order["price"])
    return total

今回は練習用として、不具合がある状態を開始地点にします。あとで修正前と修正後の違いを確認できるように、この状態をGitへ記録しておきます。

git add src/calculator.py
git commit -m "Prepare calculation practice"

まずテストを実行する

ここからは、テストを使って計算ミスを確認します。テストとは、プログラムが期待どおりに動いているかを確かめるための小さな確認作業です。

今回のプロジェクトには、tests ディレクトリの中に test_calculator.py というテスト用ファイルがあります。このファイルには、「注文金額の計算結果が正しいか」を確認するための内容が書かれています。

このテストでは、アプリ全体ではなく、合計金額を計算する calculate_total 関数だけを確認しています。

テスト用の注文データは、価格450円、数量2という1件だけです。そのため、期待する結果は900円になります。小さなデータで確認することで、数量が計算に入っているかを見やすくしています。

このコマンドは、Python の unittest というテスト機能を使って、テストを実行するためのものです。

python3 -m unittest discover -s tests -v

discover は、テスト用のファイルを自動で探す指定です。-s tests は、探し始める場所を tests ディレクトリにする指定です。最後の -v は、実行結果を詳しく表示するための指定です。

コマンドを実行すると、Python は tests ディレクトリの中を見に行き、test_calculator.py を見つけて、その中のテストを実行します。

ただし、今のコードは数量を計算に入れていない状態です。そのため、テストを実行すると、次のように失敗します。実際の画面にはこの前後にもう少し詳しい情報が表示されますが、注目するのは次の行です。

AssertionError: 450 != 900

FAILED (failures=1)

価格450円の商品が2つあるなら、期待する合計は900円です。しかし、実際の結果は450円になっています。数量が計算に入っていない可能性があります。

grep で関係する場所を探す

原因を探すために、まずは計算に関係しそうな言葉を手がかりにします。

このプロジェクトの注文データでは、価格を price、数量を quantity という名前で扱っています。そこで、まずは price という言葉を手がかりに、計算に関係しそうな場所を探してみます。

grep -Rni "price" src tests

grep は、ファイルの中から指定した言葉を探すコマンドです。ここでは "price" を探しています。

src tests と書いているので、アプリ本体が入っている src ディレクトリと、テストが入っている tests ディレクトリの両方を探します。

実行すると、次のように price を含む行が表示されます。

src/calculator.py:4:        total += int(order["price"])
tests/test_calculator.py:14:        orders = [{"price": "450", "quantity": "2"}]

1行目は、実際に合計金額を計算している場所です。src/calculator.py の4行目に、price を使った計算処理があります。

2行目は、テスト側で使っている注文データです。ここでは、価格が 450、数量が 2 になっています。

本来なら、450円の商品が2つあるので、合計は 450 × 2 で 900円になるはずです。しかし、現在の計算処理は int(order["price"]) だけを足しているため、数量を表す quantity が使われていません。

そのため、次は quantity を掛ける形に修正します。

vi で計算処理を直す

原因の見当がついたので、次は実際の計算処理を修正します。

計算処理は src/calculator.py にありましたので、vi でこのファイルを開きます。

vi src/calculator.py

現在の計算式は、価格を表す price だけを合計に足している状態です。

        total += int(order["price"])

注文金額を正しく計算するには、価格 price に、数量 quantity を掛ける必要があります。そこで、計算式を次のように修正します。

この修正により、たとえば価格が450円で数量が2の場合、450 × 2 として計算されます。つまり、合計は900円になります。

計算式を次のように修正します。

        total += int(order["price"]) * int(order["quantity"])

こちらが修正したスクリプトです。

def calculate_total(orders):
    total = 0
    for order in orders:
        total += int(order["price"]) * int(order["quantity"])
    return total

Pythonはインデント(行頭のスペース)で、処理のまとまりを表しています。

ですから、修正するときに、次のように書くとエラーになります。

def calculate_total(orders):
    total = 0
    for order in orders:
total += int(order["price"]) * int(order["quantity"])
    return total

インデントは半角スペース4つが1段分です。今回の行は fordef の2段ぶんネストしているので、半角スペース8つが必要になります。

テストとアプリ表示の両方で確認する

python3 -m unittest discover -s tests -v

テストが成功すると OK と表示されます。

Ran 1 test in 0.000s

OK

もう一度 app.py を実行します。

python3 src/app.py

一方、app.py は、テスト用の1件だけのデータではなく、data/orders.csv に入っている注文データを読み込みます。

item,price,quantity
coffee,450,2
toast,380,1
cake,520,1

テストでは450円の商品が2つなので期待値は900円でしたが、data/orders.csv には coffee、toast、cake の3件が入っています。そのため、アプリを実行すると3件分の合計である1800円が表示されます。

Order total: 1800 yen

テストは何を助けるのか

テストは、変更後の確認を繰り返しやすくしてくれます。画面表示を見る確認と、期待した計算結果になっているかを見る確認は、役割が少し違います。両方を行うと、修正への納得感が増します。

手を動かすミニ練習

  1. 失敗結果から、期待値と実際の値を読み取る
  2. grep -Rni "quantity" src tests で数量に関係する場所を探す
  3. 修正後にテストとアプリ実行を続けて行う

練習を終えた後の片付け

修正した src/calculator.py はコミットせず、そのまま残してください。

次の回で、続きの作業を行います。

次回予告

次回は、確認できた修正をGitで記録します。status diff add commit log を開発の流れに接続します。

さらに学びたいあなたへ

用途ごとに選ぶ Linux のおすすめ本

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

Created by UNIX Cafe

目次