見出し画像

【Python】SimplePrograms line 13 unittest

プログラム

13行プログラムです。

import unittest
def median(pool):
    copy = sorted(pool)
    size = len(copy)
    if size % 2 == 1:
        return copy[int((size - 1) / 2)]
    else:
        return (copy[int(size/2 - 1)] + copy[int(size/2)]) / 2
class TestMedian(unittest.TestCase):
    def testMedian(self):
        self.assertEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7)
if __name__ == '__main__':
    unittest.main()

実行結果

Ran 1 test in 0.000s

OK

解説

「Unit testing」
個人的に興味のあった機能です。

単体テスト。

まずは、単体テストの対象となる関数「median」について把握しておきましょう。


関数「median」

最初に、引数「pool」を昇順に並べ替えます。
その後、
「pool」のサイズが奇数なら
 pool[0]
 pool[1]
 pool[2]⇐ココの数値を出力
 pool[3]
 pool[4]

「pool」のサイズが偶数なら
 pool[0]
 pool[1]
 pool[2]⇐ココと
 pool[3]⇐ココの平均値を出力
 pool[4]
 pool[5]


関数「median」の単体テスト

テストはこちらの部分になります。

class TestMedian(unittest.TestCase):
    def testMedian(self):
        self.assertEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7)

class TestMedian(unittest.TestCase):

まずはこの部分。

class TestMedian(unittest.TestCase):

「unittest.TestCase」を継承して、単体テスト用のクラスを作成します。

次の行のこの部分。

def testMedian(self):

これは、テストプログラムを実行中するメンバ関数を定義します。
関数名は「test」で始まること。
でないと、テストプログラムとして実行されません。
例えば、

def utMedian(self):

のように書くと実行結果はこんな風になってしまいます。

Ran 0 tests in 0.000s

OK

「Ran 0」となって、実行されたテストは0個。
「utMedian」は実行されません。
逆に言うと、テスト用のサブ関数を作れますね。

さて、次のこの部分。

self.assertEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7)

ここがテストプログラム。
「assart」というのはプログラミングでは古くから使われている単語で、

  • 真であれば何もしない

  • 偽であれば警告する

という感じでしょうか。

「self.assertEqual」という記載は

  • 一致していれば何もしない

  • 一致していなければ警告する

ということになります。

引数は2つありますから、

  • 2つが一致していれば何もしない

  • 一致していなければ警告する

ということになります。

このサンプルプログラムでは、引数は次の2つ。

median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7

  • 関数「median」を

  • 引数「[2, 9, 9, 7, 9, 2, 4, 5, 8]」で呼び出し、

  • 戻り値が 7 であれば何もしない

  • 戻り値が 7 でなければ警告する

ということをしているだけです。

一見、なんだかすごいことをしていそうなのですが、例えばこんなことも書けます。

    def testBoo(self):
        dataa=7
        self.assertEqual(dataa, 7)
  • dataa に 7 を設定して

  • dataa が 7 かどうかを確認する

それだけです。

例えばこんなことをしてみる。

import unittest
class TestMedian(unittest.TestCase):
    def testBoo(self):
        dataa=7
        self.assertEqual(dataa, 7)
    def testFoo(self):
        datab=8
        self.assertEqual(datab, 8)
if __name__ == '__main__':
    unittest.main()

もはや、テストでもなんでもないんですが。

実行結果はこうなります。

Ran 2 tests in 0.000s

OK

2つ実行して結果はOK。

一つをNGにしてみましょう。

datab=9

にしてみます。

実行結果は・・・。

======================================================================
FAIL: testFoo (__main__.TestMedian)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/emulated/0/qpython/.last_tmp.py", line 8, in testFoo
    self.assertEqual(datab, 8)
AssertionError: 9 != 8

----------------------------------------------------------------------
Ran 2 tests in 0.002s

FAILED (failures=1)

これでもか、というくらいのメッセージの量やなぁ。
これなら「NGを見逃しました」ということもあるまい。

うーん。

unittestって、こんなもんか。
という感じがしないでもない。
もっと便利なものを期待していたけども。

試しに、unittestを使わずに試験プログラムを書いてみる。

unittestを使って書くとこうなる。

class TestMedian(unittest.TestCase):
    def testMedian(self):
        self.assertEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7)

unittestを使わずに書くとこうなる。

def testMedian():
        m = median([2, 9, 9, 7, 9, 2, 4, 5, 8])
        if m == 7: print("ok")
        else:      print("ng")

うーん。
あんまり変わらん気もするけどぉ。

テストケース1つにつき1ステップで書けるから、簡単になると言えば簡単になる、かなぁ。

まずは積極的に使ってみる?

この記事が気に入ったらサポートをしてみませんか?