Pythonのテスト mock.assert

Python学習【365日チャレンジ!】196日目のマスターU(@Udemy11)です。

知り合いの方が「上司が馬鹿すぎてやってられない」なんてことを言ってたので、ちょっと愚痴を聴いてあげました。

ドラマ半沢直樹でもありましたが、組織では稟議を回して上役の承認をもらいますが、その稟議書に難癖をつけてなかなか承認しない上司がいるらしいです。

承認しない理由というのが、稟議書の内容がきちんとしていないからではなく、文章の書き方が気に入らないとか書式がおかしいというどうでもいいような話で修正しろと言ってくるらしいです。

例えば、「この案について〜中略〜お伺いします。」という文章があったとすると、「この案について〜中略〜伺います。」としなければならないだとか、案が2つあったときは、「2案」ではなく、「案の2」にしなければならないだとか、ほんとど〜でもいいようなところに注文をつけてくるらしいです。

基本、稟議書ってどのようなことをどのようにするかがわかればいいので、多少の物言いは問題ないとは思いますが、その人の中では、答えが1つしかないんでしょうね。

日本教育で育った典型的な上司のようですね。

このようなことは日本中で起こっているんでしょうけど、会社員ならうまくストレスにならない方法を身に着けておいたほうが良さそうです。

それでは、今日もPython学習をはじめましょう。

昨日の復習

昨日は外部サービスの処理をして取得する値を仮に代入できるmockを学習しました。

外部サービスがまだできていないけど、どんな返り値が返ってくるかわかっている場合は、外部の処理を待つまでもなく、mockを使えば想定値を入れてテストをすることができました。

詳細については、こちらの記事をごらんください。

今日は、mockの中で使うmock.assertを学習します。

mock.assert

昨日は、mockを使って外部サービスで取得する値を擬似的に取得しました。

昨日のテストだけだと、擬似的に値を代入しているだけで、メインのコードで外部サービスの値を取得する関数がきちんと呼ばれているかが確認できていないので、関数が呼ばれているかどうかを確認するためのものがmock.assertです。

mock.assertを使うことで、きちんと関数が呼ばれたか、1回だけ呼ばれているか、引数を他の関数に渡せているかなどを確認することができます。

これらを確認するためのコードを確認します。

salary.py

メインのファイルは昨日のsalary.pyと同じです。

import requests

class BonusApi(object):
    def bonus_price(self, year):
        req = requests.get('http://localhost/bonus', params={'year': year})
        return req.json()['price']
    
class Salary(object):
    def __init__(self, base=50, year=2020):
        self.bonus_api = BonusApi()
        self.base = base
        self.year = year
        
    def cal_salary(self):
        bonus = self.bonus_api.bonus_price(year=self.year)
        return self.base + bonus

test_salary.py

続いてテストファイル(test_salary.py)に、何行かコードを追加します。

import unittest

from unittest.mock import MagicMock

import salary


class TestSalary(unittest.TestCase):
    def test_cal_salary(self):
        s = salary.Salary()
        s.bonus_api.bonus_price = MagicMock(return_value=100)
        self.assertEqual(s.cal_salary(), 150)
        s.bonus_api.bonus_price.assert_called()
        s.bonus_api.bonus_price.assert_called_once()
        s.bonus_api.bonus_price.assert_called_with(year=2020)
        s.bonus_api.bonus_price.assert_called_once_with(year=2020)
        self.assertEqual(s.bonus_api.bonus_price.call_count, 1)

ハイライトしている13行目から17行目が付け加えたコードです。

それぞれの次のテストをおこないます。

  • 13行目:メインファイルのbonus_api.bonus_priceが呼ばれたかどうかをテスト
  • 14行目:メインファイルのbonus_api.bonus_priceが1度だけ呼ばれたかどうかをテスト
  • 15行目:メインファイルのbonus_api.bonus_priceの引数year2020かどうかをテスト
  • 16行目:14行目と15行目を一度でテスト
  • 17行目:メインファイルのbonus_api.bonus_priceが呼ばれ方回数が1であるかどうかをテスト

どれも問題がなければ普通にテストをパスします。

デバッガを使って実行してみてもテストがきちんと実行されているのがわかりますが、たとえば15行目のyear=2020year=2021にすれば、テストは失敗します。

Pythonのテスト 擬似的に結果を代入してテストができるmock.assert

コードはたくさん

Pythonだけじゃなく、プログラミングの学習は、すべての内容を網羅することはできません。

すべての内容をマスターするには、公式ドキュメントをすべて頭に入れる必要がありますが、実際に使わないコードもたくさんあります。

現在、私が学習中の酒井さんの講座では、実際のPythonプログラミングで使用頻度の高いものに絞ってレクチャーしてくれているので、非常に効率よくPythonを学習することができます。

Udemy講師 酒井さん プログラミング Python

Pythonの入門編から応用編まで幅広く網羅した内容になっていいるので、初心者の方から中級者の方まで学べることがたくさんあるので、ぜひ受講してみてください。

講座をひととおり学習し、実際に使うところを復習したり、ネットなどで補完してPythonのスキルをつけましょう!

それでは明日もGood Python!