【Python入門】基礎から理解するユニットテスト入門

みなさんはPythonでユニットテストを書いていますか?

  • プログラミングでテストって何?
  • ユニットテストって何で書くの?

などの疑問もでてくるかと思います。

そのような方に向けて、この記事では以下のようなテストの基本から実際にユニットテストの書き方について解説していきます。

  • ユニットテストとは
  • ユニットテストの書き方

ユニットテストの基本からわかりやすく解説していますので、ぜひ参考にしてくださいね!

本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。

→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説

なお、その他のPythonの記事についてはこちらにまとめています。

目次

ユニットテストとは

プログラミングにおけるテストとは、みなさんがプログラミングをして作成したアプケーションなどが正しく動作することを保証するためのプログラムになります。

テストコードと言ったりもします!

テストには様々な種類がありますが今回紹介するユニットテストとは、関数やメソッドなどのプログラム内で比較的小さな単位に区切って行うテストになります。

関数やメソッド(ユニット)ごとに区切ってテストすることで個々の機能ごとにしっかり検証できますね!

ユニットテストを書いてみよう!

ユニットテストの書き方

それではユニットテストを書いてみましょう!

まずテストに使用するサンプルのプログラムを書いていきます。

二つの引数arg1とarg2を受け取り、足した結果を返す関数plusを定義します!

plus.py

def plus(arg1, arg2):
    return arg1 + arg2

次に先程書いた関数plusをテストするためのユニットテストを書いていきましょう!

ユニットテストを書く際のポイントは以下になります。

  • unittest.TestCaseを継承したクラスにする
  • 作成するクラスのメソッド名は、test_で始めた名前にする

それでは、上記のポイントに注意してユニットテストのコードを書いていきましょう!

まず先頭でunittestとテストするplus関数をインポートしましょう!ポイントのunittest.TestCaseを継承したクラスを作成し、メソッド名はtest_plusとします!

変数actual_resultには、関数plus(1, 1)の結果を代入しておきます。そしてunittest.TestCaseを継承したことにより、テストで使用できる便利なassertメソッドが使えるようになっています。

self.assertEqual()を使用して、変数actual_resultに格納した関数plus(1, 1)の結果が2であるかを確認しています!

test_plus.py

import unittest
from plus import plus


class TestPlus(unittest.TestCase):
    def test_plus(self):
        actual_result = plus(1, 1)
    
        self.assertEqual(actual_result, 2)

ユニットテストの実行方法

それでは、作成したテストを実行していきましょう!

以下のコマンドを実行してテスト結果を確認してみましょう!

$ python -m unittest test_plus.py

実行結果

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

このように、関数plus(1, 1)の結果が期待した値2と等しいため、OKと表示され、テスト結果が成功していることがわかります!

では、試しにtest_plus.pyの最終行にあるassertEqualの第二引数を3に変えて、テストを実行してみましょう!

test_plus.py(最終行のみ)

        self.assertEqual(actual_result, 3)

このように、期待した値と一致しない場合は、テスト失敗となります。

$ python -m unittest test_plus.py

実行結果

F
======================================================================
FAIL: test_plus (test_plus.TestPlus)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/myhome_dir/python_unittest/test_plus.py", line 9, in test_plus
    self.assertEqual(result, 3)
AssertionError: 2 != 3

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

色々なassertを使ってみよう!

それでは実際に色々なテストメソッドを試してみてテストに慣れていきましょう!

テストする関数はこちらに用意しました。このサンプルコードを使用してテストをしていきましょう!

func.py

import re
import random


def extract_char(char):
    start = random.randint(0, 9)
    end = random.randint(start, 9)
    return char[start:end]


def remove_number(char):
    return re.sub('([0-9]*)', '', char)


def get_random_list(num):
    l = []
    l.append(9)
    for _ in range(num-1):
        l.append(random.randint(1, 9))
    return l


def is_upper(char):
    return char.isupper()


def get_two_plus_number(num):
    return num + 2

assertEqual/NotEqual

それでは、assertEqual/NotEqualを使用したテストをやっていきましょう!

func.pyをテストするためのtest_func.pyを作成し、テストを実行していきます。

まず1つ目のテストする関数remove_numberは、引数として渡した文字列の中に含まれている数値を除外してくれる関数になります。2つ目の関数extract_charは、引数として渡した文字列を1〜10文字の中でランダムで切り出してくれる関数になります。

では、これらの関数をそれぞれテストしていきましょう!

test_remove_numberメソッドでは、assertEqualを使用してremove_number(‘1テ2ス3ト4’)の結果が’テスト’となっているか確認しています。

test_extract_factorメソッドでは、assertNotEqualを使用してextract_char(‘abcdefghijklmnopqrstuvwxyz’)の結果が元の ‘abcdefghijklmnopqrstuvwxyz’とは異なっていることを確認しています。

test_func.py

import unittest
from func import remove_number
from func import extract_char


