SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

Python - unittestで例外発生をテストする

小ネタです。

Python標準の単体テストツールunittestですが、テスト対象メソッドが例外を送出するかテストすることもできます。

その方法が他の言語とはちょっと違ったので、書いてみます。

バージョン

対象 バージョン
OS Windows 10 Pro 64bit
Python 3.7.0
Visual Studio Code 1.27.2
Python(拡張機能) 2018.8.0

テスト対象メソッド

簡単なコードを書きました。

  • テスト対象(bases.filesモジュール)
from os import path
import shutil

def copy(source: str, destination: str):
    """destination で指定したディレクトリに、ファイルをコピーします。"""

    if not path.exists(source):
        raise FileNotFoundError(source + " is not found.")
    
    if not path.exists(destination):
        raise NotADirectoryError()

    if not path.isdir(destination):
        raise NotADirectoryError()

    shutil.copy(source, destination)
            

destinationで指定したフォルダに、ファイルをコピーするだけのものです。

例外発生の検知

次はテストコードです。

まず、ご作法通り、unittestを継承したクラスを作成します。

そして、テストメソッド内で

import unittest as ut

import bases.files as f

class test_copy(ut.TestCase):
    def test_notexist_file(self):
        with self.assertRaises(FileNotFoundError):
            f.copy("aaa", "bbb")

のように書きます。

with self.assertRaises(FileNotFoundError):
    f.copy("aaa", "bbb")

の部分がテストです。

  • 例外発生部分を、with句とともにassertRaisesで括る
  • 発生を期待する例外は、assertRaisesに渡す
  • with句の中で例外を発生させる処理を呼び出す

の3点が必要です。

メッセージをテストする

あまり需要は無いと思いますが、例外が送出するメッセージもテストできます。

assertRaisesの戻り値を取得すると、その中にメッセージが入っているようです。

with self.assertRaises(FileNotFoundError) as er:
    f.copy("aaa", "bbb")
raise_except = er.exception
self.assertEqual(raise_except.args[0], "aaa is not found.")

デバッグしてargs[0]の中にメッセージが入っているのを確認しましたが、もっと良い方法があるかもしれません。

ほかにも、エラーコードを確認したりできるようです。

テストコード全文

import unittest as ut

import bases.files as f

class TestCopy(ut.TestCase):
    def test_notexist_file(self):
        with self.assertRaises(FileNotFoundError) as er:
            f.copy("aaa", "bbb")
        raise_except = er.exception
        self.assertEqual(raise_except.args[0], "aaa is not found.")

下記のように、テストには成功しています。フォルダ階層等は環境に依存します。

f:id:hiroronn:20181004085539p:plain

おわりに

たしか、C#の場合、テストメソッドに属性を付ける、という方法でテストできたと思います。

言語によって流儀は違いますが、テスト手段が用意されているので、自分でtry - exceptするような書き方はしないように注意したいです。