前言
Python中有非常多的單元測試框架,如unittest、pytest、nose、doctest等,Python2.1及其以后的版本已經將unittest作為一個標准模塊放入Python開發包中。並且在pytest框架中,是可以兼容運行unittest的代碼的,簡單來說,就是學一頂倆。並且unittest也是比較簡單上手的,等unittest篇完結后,我們再開一個pytest篇。成為自動化測試大神指日可待🙊
認識斷言
單元測試本質上就是通過一段代碼去驗證另外一段代碼,那么這段驗證的代碼里,有一個起到關鍵作用的關鍵字,就是assert
-斷言。assert(斷言)用於判斷一個表達式,在表達式條件為 false 的時候觸發異常。下面舉例說明一下用法
-
來看看語法格式,一般assert后面跟一個條件和一個斷言失敗信息
比如
assert 1 == -1,'報錯就打印我出來'
斷言失敗就會拋出
AssertionError
異常,並且把自定義的斷言失敗信息打印出來上面這條語句就等價於
if not 1 == -1: print("報錯就打印我出來") raise AssertionError
看到這里的話應該很清晰了,所謂斷言就是判斷一個條件,條件不成立就會拋出異常,稱之為斷言失敗,反之就是斷言成功。
代碼初體驗
了解基本情況后,開始動手敲敲代碼吧,始終貫徹代碼驅動學習理念,只看是永遠學不會的!當然了天才除外👏🏻
先來創個項目,項目名就叫Study_unittest
,直白易懂
先創第一個py文件,名就叫calculator.py
,在這里面創建計算器類。
#計算器類
class Calculator:
"”用於完成兩個數的加、減、乘、除"""
def __init__(self,a,b):
self.a=int(a)
self.b=int(b)
# 加法
def add(self):
return self.a + self.b
#減法
def sub(self):
return self.a - self.b
#乘法
def mul(self):
return self.a * self.b
#除法
def div(self):
return self.a / self.b
在定義好上面的 alculator.py
程序之后,該程序就相當於一個模塊,接下來為該模塊編寫單元測試代碼。
創建test_calculator.py
文件,下面就是測試用例的代碼:
import unittest
from calculator import Calculator
class TestCalculator(unittest.TestCase):
def test_add(self):
c = Calculator(1, 2)
result = c.add()
self.assertEqual(result, 3)
def test_sub(self):
c = Calculator(5, 1)
result = c.sub()
self.assertEqual(result, 4)
def test_mul(self):
c = Calculator(5, 1)
result = c.sub()
self.assertEqual(result, 6)
def test_div(self):
c = Calculator(6, 2)
result = c.sub()
self.assertEqual(result, 3)
if __name__ == '__main__':
unittest.main()
由上得知,unittest 要求單元測試類必須繼承 unittest.TestCase
,該類中的測試方法需要滿足如下要求:
- 測試方法不應該有返回值。
- 測試方法不應該有任何參數。
- 測試方法應以test 開頭。
運行結果如下:
本次統計運行了4條測試用例,運行時間為0.139s,失敗(failures)了1條測試用例,成功(successes)了3條測試用例。失敗的測試用例也有清晰說明用例名稱以及錯誤的位置。
斷言方法
-
unittest.TestCase 內置了大量 assertXXX 方法來執行斷言,其中最常用的斷言方法如表 1 所示。
斷言方法 檢查條件 assertEqual(a, b) a == b assertNotEqual(a, b) a != b assertTrue(x) bool(x) is True assertFalse(x) bool(x) is False assertIs(a, b) a is b assertIsNot(a, b) a is not b assertIsNone(x) x is None assertIsNotNone(x) x is not None assertIn(a, b) a in b assertNotIn(a, b) a not in b assertlsInstance(a, b) isinstance(a, b) assertNotIsInstance(a, b) not isinstance(a, b) 表 1 TestCase 中最常用的斷言方法
-
除了上面這些斷言方法,如果程序要對異常、錯誤、警告和日志進行斷言判斷,TestCase 提供了如表 2 所示的斷言方法。
斷言方法 檢查條件 assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) 引發 exc 異常 assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) 引發 exc 異常,且異常信息匹配 r 正則表達式 assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) 引發 warn 警告 assertWamsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) 引發 warn 警告,且警告信息匹配 r 正則表達式 assertLogs(logger, level) With 語句塊使用日志器生成 level 級別的日志 表 2 TestCase 包含的與異常、錯誤、警告和日志相關的斷言方法
-
TestCase 還包含了如表 3 所示的斷言方法用於完成某種特定檢查。
斷言方法 檢查條件 assertAlmostEqual(a, b) round(a-b, 7) == 0 assertNotAlmostEqual(a, b) round(a-b, 7) != 0 assertGreater(a, b) a > b assertGreaterEqual(a, b) a >= b assertLess(a, b) a < b assertLessEqual(a, b) a <= b assertRegex(s, r) r.search(s) assertNotRegex(s, r) not r.search(s) assertCountEqual(a, b) a、b 兩個序列包含的元素相同,不管元素出現的順序如何 表 3 TestCase 包含的用於完成某種特定檢查的斷言方法
-
當測試用例使用 assertEqual() 判斷兩個對象是否相等時,如果被判斷的類型是字符串、序列、列表、元組、集合、字典,則程序會自動改為使用如表 4 所示的斷言方法進行判斷。換而言之,如表 4 所示的斷言方法其實沒有必要使用,unittest 模塊會自動應用它們。
斷言方法 | 用於比較的類型 |
---|---|
assertMultiLineEqual(a, b) | 字符串(string) |
assertSequenceEqual(a, b) | 序列(sequence) |
assertListEqual(a, b) | 列表(list) |
assertTupleEqual(a, b) | 元組(tuple) |
assertSetEqual(a, b) | 集合(set 或 frozenset) |
assertDictEqual(a, b) | 字典(dict) |
表 4 TestCase 包含的針對特定類型的斷言方法
運行測試
在編寫完測試用例之后,可以使用如下兩種方式來運行它們:
-
通過代碼調用測試用例。程序可以通過調用 unittest.main() 來運行當前源文件中的所有測試用例。例如,在上面的測試用例中增加如下代碼:
if __name__ == '__main__': unittest.main()
-
使用 unittest 模塊運行測試用例。使用該模塊的語法格式如下:
python -m unittest 測試文件
在使用 python -m unittest 命令運行測試用例時,如果沒有指定測試用例,該命令將自動查找並運行當前目錄下的所有測試用例。因此,程序也可直接使用如下命令來運行所有測試用例:
py -m unittest
相信通過本篇文章,你對unittest有了基本的認識,該系列的文章也會做到簡潔通俗明了,讓大家更容易上手。
這一期就到這里了,下一期內容來介紹unittest的四大重點。喜歡的朋友可以收藏下來方便以后查看~