class TestEqualNotEqual(unittest.TestCase):
    def test_remove_number(self):
        actual_result = remove_number('1テ2ス3ト4')
        self.assertEqual(actual_result, 'テスト')

    def test_extract_factor(self):
        actual_result = extract_char('abcdefghijklmnopqrstuvwxyz')
        self.assertNotEqual(actual_result, 'abcdefghijklmnopqrstuvwxyz')

以下のコマンドを実行してテストが正常に実行されることを確認しましょう!

$ python -m unittest test_func.py 
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

assertTrue/False

次はassertTrue/Falseを使用したテストの方法を確認していきましょう!テストする関数is_upperは、引数として渡した文字列が全部大文字かどうかを真偽値で判定してくれます!

こちらもfunc.pyをテストするためのtest_func.pyを作成し、テストを実行していきます。

それではテストのメソッドを見ていきましょう!

test_is_upper_trueメソッドでは、assertTrueを使用して、関数の結果がTrueになることを確認しています。

test_is_upper_falseメソッドでは、assertFalseを使用して、関数の結果がFalseになることを確認しています。

test_func.py

import unittest
from func import is_upper


class TestTrueFalse(unittest.TestCase):
    def test_is_upper_true(self):
        actual_result = is_upper('UNIT TEST')
        self.assertTrue(actual_result)

    def test_is_upper_false(self):
        actual_result = is_upper('Unit Test')
        self.assertFalse(actual_result)

以下のコマンドを実行してテストが正常に実行されることを確認しましょう!

$ python -m unittest test_func.py 
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

assertIn/NotIn

次はassertIn/NotInの使い方を確認していきましょう!テストする関数get_random_listは、0は含まず、9を必ず含む、9個のリストを作成してくれます。

こちらもfunc.pyをテストするためのtest_func.pyを作成し、テストを実行していきます。

それではテストのメソッドを見ていきます!

test_exclude_multiples_inメソッドでは、assertInを使用して、9の値が含まれていることを確認しています!

test_exclude_multiples_notinメソッドでは、assertNotInを使用して、0の値が含まれていないことを確認しています!

test_func.py

import unittest
from func import get_random_list


class TestInNotIn(unittest.TestCase):
    def test_exclude_multiples_in(self):
        actual_result = get_random_list(5)
        self.assertIn(9, actual_result)

    def test_exclude_multiples_notin(self):
        actual_result = get_random_list(5)
        self.assertNotIn(0, actual_result)

以下のコマンドを実行してテストが正常に実行されることを確認しましょう!

$ python -m unittest test_func.py 
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

assertGreater(Equal)/Less(Equal)

次はassertGreater/Lessの使い方を確認していきましょう!

こちらもfunc.pyをテストするためのtest_func.pyを作成し、テストを実行していきます。

テストする関数get_two_plus_numberは、引数に与えた数に+2して返してくれる関数です。サンプルコードで使用しているassertメソッドの使い方はこちらになります。

  • assertGreater(a, b)

a > bであることを確認できます。

  • assertGreaterEqual(a, b)

a >= bであることを確認できます。

  • assertLess(a, b)

a < bであることを確認できます。

  • assertLessEqual(a, b)

a <= bであることを確認できます。

test_func.py

import unittest
from func import get_two_plus_number


class TestGreaterLess(unittest.TestCase):
    def test_get_two_plus_number_greater(self):
        actual_result = get_two_plus_number(5)
        self.assertGreater(actual_result, 5)

    def test_get_two_plus_number_less(self):
        actual_result = get_two_plus_number(5)
        self.assertLess(actual_result, 10)

    def test_get_two_plus_number_greaterequal(self):
        actual_result = get_two_plus_number(5)
        self.assertGreaterEqual(actual_result, 7)

    def test_get_two_plus_number_lessequal(self):
        actual_result = get_two_plus_number(5)
        self.assertLessEqual(actual_result, 7)

以下のコマンドを実行してテストが正常に実行されることを確認しましょう!

$ python -m unittest test_func.py 
....
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

まとめ

いかがでしたでしょうか。

今回は、Pythonのユニットテストについて学習しました!
assertEqual/NotEqual
ユニットテストはプログラミング初学者の方の場合はあまり馴染みがないですよね!最初はなかなかとっつきにくいかもしれないですが、実務では必要な知識なので頑張って覚えていきましょう!

普段の勉強で作成したプログラムのテストを書くように心がけるとプログラムの品質も保てるので是非チャレンジしていきましょう!

なお、今Pythonを学習している方は以下の記事もどうぞ。

はじめてPythonを使う方でもわかりやすいように、Pythonでできることやその学習法などを中心にまとめています。

復習にも使えると思いますので、ぜひ一度ご覧になってみてくださいね。

Python 入門完全攻略ガイド

この記事を書いた人

インフラエンジニア→プログラマー。趣味は3歳の子供にPCの使い方、タイピングを教えること。業務ではPython, PHP, Javaなどやってます。

目次