アクセスありがとうございます!次は「とあるエンジニアのエソラゴト」で検索して頂けると嬉しいです!

【Python入門】単体テストのやり方【基礎編】

どうも、当ブログ(とあるエンジニアのエソラゴト)を運営している、エンジニアのエソラ(@ya6madev)です。

普段はSIer企業でDXとかAI開発をしながら、自社サービスの開発をしています。

今回はPythonで単体テスト(ユニットテスト)をコーディングする方法について、基礎的なところから解説をします。

単体テストコードを実装出来るようになると、以下のようなメリットを受けることができます。

  • 自動でテストができるようになるので、一度作ってしまえば作業量が激減する。
  • リファクタリング(一度書いたコードの修正)がやりやすくなるので、洗練されたかっこいいコードに思い切って修正ができる。
  • デグレーション(修正によって、意図しない箇所に不具合が起こること)を防げるので、かっこ悪い謝罪をする必要がなくなる。

単体テストのコードを書けるようになることで、このような幸せな結果を得ることができます。

基礎的なところから解説をしていきますので、是非、ここで単体テストのコードを書けるようになりましょう!

もし、もっとPythonの文法や便利な使い方について、効率的に学びたいという方がいたら以下の記事がおすすめです。

Pythonで単体テストを実装する4ステップ

Pythonで単体テストを実装するためには、以下の4ステップが必要です。

  1. unittestをインポートする。
  2. unittest.TestCaseを継承して、クラスを作成する。
  3. テスト用の関数を作成する。
  4. assertEqual等のAssertメソッドを利用して、テスト内容を記述する。

以下からは4ステップの詳細について、FizzBuzzのプログラムを例に解説をしていきます。

テスト対象のコードは以下となります。

def fizzbuzz(num):
    if num % 15 == 0:
        return 'FizzBuzz'
    elif num % 3 == 0:
        return 'Fizz'
    elif num % 5 == 0:
        return 'Buzz'
    else:
        return str(num)

ステップ1:unittestをインポート

ステップ1では、単体テストのライブラリである「unittest」をインポートします。

以下のようにunittestをインポートするだけで、単体テストのコードが書けるようになります。

import unittest

簡単ですね!

ステップ2:unittest.TestCaseを継承して、クラスを作成

ステップ2では、インポートしたunittestからTestCaseを継承して、クラスを作成します。

慣例として、クラス名の頭にはTestと付けることが多いです。

例としては、以下のような感じです。

import unittest

class TestFizzBuzz(unittest.TestCase):
    # 以下にテスト用の関数を書く

ステップ3:テスト用の関数を作成

単体テストをするにはテスト用に関数を作成します。

関数名の頭には、「test_」を付けます。

例としては以下のようになります。

import unittest

class TestFizzBuzz(unittest.TestCase):

    def test_fizzbuzz_fizz(self):
        # ここにテスト内容を書く

ステップ4:関数にテスト内容を記述

ステップ4では、関数の中にテスト内容のコードを書いていきます。

具体的には、assertEqual等のAssertメソッドを利用して、期待値と実際の値を比較します。

サンプルコードは以下となります。

import unittest

class TestFizzBuzz(unittest.TestCase):

    def test_fizzbuzz_fizz(self):
        """3の倍数のテスト."""
        self.assertEqual(fizzbuzz(9), 'Fizz')

    def test_fizzbuzz_buzz(self):
        """5の倍数のテスト."""
        self.assertEqual(fizzbuzz(55), 'Buzz')

    def test_fizzbuzz_fizzbuzz(self):
        """15の倍数のテスト."""
        self.assertEqual(fizzbuzz(45), 'FizzBuzz')

    def test_fizzbuzz_not_fizzbuzz(self):
        """3と5の倍数以外のテスト."""
        self.assertEqual(fizzbuzz(11), '11')

if __name__ == "__main__":
    unittest.main()

以下のようにassertEqualメソッドを使用して、テストをしています。

    def test_fizzbuzz_fizz(self):
        """3の倍数のテスト."""
        self.assertEqual(fizzbuzz(9), 'Fizz')

