Pythonで完全に理解するユニットテストの全手順5ステップ

Pythonユニットテストチュートリアルイメージ Python
この記事は約9分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

ユニットテストはソフトウェア開発の中でも重要な部分を占め、品質保証とバグの早期発見に役立ちます。

特にPythonは豊富なユニットテストライブラリが存在し、テスト駆動開発(TDD)を支えています。

本記事ではPythonでのユニットテストの全手順を5つのステップで理解することを目指します。

●Pythonとユニットテストとは

ユニットテストはソフトウェアの最小単位(ユニット)が正しく動作していることを確認するためのテスト手法です。

Pythonではこのユニットテストが非常に重要とされています。

○Pythonとは

Pythonは可読性が高く、コードが簡潔に書けるため、初心者からプロの開発者まで幅広く使われているプログラミング言語です。

さらに、Pythonにはユニットテストを支援するライブラリが多数存在します。

○ユニットテストとは

ユニットテストは、関数やメソッドといったソフトウェアの最小単位(ユニット)が期待通りに動作していることを確認するテスト手法です。

これにより、バグの早期発見や再発防止、リファクタリング時の安心感などが得られます。

●Pythonでのユニットテストの基本

Pythonでは、標準のunittestライブラリを使用してユニットテストを行います。

○Pythonの標準ユニットテストライブラリ: unittest

unittestはPythonの標準ライブラリで、JavaのJUnitに影響を受けたxUnit型のフレームワークです。

テストケースの作成からテストスイートの組み立て、テストランナーを用いたテストの実行まで、一連の流れをサポートします。

○サンプルコード1:簡単なunittestの使用方法

Pythonのunittestを使用した簡単なテストコードを紹介します。

import unittest

class TestCalc(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(1, 2), 3)

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

このコードでは、「add」関数が正しく足し算を行えるかを確認するテストケースを作成しています。

この例では、1と2を引数にadd関数を実行し、その結果が3になることを確認しています。

ここで、’assertEqual’はunittestが提供するアサーションメソッドの一つで、二つの引数が等しいことを確認します。

このコードを実行すると、テストが正しくパスするか(つまり、add関数が正しい結果を返すか)を確認できます。

●Pythonでユニットテストを書く際のベストプラクティス

ユニットテストを効果的に行うためには、次のようなベストプラクティスがあります。

○テストケースの作成

テストケースは、個々の機能が正しく動作しているかを確認するためのものです。

例えば、ある関数が期待通りの戻り値を返すか、適切なエラーを発生させるかなどを確認します。

○テストスイートの作成

テストスイートは、複数のテストケースをまとめて管理するためのものです。

テストスイートにより、関連するテストケースを一つのグループとしてまとめ、一括でテストを実行することが可能になります。

○テストランナーの使用

テストランナーは、テストケースまたはテストスイートを実行し、その結果を表示するためのものです。

unittestでは、コマンドラインからテストを実行するための簡易的なテストランナーが提供されています。

○サンプルコード2:テストケース、テストスイート、テストランナーの使用方法

テストケース、テストスイート、テストランナーの使用例を紹介します。

import unittest

class TestCalc(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(1, 2), 3)

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(TestCalc))
    suite.addTest(unittest.makeSuite(TestStringMethods))
    runner = unittest.TextTestRunner()
    runner.run(suite)

このコードでは、先程のadd関数のテストケースに加え、新たに文字列のupperメソッドのテストケースを追加しています。

これらのテストケースをテストスイートにまとめ、テストランナーを使って実行しています。

このコードを実行すると、全てのテストが一括で実行され、その結果が表示されます。

●Pythonでよく使われるユニットテストライブラリ:pytest

Pythonで広く使われているユニットテストライブラリの一つがpytestです。

pytestは、unittestよりもさらに強力な機能を提供し、よりシンプルなテストコードの記述を可能にします。

○pytestの基本的な使用方法

pytestは、アサーションを通常のPythonのassert文で書くことができ、エラーメッセージも自動的に生成されます。

また、テストケースは特殊なクラスやメソッドを作成するのではなく、単純に’test_’で始まる関数を作成すればよいため、コードがシンプルになります。

○サンプルコード3:pytestの使用方法

pytestを使用した簡単なテストコードを紹介します。

