Select Language

AI Technology Community

6.7、Python assertはソフトウェアテストを実現する

Pythonはテストを非常に重視しています。例えば、テストで最も一般的な操作であるアサーションassertは、Pythonではキーワードであり、関数ではありません。一方、C言語では、assertは単なる普通の関数です。この点からもわかるように、Pythonはテストを最も基本的な部分として位置付けています。

以下のコードを使用して、Python言語で定義されているキーワードを確認できます。

>>> import keyword                                     # モジュールkeywordをインポート
>>> keyword.kwlist                                     # すべてのキーワードを取得
# キーワードリスト
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
'break', 'class', 'continue', 'def', 'del', 'elif', 'else',
'except', 'finally', 'for', 'from', 'global', 'if', 'import',
'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass',
'raise', 'return', 'try', 'while', 'with', 'yield']

ソースコード内でassertを直接使用してテストを行うことができます。一般的なやり方は図1の通りです。


図1 テストコードと実装機能を同じファイルに配置する


次に簡単な例を見てみましょう。自作のモジュールsampleAssertを定義したとします。そのコードは以下の通りです。

def int_list_sort(input_list):          # テスト対象。入力された整数リストをソートする
    input_list.sort()                   # ソートを実行
if __name__ == "__main__":                      # 条件判定。中身はテスト用
    def test_normal_positive_input():                   # テストケースを定義
        input_list = [3, 5, 9, 1, 8]
        int_list_sort(input_list)
        assert input_list == [1, 3, 5, 8, 9]
        print("test_normal_positive_input: PASS")
    test_normal_positive_input()                         # テストケースを実行

このモジュールをimport(インポート)すると、caseは実行されません。つまり、3行目から始まるブロックは実行されないため、このブロック内に含まれるテストケースの定義は見えず、テストケースも実行されません。

$ python                                       # インタープリタを起動。Python 3
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sampleAssert                        # 先ほど定義したモジュールをインポート
>>> sampleAssert.test_normal_positive_input()  # テスト関数は見えない
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'sampleAssert' has no attribute 'test_normal_
        positive_input'
>>> list_obj = [3, 1, 6, 100, 98, 9]
>>> sampleAssert.int_list_sort(list_obj)         # テスト対象は見える
>>> list_obj
[1, 3, 6, 9, 98, 100]                            # ソート後の結果

このスクリプトを直接実行すると、テストケースがトリガーされます。

$ python sampleAssert.py
test_normal_positive_input: PASS


次に、整数リストにのみ有効なバブルソートアルゴリズムを実装しましょう。バブルソートは最も簡単なソートアルゴリズムで、隣接する要素を交換することでソートを行います。以下は、3、1、5、2の4つの要素を含むリストをソートする例で、このプロセスを図2に示します。


図2 バブルソート


まず、リストの末尾、つまり下部から順に、並び順が正しくない隣接する2つの数を探します。最初に見つかったのは5と2で、これらを交換します。その後、引き続き探すと、3と1という並び順が正しくない隣接する数が見つかり、これらも交換します。この1ラウンドの交換により、最小の数が最初の要素に移動します。その後、他の要素のソートを続けます。2ラウンド目では、2番目に小さい数が2番目の位置に配置されます。これを繰り返すことで、最大でn - 1ラウンドですべてのデータのソートが完了します。

この例では、2ラウンドですべてのデータのソートが完了しました。

以下は、完全な実装コードと関連するテストコードです。

def bubble_sort(input_list):                    # テスト対象の関数。バブルソート
    if type(input_list) is not type([]):        # 入力パラメータが適切でない場合
        print("Invalid Input Type")
        return None
    for x in input_list:                                # 要素が整数でない場合、Noneを返す
        if type(x) != int:
            return None
    input_len = len(input_list)
    print()
    print("Origin:", input_list)
    if input_len <= 1:                               # 要素がないか、1つだけの場合
        return input_list
    for x in range(input_len-1):                # 順序が正しくない場合、隣の要素と交換
        swap_happens = False
        for y in range(input_len-1, x, -1):
            if input_list[y-1] > input_list[y]:
                input_list[y-1], input_list[y] = input_list[y], input_
                        list[y-1]
                swap_happens = True
        if swap_happens == False:               # 前のラウンドでデータの交換がなかった場合、ソート完了
            break
        print("Temp %d:" % x, input_list)
    return input_list                                   # ソート完了したリストを返す
if __name__ == "__main__":                              # このスクリプトを実行する場合、インポートするのではなく
    import random                                               # テストコード開始
    def test_empty_input():                             # 入力リストが空の場合
        input 
post
  • 7

    item of content
例外処理は現代のプログラミング言語の基本的な特性でもあり、正常な分岐と例外の分岐を切り分けることができます。C言語とは異なり、正常な分岐と例外の分岐が混在することはありません。
Pythonにおいて例外は特別なオブジェクトであり、この例外オブジェクトを通じて例外発生時の情報を例外処理関数に渡すことができます。
この章では、例外の捕捉方法、例外情報の取得方法、特定の例外の無視、例外のスロー方法、カスタム例外オブジェクトの作成、そしてPython 2とPython 3における例外処理の類似点と相違点について説明します。最後に、一般的なシステム定義の例外についても紹介します。