Python
unittest
python3

めんどくさがり屋のためのユニットテスト

Introduction

テストの重要性は言わずもがななんですが、結構書くの面倒なんですよね。。

そんな人のための即席ユニットテストの紹介です。
言語は何でも良いんですが、今回はpython(3)で書いていきます。

あと今回はユニットテストなのでプログラムはある程度関数orクラスに
分割されているものとします。

Problem

例えば下のようなmain関数とfizz_buzz関数があるとします。

fizz_buzz関数はstart ~ endまでfizz-buzzし、結果を文字列で返します。
main関数はfizz_buzz関数を使ってなにかややこしいことをします。

def main():
    # do something with fizz_buzz
    s = fizz_buzz(10, 50)

def fizz_buzz(start, end):
    if start > end: return ""
    s = []
    for i in range(start, end+1):
        if i % 15 == 0:
            s.append("Fizz Buzz")
            continue
        if i % 3 == 0:
            s.append("Fizz")
            continue
        if i % 5 == 0:
            s.append("Buzz")
            continue
        else:
            s.append(str(i))
    return "\n".join(s)

if __name__ == "__main__":
    main()

簡単なプログラムなんですが、実際には動かしてみないとエラーやバグが入り込む可能性もあります。(endを含むかどうかとか)

しかし、main関数はややこしいことをいっぱいしているので、バグが有った際それがmainによるものかfizz_buzzによるものかが簡単にはわかりません。

Method

そこで、ユニットテスト用の関数testを作り、下のようにします。

このスクリプトを実行するとtestの部分が実行され、mainは実行されません。
これで簡単なテストを行うことができます。
またtestの呼び出しをコメントアウトすれば通常どおりmainが実行できます。

テストの内容を追加したい場合はtest関数に継ぎ足せばOKですし、
テストをスキップしたい場合は段落ごとにコメントアウトすればOKです。
(Vimならvipで段落選択ができるので便利)

def main():
    test() # テストしないときにはここだけコメントアウト
    # do something with fizz_buzz
    s = fizz_buzz(50)

def fizz_buzz(n):
    pass
    # 略

def test():

    s = fizz_buzz(3)
    expect = "1\n2\nFizz"
    print(s == expect)

    s = fizz_buzz(15, 15)
    expect = "Fizz Buzz"
    print(s == expect)

    s = fizz_buzz(16, 15)
    expect = ""
    print(s == expect)

    exit()

if __name__ == "__main__":
    main()

Conclusion

ちょっとでも良いのでテストを書こう!