def test_add():
    assert add(1, 2) == 3

このコードでは、add関数が1と2を足して3になることを確認しています。

pytestを使ったテストはこのようにシンプルで、かつ強力なアサーションが可能です。

このコードを実行すると、テストが正しくパスするか(つまり、add関数が正しい結果を返すか)を確認できます。

●ユニットテストの注意点と対処法

ユニットテストを行う際には、次のような注意点があります。

○テストの独立性

各テストケースは独立して動作するべきです。

つまり、一つのテストケースが他のテストケースの結果に影響を与えてはなりません。

○テストカバレッジ

テストカバレッジは、テストがソフトウェアのどの程度をカバーしているかを示す指標です。

カバレッジが低いということは、テストされていないコードが存在する可能性があり、それがバグの原因になる可能性があります。

○リファクタリングとユニットテスト

リファクタリング(コードの整理)は、プログラムの外部から見た動作を変えずに内部のコードを改善する行為です。

ユニットテストは、リファクタリングにより機能が損なわれていないことを確認するのに役立ちます。

●Pythonでのユニットテストの応用例

Pythonでは、モックオブジェクトを使ったテストやフィクスチャを用いたテストなど、様々な応用的なテスト方法が存在します。

○モックオブジェクトを用いたテスト

モックオブジェクトは、実際のオブジェクトを模倣したもので、テスト対象のコードが外部リソース(例えば、データベースやネットワーク)に依存する場合に用いられます。

○サンプルコード4:モックオブジェクトの使用方法

モックオブジェクトを用いたテストのサンプルコードを紹介します。

from unittest.mock import MagicMock
import unittest

def is_even(n):
    return n % 2 == 0

class TestIsEven(unittest.TestCase):

    def test_is_even(self):
        mock = MagicMock(return_value=True)
        self.assertEqual(is_even(mock), True)

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

このコードでは、モックオブジェクトを作成し、その戻り値をTrueに設定しています。

これにより、is_even関数が正しい結果を返すことを確認できます。

このコードを実行すると、モックオブジェクトが正しく動作し、テストがパスすることを確認できます。

○フィクスチャを用いたテスト

フィクスチャは、テストを行うための準備や後片付けを行うためのコードのことを指します。

pytestでは、フィクスチャを簡単に作成し、テスト間で再利用することができます。

○サンプルコード5:フィクスチャの使用方法

pytestのフィクスチャを使用したテストのサンプルコードを紹介します。

import pytest

@pytest.fixture
def input_value():
    return 5

def test_divisible_by_5(input_value):
    assert input_value % 5 == 0

このコードでは、フィクスチャinput_valueを作成し、その値をテストケースに注入しています。

このようにフィクスチャを用いることで、複数のテストで共通の準備や後片付けを行うことが容易になります。

このコードを実行すると、フィクスチャが正しく動作し、テストがパスすることを確認できます。

●ユニットテストのカスタマイズ

Pythonのユニットテストライブラリは、アサーションのカスタマイズを可能にします。

これにより、特定のテストシナリオに対するチェックをより直感的で読みやすい形式で記述することができます。

○カスタムアサーションの作成

unittestライブラリには、アサーションをカスタマイズする機能が含まれています。

これにより、特定の条件をチェックするための独自のアサーションを作成することができます。

○サンプルコード6:カスタムアサーションの作成方法

カスタムアサーションを作成するサンプルコードを紹介します。

import unittest

class TestCustomAssertion(unittest.TestCase):

    def assertIsEven(self, n):
        self.assertEqual(n % 2, 0, 'The number is not even')

    def test_custom_assertion(self):
        self.assertIsEven(2)

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

このコードでは、新たなアサーションメソッドassertIsEvenを定義し、このメソッドを用いて数字が偶数であることをアサートしています。

このコードを実行すると、カスタムアサーションが正しく動作し、テストがパスすることを確認できます。

まとめ

Pythonでのユニットテストは、ソフトウェアの品質を確保するための重要な手段であり、unittestやpytestなどのライブラリを活用することで効率的にテストを行うことができます。

本記事では、Pythonでのユニットテストの基本から応用、カスタマイズまでを5つのステップで解説しました。

この知識をもとに、自身のコードの品質向上に役立てていただければ幸いです。