Pytest特點
Pytest是Python的一個第三方單元測試庫。它的目的是讓單元測試變得更容易,並且也能擴展到支持應用層面復雜的功能測試。
Pytest的特點有:
- 入門簡單,易上手,文檔豐富
- 支持用簡單的assert語句實現豐富的斷言,無需復雜的self.assert*函數
- 支持參數化
- 自動識別測試模塊和測試函數
- 執行測試過程中可以將某些測試跳過(skip),或者對某些預期失敗的case標記成失敗
- 支持重復執行(rerun)失敗的 case
- 模塊化夾具用以管理各類測試資源
- 對 unittest 完全兼容
- 可以很好的和jenkins集成
- 豐富的插件生態,有各式各樣的插件,社區繁榮
快速入門
安裝pytest
使用 pip 進行安裝:
pip install pytest
安裝之后查看版本:
pytest --version
快速開始
1.創建測試函數
Pytest 使用 Python 的 assert
進行條件判斷,最簡單的測試函數如:
# testdemo.py
def test_passing():
assert(1,2,3) ==(1,2,3)
2.運行測試函數
在當前文件目錄使用命令pytest
運行測試函數:
3.pytest運行規則
pytest會查找當前目錄及其子目錄下以test_
開頭的文件或以_test
結尾的文件,找到文件后,執行文件中以test開頭的 函數
4.創建測試類
# test_class.py
class TestClass:
def test_a(self):
x = "hello"
assert "h" in x
def test_b(self):
x = "hello"
assert "a" in x
在當前文件目錄使用命令pytest
運行測試:
第一次測試通過,第二次測試失敗。 可以在斷言中查看失敗的原因
Pytest執行用例命令行參數
除了pytest
命令,pytest還提供了很多執行用例的命令行參數,如下:
1.-v
輸出用例更加詳細的執行信息,比如用例所在的文件及用例名稱等
2.-s
輸出用例中的調式信息,比如print的打印信息等,我們在之前的test_class.py第3行加上一句 print(“測試調試信息”)
# test_class.py
class TestClass:
def test_a(self):
print("測試調試信息")
x = "hello"
assert "h" in x
def test_b(self):
x = "hello"
assert "a" in x
再執行一次用例看看
3.-m
執行被標記的測試用例
我們修改test_class.py文件如下:
# test_class.py
import pytest
class TestClass:
def test_a(self):
print("測試調試信息")
x = "hello"
assert "h" in x
@pytest.mark.run_this_case
def test_b(self):
x = "hello"
assert "a" in x
使用命令 pytest -m run_this_case test_calss.py
執行
可以看到只執行了被標記的用例
4.-k
執行用例包含“關鍵字”的用例
我們修改test_class.py文件如下:
# test_class.py
import pytest
class TestClass:
def test_a(self):
print("測試調試信息")
x = "hello"
assert "h" in x
def test_b(self):
x = "hello"
assert "a" in x
def test_rock(self):
x = "rock"
assert "o" in x
使用命令 pytest -k "rock" test_class.py
執行
5.-q
簡化控制台的輸出,可以看到輸出信息和上面的結果都不一樣, 下圖中有三個.代替了pass結果
6.--collect-only
羅列出所有當前目錄下所有的測試模塊,測試類及測試函數
7.--tb=style
執行用例的時候,有些用例執行失敗的時候,屏幕上會出現一大堆的報錯內容,不方便快速查看是哪些用例失敗,--tb=style
可以屏蔽測試用例執行輸出的回溯信息,可以簡化用例失敗時的輸出信息, style的選項有['auto', 'long', 'short', 'no', 'line', 'native'], 具體區別如下:
--tb=auto 有多個用例失敗的時候,只打印第一個和最后一個用例的回溯信息
--tb=long 輸出最詳細的回溯信息
--tb=short 輸入assert的一行和系統判斷內容
--tb=line 使用一行顯示錯誤信息
--tb=native 只輸出python標准庫的回溯信息
--tb=no 不顯示回溯信息
8.--lf和--ff
--last-failed 只重新運行上次運行失敗的用例(或如果沒有失敗的話會全部跑)
--failed-first 運行所有測試,但首先運行上次運行失敗的測試(這可能會重新測試,從而導致重復的fixture setup/teardown)
我們修改test_class.py文件如下:
# test_class.py
import pytest
class TestClass:
def test_a(self):
print("測試調試信息")
x = "hello"
assert "h" in x
def test_b(self):
x = "hello"
assert "a" in x
def test_rock(self):
x = "rock"
assert "o" in x
def test_c(self):
x = "world"
assert "q" in x
使用命令pytest
執行全部用例,結果如下:
可以看到執行了4條用例,失敗了2條
然后使用命令pytest --lf
,執行失敗的用例,結果如下:
可以看到只執行了兩條失敗的用例
最后我們使用命令pytest --ff
,先執行失敗的用例,再執行成功的用例,結果如下:
可以看到先執行了2條失敗的用例,然后執行了2條成功的用例
9.-x
遇到錯誤時停止測試
可以看到,本來有4條用例,但是在第2條用例失敗后,就沒有繼續往下執行了
10.--maxfail=num
當用例錯誤個數達到指定數量時,停止測試
我們執行命令 pytest --maxfail=1
可以看到,本來有4條用例,但是在第2條用例失敗后,就沒有繼續往下執行了
以上就是命令行運行測試用例時經常使用到的參數,這些參數不僅可以單獨使用,也可以組合一起使用,可以使用--help
來查看更多命令的幫助信息
Pytest收集用例規則
- 從一個或者多個目錄開始查找,你可以在命令行指定文件或者目錄,如果未指定那么從當前目錄開始收集用例
- 在該目錄和所有子目錄下遞歸查找測試模塊
- 測試模塊是指文件名為test_.py或者_test.py的文件
- 在測試模塊中查找以test_開頭的函數
- 查找名字以Test開頭的類。其中首先篩選掉包含__init__()函數的類,再查找類中以Test_開頭的類方法
規則驗證
我們按照以下目錄結構新建一個項目
代碼如下:
case01.py
# case01.py
# 測試函數
def test_02():
assert 1 == 1
# 普通函數
def func():
assert 1 == 1
test_01.py
# test_01.py
# 測試函數
def test_01():
assert 1 == 1
# 普通函數
def func_01():
print("這是一個普通函數")
# 測試類
class TestClass_01(object):
# 測試函數
def test_class_1(self):
assert 1 == 1
# 普通函數
def func_class_1(self):
assert 1 == 1
# 普通類
class NoTestClass_02(object):
# 測試函數
def test_class_2(self):
assert 1 == 1
# 普通函數
def func_class_2(self):
assert 1 == 1
case.py
# 測試函數
def test_02():
assert 1 == 1
# 普通函數
def func():
assert 1 == 1
在項目根目錄下執行pytest --collect-only
,結果如下:
可以看到,只有2條有效的測試用例
使用pytest -v
命令執行用例,結果如下:
可以看到,只有test_01.py被識別為測試模塊
pytest執行用例規則
規則驗證
按照如下目錄結構新建項目
代碼如下:
test_01.py
# 測試函數
def test_func1():
assert 1 == 1
# 普通函數
def func1():
assert 1 == 1
test_02.py
# 測試類
class TestClass1(object):
# 測試函數
def test_func2(self):
assert 1 == 1
# 普通函數
def func2(self):
assert 1 == 1
case01.py
# 測試函數
def test_func5():
assert 1 == 1
# 普通函數
def func5():
assert 1 == 1
test_03.py
# 測試類
class TestClass2(object):
# 測試函數
def test_func3(self):
assert 1 == 1
# 普通函數
def func3(self):
assert 1 == 1
# 測試函數
def test_func4():
assert 1 == 1
# 普通函數
def func4():
assert 1 == 1
case_02.py
# 測試方法
def test_func8():
assert 1 == 1
# 普通方法
def func8():
assert 1 == 1
04_test.py
# 測試方法
def test_func6():
assert 1 == 1
# 普通方法
def func6():
assert 1 == 1
# 測試類
class TestClass(object):
# 測試方法
def test_func7(self):
assert 1 == 1
# 普通方法
def func7(self):
assert 1 == 1
在項目根目錄下執行pytest -v
,結果如下:
可以看到一共有執行了6條用例,但是我們實際上寫了不止6條用例,通過觀察,會發現這樣一個規律:
Pytest會從我們當前的目錄開始遍歷查找所有目錄,查找以test_開頭或_test結尾的文件,在這些文件中找到以test開頭的函數和以Test開頭的類和類里面以test開頭的函數做為測試用例
Pytest運行指定測試用例
運行指定目錄下的所有用例
使用命令 pytest -v Case01
運行 Case01目錄下的用例, 結果如下
運行指定文件中的所有用例
使用命令 pytest -v Case01/test_01.py
運行Case01中的test_01.py文件中的測試用例,結果如下
運行指定文件中的測試類
使用命令 pytest -v Case02/test_03.py::TestClass2
運行Case02中的test_03.py文件中的測試類Testclass2,結果如下
運行指定的測試用例函數
使用命令 pytest -v Case02/test_03.py::test_func4
運行Case02中的test_03.py文件中的test_func4函數,結果如下
總結
收集用例規則
搜索所有以test_開頭的測試文件,以Test開頭的測試類,以test_開頭的測試函數
執行用例規則
-
運行指定的目錄下用例
- 使用命令
pytest 目錄/目錄
- 使用命令
-
運行指定文件
- 使用命令
pytest 目錄/文件
- 使用命令
-
運行指定類或者函數
- 使用命令
pytest 目錄/文件::類名::函數名 或者 pytest 目錄/文件::函數名
- 使用命令