iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 28
0
Software Development

30 天把自己榨好榨滿的四週四語言大挑戰!系列 第 28

[Day 27] 自己的程式自己測

先前寫了那麼多程式,是時候來談談測試了。這裡的測試指的是 Unit test,大部分的時間是以一個 Function、Class 等等為單位去測試,看輸入幾組設計過後的 Input 是否可以得到預期的 Output。Unit test 可以說是身為一個軟體工程師最基本要去撰寫跟測試相關的部分,因為每個 Function 的細節通常只有軟體工程師自己會知道,而測試工程師一般來說,是把你的 API 或是 Service 當成一個黑盒子去進行測試。當我們需要做像是 Refactoring 的時候,先前寫的這些 Unit test 就能夠達到保護的作用,避免因為把程式改壞了而不自知。而好的 Unit test 的 Case 通常也可以拿來告訴讀者這段程式在實際上會是怎樣被使用以及應該要得到的結果。有時候迫於現實,常常是來不及把測試寫完,就必須先讓可以動的程式碼上架。這種情況最好事後還是要把 Unit test 補完,除了上面提到的在未來可以起到保護的作用,另一方面也可以讓自己能夠留下一些蛛絲馬跡在未來不管是自己或別人在閱讀程式碼的時候有所依據。此外還有提倡許久的 TDD (Test-driven development),也就是先把測試寫出來,再去把實作完成,藉由最後讓程式碼可以通過程式,來確立已經完成了預計的 Scenarios。
那麼就讓我們來看看這些語言大概是怎麼樣來進行測試程式的撰寫吧!

Python 3

  • 在 Python 我們用的是 unittest 這個單元測試框架。我們會 import unittest,並且從此 Module 引入 TestCase 這個基礎類別。再來通常我們會為每個要被測試的 Function 或 Class 建立一個測試 class 並讓此 class 繼承 TestCase,例如我們今天要測下面程式碼的 add 這個函式。
# Functions to be tested
def add(x, y):
    return x + y
  • 再來看我們的測試程式碼,首先 import unittest,並且宣告 class AddTestCase(unittest.TestCase),表示一個用來測試 add 的類別 (並繼承 unittest.TestCase)。而每個測試都必須以 test_ 開頭,像是下面的 test_add,最關鍵的是我們利用了 self.assertEqual(expected, result) 來替我們比對 expected 以及實際的 result。接下來看到 setUptearDown 是所謂的 Test fixture,也就是每次測試之前的準備跟測試之後一些清除的動作,例如準備一個要拿來被測試的資料,以及在測試之後將其清除,這裡我們加上 args 這個屬性來當作測試資料。再來是 Test suite,也就是一組的測試案例。例如我們建立了 suite 這個 Test suite,然後把測試加到這個 Suite(當然還有其他方式可以讓我們把案例加到 Suite 之中,也可以加到兩個以上)。以上這些都有了之後,最後要有的是一個 Test runner 來幫我們去執行某個測試的 Suite,也就是 unittest.TextTestRunner(verbosity=2).run(suite),verbosity 是調整執行測試時所輸出的細節。
import unittest

class AddTestCase(unittest.TestCase):
    def setUp(self):
        self.args = (100, 99)

    def tearDown(self):
        self.args = None

    def test_add(self):
        expected = 199;
        result = add(*self.args);
        self.assertEqual(expected, result);
        
suite = unittest.TestSuite()
suite.addTest(AddTestCase('test_add'))

unittest.TextTestRunner(verbosity=2).run(suite)
  • 如果測試成功的話我們可以看到如下:
test_add (__main__.AddTestCase) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
  • 測試失敗的話會看到類似如下:
test_add (__main__.AddTestCase) ... FAIL

======================================================================
FAIL: test_add (__main__.AddTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "main.py", line 21, in test_add
    self.assertEqual(expected, result);
AssertionError: 19 != 199

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)
  • 更多關於 unittest 這個 Module 可以參考這裡囉!

上一篇
[Day 26] 以組合代替繼承?
下一篇
[Day 28] 來看正規表示式
系列文
30 天把自己榨好榨滿的四週四語言大挑戰!30

尚未有邦友留言

立即登入留言