Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで関数が例外を発生させることをテストする方法(unittestのassertRaises活用)

Pythonのユニットテストでは、「関数が期待どおりの例外を投げない場合にのみ失敗する」というテストを書くことができます。これは、型安全性やエラーハンドリングの正しさを検証するうえで非常に重要な手法です。

ここでは、Python標準ライブラリの unittest を使って、関数が例外をスローすることを確認する方法を解説します。

例外発生をテストするサンプルコード

たとえば、整数と文字列を足し合わせると TypeError が発生することを確認するコードは、以下のように書けます。Pythonシェルにそのまま貼り付けて実行できます。

import unittest
class MyTestCase(unittest.TestCase):
    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'

    def test_2_cannot_add_int_and_str(self):
        import operator
        self.assertRaises(TypeError, operator.add, 1, '1')

unittest.main(exit=False)

テストの実行結果

上記のコードを実行すると、ターミナルには次のような出力が表示されます。

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

assertRaises の2つの使い方

1. コンテキストマネージャとして使う(推奨)

1つ目のテストでは、assertRaiseswith 文によるコンテキストマネージャとして使用しています。この書き方なら、例外が適切に捕捉・記録され、後処理も自動的に行われるため、最もシンプルで可読性の高い方法です。

2. 関数呼び出し形式で使う

2つ目のテストのように、コンテキストマネージャを使わずに書くことも可能です。この場合、引数は次の順序で指定します。

  • 第1引数: 発生を期待する例外の型(例: TypeError
  • 第2引数: テスト対象の関数
  • 以降の引数: テスト対象の関数に渡される位置引数やキーワード引数

ただし、特別な理由がない限り、コンテキストマネージャ形式のほうが簡潔で読みやすいため、こちらを使うのが一般的です。

まとめ

この例では、1'1' を足そうとすると、期待どおり TypeError が発生することが確認できました。このように assertRaises を使えば、「例外が正しく発生すること」だけでなく「例外が発生しなかった場合にテストを失敗させる」ことも簡単に検証できます。エラーハンドリングの品質を担保したい場面で、ぜひ活用してみてください。

  1. Python Matplotlibで多変量関数をプロットする方法

    Pythonで多変量関数(複数の変数を持つ関数)を視覚的に表現したい場合、Matplotlibの散布図を活用すると、x・y・zの3つの変数の関係を1つのグラフ上で直感的に把握できます。ここでは、具体的な手順とサンプルコードを交えて解説します。実装の手順図のサイズを設定し、サブプロット間および周囲の余白(パディング)を調整します。NumPyを使って、ランダムな x、y、z のデータ点を生成します。図(figure)とサブプロット(axes)のセットを作成します。x・y・z のデータ点をもとに散布図を描画します。ScalarMappableインスタンス s に対してカラーバーを作成し、z値の色の対

  2. Pythonのラムダ関数(lambda)とは?基本構文と使い方を実例付きで解説

    Pythonのラムダ関数(lambda関数)は、実行時にその場で生成される「名前を持たない匿名関数」です。通常、1行で記述され、特定の名前に束縛されることなく定義できます。 ラムダ関数には以下のような特徴があります。 関数の定義をその場で返すことができる return文を含まず、常に式(expression)を評価して結果を返す 関数オブジェクトが期待される場所なら、どこにでもラムダ式を記述できる ラムダ関数を使う場面 ある関数が一度しか使わず、呼び出し箇所も一箇所だけであるような場合、ラムダ関数が便利です。このようなケースでは、わざわざdef文で関数に名前を付けて定義する必要はありません