你會寫單元測試嗎

關於我
編程界的一名小小程序猿,目前在一個創業團隊任team lead,技術棧涉及Android、Python、Java和Go,這個也是咱們團隊的主要技術棧。 聯繫:hylinux1024@gmail.comhtml

也許你已經據說過Test Driven Development,但不知道你是否遵循這個規則呢?其實我本身在寫代碼的時候也不多會先寫單元測試再寫業務功能邏輯。這不我也今天也來學習如何在Python中寫單元測試。python

0x00 unittest

Python中的unittest單元測試框架跟其它語言如JUnit是相似的。它支持測試自動化、配置共享以及關機代碼測試。linux

假設在個人項目目錄下有一個mysum模塊用於計算列表中各個數之和。 還有一個test_mysum.py用於編寫單元測試的文件。編程

myproject/
│
├── mysum/
│   └── __init__.py
└── unittests
    └── test_mysum.py

複製代碼

打開mysum模塊中的__init__.py文件。json

添加下面的方法小程序

def sum(args):
    total = 0
    for arg in args:
        total += arg
    return total
複製代碼

打開test_mysum.py,編寫單元測試bash

import unittest

from mysum import sum

class TestSum(unittest.TestCase):
    def test_list_int(self):
        """ 測試一個整數列表的和 """
        data = [1, 2, 3]
        result = sum(data)
        self.assertEqual(result, 6)


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

複製代碼

首先導入咱們要測試的模塊mysum 測試用例類經過繼承unittest.TestCase來實現,測試方法test_list_int是以test開頭的。 在這個方法中定義了一個整型列表,執行sum方法,而後判斷執行結果是否與預期相符。app

最後調用unittest.main()來執行這個測試用例框架

Ran 1 test in 0.001s

OK
複製代碼

若是再添加一個方法ide

def test_list_sum(self):
    data = [1, 3, 4]

    result = sum(data)
    self.assertEqual(result, 6)
複製代碼

執行後會看到以下相似信息

6 != 8

Expected :8
Actual   :6
複製代碼

從這個輸出信息能夠看出指望值與實際值不相符,這時候若是咱們的測試用例沒有問題,那就要看看mysum的實現邏輯了。

從這個例子中能夠總結一個測試用例的過程:

  1. 構建輸入數據
  2. 執行要測試模塊,獲取執行結果
  3. 與預期結果相比較,根據結果修改代碼

0x01 setup/tearDown

在編寫單元測試時,還能夠重寫父類的setuptearDown方法,能夠在執行測試邏輯開始前和結束時作一些處理。例如在setup方法中能夠初始化測試數據,在tearDown方法作一些清理工做。

import unittest

class TestBasic(unittest.TestCase):
    def setUp(self):
        # 加載測試數據
        self.app = App(database='fixtures/test_basic.json')

    def test_customer_count(self):
        self.assertEqual(len(self.app.customers), 100)

    def test_existence_of_customer(self):
        customer = self.app.get_customer(id=10)
        self.assertEqual(customer.name, "Org XYZ")
        self.assertEqual(customer.address, "10 Red Road, Reading")
    
    def tearDown(self):
        self.app.releaseDB()
複製代碼

在每一個測試執行時setuptearDown都會被執行一次。

0x02 pytest

pytest是一個第三方測試框架,使用它不須要繼承某個類,它可使用原生的assert語句用於測試結果的斷言。

它的用法也很簡單

首先經過pip安裝

➜ pip install pytest
複製代碼

咱們寫一個單獨的tests文件夾下建立測試用例文件test_pytest.py。 注意:這裏pytest的文件必須與上文的unittests文件必須區分開,不然會出現ModuleNotFoundError。我已經在這裏踩坑。

我這裏使用pytest單元測試的文件結構爲

tests
│
└── test_func.py
複製代碼

test_func.py的內容爲

# 導入咱們要測試的模塊
from mysum import sum


def test_answer():
    data = [1, 2, 3]

    assert sum(data) == 5

複製代碼

測試方法以test開頭

而後再命令行中執行

➜ python -m pytest tests/test_func.py 
複製代碼

注意:這裏要使用python -m pytest,若是直接使用pytest會提示ModuleNotFoundError: No module named 'mysum'

執行結果以下

tests/test_func.py F                                                                                                                                                                          [100%]

======================================================= FAILURES ==============================================
_______________________________________________________ test_answer ___________________________________________

    def test_answer():
        data = [1, 2, 3]
    
>       assert sum(data) == 5
E       assert 6 == 5
E        +  where 6 = sum([1, 2, 3])

tests/test_func.py:11: AssertionError
=======================================================1 failed in 0.03 seconds =======================================================
複製代碼

因爲6!=5,這個單元測試提示了出錯的位置。

0x03 總結一下

測試代碼對編寫代碼很是重要,寫單元測試也是一個好習慣。本文也只是一個開胃菜。要寫出健壯的代碼,從寫單元測試開始吧。

0x04 學習資料

相關文章
相關標籤/搜索