第1引数は実際の値、第2引数には期待値を渡します。

Assertメソッドの一覧については、以下を参考にしてください。

メソッド確認事項
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) is True
assertFalse(x)bool(x) is False
assertIs(a, b)a is b
assertIsNot(a, b)a is not b
assertIsNone(x)x is None
assertIsNotNone(x)x is not None
assertIn(a, b)a in b
assertNotIn(a, b)a not in b
assertIsInstance(a, b)isinstance(a, b)
assertNotIsInstance(a, b)not isinstance(a, b)
引用元:『https://docs.python.org/ja/3.7/library/unittest.html#assert-methods』

単体テストコードを実行

ここまでで、単体テストのコードが書けました。

今回作成したコードの全体像はこちらです。

import unittest

def fizzbuzz(num):
    if num % 15 == 0:
        return 'FizzBuzz'
    elif num % 3 == 0:
        return 'Fizz'
    elif num % 5 == 0:
        return 'Buzz'
    else:
        return str(num)

class TestFizzBuzz(unittest.TestCase):

    def test_fizzbuzz_fizz(self):
        """3の倍数のテスト."""
        self.assertEqual(fizzbuzz(9), 'Fizz')

    def test_fizzbuzz_buzz(self):
        """5の倍数のテスト."""
        self.assertEqual(fizzbuzz(55), 'Buzz')

    def test_fizzbuzz_fizzbuzz(self):
        """15の倍数のテスト."""
        self.assertEqual(fizzbuzz(45), 'FizzBuzz')

    def test_fizzbuzz_not_fizzbuzz(self):
        """3と5の倍数以外のテスト."""
        self.assertEqual(fizzbuzz(11), '11')

if __name__ == "__main__":
    unittest.main()

コードが分かりやすいように、テスト対象の処理とテストコードを同じファイルに記述しています。

さて、ここまで来たら単体テストコードを実行してみましょう。

以下のようにコマンドを打つと、テストが実行されます。

$ python test_fizzbuzz.py 
....
----------------------------------------------------------------------
Ran 4 tests in 0.001s

OK

4つのテストが全てパスしていることが分かります。

次は、わざとテストコードを間違えてみます。

    def test_fizzbuzz_fizz(self):
        """3の倍数のテスト."""
        self.assertEqual(fizzbuzz(2), 'Fizz')

すると、以下のようになりました。

$ python test_fizzbuzz.py 
.F..
======================================================================
FAIL: test_fizzbuzz_fizz (__main__.TestFizzBuzz)
3の倍数のテスト.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_fizzbuzz.py", line 19, in test_fizzbuzz_fizz
    self.assertEqual(fizzbuzz(2), 'Fizz')
AssertionError: '2' != 'Fizz'
- 2
+ Fizz


----------------------------------------------------------------------
Ran 4 tests in 0.001s

期待値と実績値が違うため、エラーとなっていることが分かります。

まとめ – Pythonで単体テストを書く

ここまで、Pythonで単体テストを書く方法を4ステップに分けて記載していきました。

4ステップとは以下でした。

  1. unittestをインポートする。
  2. unittest.TestCaseを継承して、クラスを作成する。
  3. テスト用の関数を作成する。
  4. assertEqual等のAssertメソッドを利用して、テスト内容を記述する。

単体テストコードが書けるようになれば、コーティングをする効率も品質を上がり、エンジニアとして他の人よりも一歩先にレベルアップすることができます。

ぜひとも、単体テストのコーディング方法をしっかりとマスターして下さい!

ここまでお読み頂き、ありがとうございました。

もし、「面白かった」、「参考になった」という方がいましたら、以下のソーシャルボタンからシェア頂けると泣いて喜びます!!

エソラ
エソラ
またブログランキングにも参加しています。
よろしければ、ポチッとお願いしまーす!

それでは、良いエンジニアライフをお過ごし下さい!

最新情報をチェックしよう!