【初心者〜現場で活躍まで】挫折しないPython勉強方法もっと知る

【基礎編】Pythonで単体テスト:unittestの使い方

Pythonでの単体テストのやり方を、基礎から解説をします。具体的には、unittestの使い方を解説します。

エソラ

unittestはPython標準のテストツールです。

この記事を読めば、Pythonで単体テストが書けるようになります。

この記事を書いた人

エソラ
  • エンジニア歴10数年
  • SIerでDX推進を仕事に
  • Python、AWSを使ったアーキテクチャ設計・アプリ開発が得意
  • 30代、2児の父でサウナ好き
  • [icon-class=”icon-twitter”]Twitter

単体テストを書くメリット・デメリットは、以下の通りです。

メリットデメリット
一度作れば、自動テストができて、作業量が激減する
リファクタリング(一度書いたコードの修正)がしやすくなり、保守性が上がる
デグレーション(修正時に、意図しない不具合が発生)を防げるので、かっこ悪い謝罪が少なくなる
学習コストが高い
テストコードを書く工数が余計にかかる
テストしやすいように、コードを修正する場合がある
単体テストを書くメリット・デメリット

デメリットはありますが、単体テストのコードを書けると、デメリットを上回る幸せな結果を得られます。

基礎から解説しますので、この機会に単体テストのコードを書けるようになりましょう!

unittestと互換性があり、もう少し書きやすいpytestの使い方を解説した記事もあります。

Pythonの勉強方法は、まとめ記事があります。

Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。

目次

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

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

単体テストを実装する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

unittestはPythonに標準で入っているため、pipでインストールする必要がありません。

簡単ですね!

ステップ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ステップとは以下でした。

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

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

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

またPython標準のunittestの他に、テストツールにはpytestもあります。

pytestの方が直感的に使えますので、そちらを学びたい場合、以下がおすすめです。

pytestの使い方を解説した記事

書籍なら、以下がおすすめ

書籍で唯一、Pythonの単体テストが勉強できる評判の技術書。第2版が出て、更にパワーアップしました。

著:Brian Okken, 翻訳:株式会社クイープ, 監修:株式会社クイープ, 監修:安井 力
¥2,970 (2022/11/24 04:05時点 | Amazon調べ)

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

役に立った、面白かったと思ったら、SNSでシェアしてくれると嬉しいです。

エソラ

もし分からないことがあれば、お問い合わせTwitterにご連絡をいただけると嬉しいです。(Twitterの方が返信早いかも…)

\ 更新の励みになるので、ポチッとしてね /

エソラ

他にもスキルアップやキャリアアップの役に立つ情報が満載です。他の記事も読んで、ゆっくりしていってね!

この記事が気に入ったら
フォローしてね!

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

コメント

コメント一覧 (2件)

コメントする

目次