1. 程式人生 > >python中更人性化的一個單元測試框架:nose2

python中更人性化的一個單元測試框架:nose2

如果你學過 python 進行自動化測試,你一定使用過 unittest。今天我們要講的 nose2 是一個高階版本的 unittest。他比 unittest 更容易理解,用起來也更加方便一些。

快速開始

nose2 在 unittest 的基礎上開發的,所以如果你之前是用 unittest 做測試,但是有想使用 nose2 的新特性,你可以在不改變原有程式碼的情況下直接使用 nose2。

import unittest
import nose2

class TestAdd(unittest.TestCase):
    def test_add(self):
        self.assertEqual(1+1, 3)

if __name__ == '__main__':
    # 只需要替換這一行
    # unittest.main()
    nose2.main()

安裝

nose2 是第三方庫,需要自己安裝,直接在 cmd 執行 pip 指令安裝:

pip install nose2

執行測試用例

在快速開始當中,我們使用了在 python 程式碼中用 nose2.main() 的方式去執行測試用例,這樣是完全 OK 的。

還有另外一種執行方式:直接在命令列通過 nose2 命令執行。他會在python檔案中查詢名稱以 test 開頭的測試檔案,並執行它發現的每個以 test 開頭的測試函式名稱。比如說我的專案當中有 test_add.py, test_minus.py 這些檔案,如果我想執行所有的測試用例,只需要在當前檔案下輸入 cmd 命令,他就會自動去查詢所有的測試用例,然後去執行:

nose2

執行指定資料夾下的測試用例

nose2 -s 資料夾名稱

我把登入相關的用例都放到一個叫 login_case 的資料夾當中,當我執行 nose2 -s login_case 的時候,其他的用例是不會執行的, nose2 只會去找 login_case 資料夾下面的用例。

 

 

執行指定的測試用例

nose2 login_case.test_nose2_dir.test_login

在這個例子當中:

  • login_case 是儲存的資料夾
  • test_nose2_dir 是檔名稱
  • test_login 是測試用例方法的名稱

每一個層級之間,用 . 號隔開。

如果想測試 test_nose2_dir.py 檔案下的所有用例:

nose2 login_case.test_nose2_dir

如果想測試 login_case 資料夾下的所有用例:

nose2 login_case

測試用例的命名

為什麼 nose2 可以自動查詢用例並且執行呢?是因為他在內部制定了規則,然後根據規則去判定。

比如首先他規定,你所有的測試用例檔名稱應該以 test 開頭,如果你不這麼做,那這個檔案就不是測試用例檔案。以下的檔名都會被判定為測試用例檔案:

test.py
test_add.py
testRegister.py

而這一些不會被判定為測試用例檔案,從而被忽略:

add_test.py
a_test.py
register_test_file.py

高階特性

測試用例方法的編寫

與unittest不同的是,nose2 的測試用例並不一定要以類的形式存在,也可以使用函式。任何函式和類,只要名稱匹配一定的條件(例如,以test開頭或以test結尾等),都會被自動識別為測試用例。

def test_add():
    assert 1 == 2


if __name__ == '__main__':
    nose2.main()

引數化

類似於 unittest 當中的 ddt 模組,不過比 ddt 模組使用起來簡潔一些。在測試過程當中,通常會有多組測試用例資料,多組測試用例會共用一個測試用例的方法,從而實現資料驅動。在 nose2 當中你可以這樣使用:

import nose2
from nose2.tools import params

def add(a, b):
    return a + b

test_data = [
    {"data": (1, 2), "expected": 3},
    {"data": (2, 2), "expected": 4},
    {"data": (3, 2), "expected": 6},
]

@params(*test_data)
def test_add(data):
    assert add(*data["data"]) == data["expected"]

1, @params(*test_data) 會接收外部傳進來的多組測試資料;

2,test_add(data) 當中的 data 每次取出一組資料執行,所以,data 其實就是 {“data”: (1, 2), “expected”: 3} 這樣的一組資料。

3,這裡因為有 3 組資料,所以執行的時候會有 3 個測試用例。

測試夾具

測試夾具是為了給測試用例準備前置條件和後置條件。

  • @with_setup(before_test) 表示在測試用例執行之前要執行的前置條件
  • @with_teardown(after_test) 表示在測試用例執行之後的後置條件
  • before_test 和 after_test 是自己定義的函式
from nose2.tools.decorators import with_setup, with_teardown

def before_test():
    print("before test")

def after_test():
    print("after test")

@with_setup(before_test)
@with_teardown(after_test)
def test_add(data):
    assert add(*data["data"]) == data["expected"]

 

總結

本篇我們介紹了 nose2 的簡單入門:

  • nose2 是在 unittest 的基礎上實現的,可以和 unittest 相容,如果你沒有接觸過 unittest, 建議先從 unittest 學起,很多同學在網上看到一些說 unittest 過時或者是說 unittest 不高階的言論就開始批判,不對。 unittest 是 其他 python 單元測試框架的基礎,沒學好 unittest , 其他的框架你也學不好。
  • nose2 可以自動發現測試用例,你只需要執行 nose2 命令就可以,用起來非常簡單。
  • nose2 的測試用例名稱要符合規範,以 test 開頭,否則不會被判定為用例。
  • 你可以通過 -s 執行指定檔案下的用例,也可以通過 . 號去執行單個用例。

 

nose2 vs unittest

nose2 上手會比 unittest 更簡單,使用 unittest, 需要同時掌握 testrunner, testsuite, testcase 等基本概念,還需要熟悉類和物件。 nose2 隱藏了這些細節設計,難度會更低一些。

nose2 可以直接執行 unittest 的測試用例,可以實現無縫切換。

但是並不是說 unittest 就不好。 unittest 做為一個 python 標準庫,和 python 版本繫結,非常穩定,不用擔心相容性的問題。

如果要學習一個單元測試框架,建議從 unittest 開始,因為你可以接觸到 loader, suite, runner 這樣的元件,對理解測試框架更有幫助,學習好 unittest 以後,再學習 nose2 或者 pytest 這樣更高階的框架,能有效提升程式設計效率。

nose2 vs pytest

如果你只想學習一個高階單元測試框架,建議你學 pytest, 而不是 nose2。

nose2 足夠好,甚至看上去他的設計比 pytest 更加清晰,更容易理解。但是社群沒有 pytest 活躍,因此使用的人也比較少。

實際上,nose2 和 pytest 的用法很多都是非常類似的,學習了一個,另外一個也能輕鬆上手。nose2 對於加深對測試框架的理解有很大的好處。