1.Pytest介紹
pytest是python的一種單元測試框架,與python自帶的unittest測試框架類似,但更簡潔並高效。
官方網站優點簡介:
- 非常容易上手,入門簡單,文檔豐富,文檔中有很多實例可以參考
- 能夠支持簡單的單元測試和復雜的功能測試
- 支持參數化
- 執行測試過程中可以將某些測試跳過,或者對某些預期失敗的case標記成失敗
- 支持重復執行失敗的case
- 支持運行由nose, unittest編寫的測試case
- 具有很多第三方插件,並且可以自定義擴展
- 方便的和持續集成工具集成
2. 安裝pytest
下面兩種安裝方式二選一即可。
1 pip install -U pytest 2 easy_install -U pytest
安裝完成查看安裝的版本,若提示pyttest函數不存在,只需要將python目錄下的Scripts目錄配置到環境變量中即可解決問題
pytest --version
3. 執行用例
-
簡單執行單個用例
1 # content of test_sample.py 2 3 4 def func(x): 5 return x + 1 6 7 8 def test_func(): 9 assert func(3) == 5
到該模塊的目錄下,輸入pytest(模塊的名字與執行函數必須是test開頭或_test結尾,否則不會被執行,切記!),見該代碼執行的結果,見截圖:
-
執行class中的測試用例
1 # content of test_class.py 2 3 class TestClass: 4 def test_one(self): 5 x = "this" 6 assert 'h' in x 7 8 def test_two(self): 9 x = "hello" 10 assert hasattr(x, 'check')
-
執行目錄下指定用例
在測試中,有N個測試用例,但是我們只是想執行其中的一個用例,其它的用例不想執行,那怎么辦呢?使用下面命令就可以執行單個用例
1 # $pytest -q /path/用例名 2 pytest -q test_case2.py
4.編寫測試樣例與規范
-
python命名規范
1 一 包名、模塊名、局部變量名、函數名 2 全小寫+下划線式駝峰 3 example: this_is_var 4 二 全局變量 5 全大寫+下划線式駝峰 6 example: GLOBAL_VAR 7 三 類名 8 首字母大寫式駝峰,否則會報錯提示語法錯誤 9 example: ClassName()
-
測試用例規則
1 - 測試文件以test_開頭(以_test結尾也行) 2 - 測試類以Test開頭,並且不能帶有__init__方法 3 - 測試函數以test_開頭 4 - 斷言使用基本的assert即可
5. pytest高級進階——Fixture
-
何為fixture
fixture是pytest的一個閃光點,fixture是pytest特有的功能,它用pytest.fixture標識,定義在函數前面。在你編寫測試函數的時候,你可以將此函數名稱做為傳入參數,pytest將會以依賴注入方式,將該函數的返回值作為測試函數的傳入參數。
fixture有明確的名字,在其他函數,模塊,類或整個工程調用它時會被激活。
fixture是基於模塊來執行的,每個fixture的名字就可以觸發一個fixture的函數,它自身也可以調用其他的fixture。
fixture主要的目的是為了提供一種可靠和可重復性的手段去運行那些最基本的測試內容。比如在測試網站的功能時,每個測試用例都要登錄和退出,利用fixture就可以只做一次,否則每個測試用例都要做這兩步也是冗余。
-
Fixture入門實例
把一個函數定義為Fixture很簡單,只能在函數聲明之前加上“@pytest.fixture”。其他函數要來調用這個Fixture,只用把它當做一個輸入的參數即可。
import pytest @pytest.fixture() def setup(): print('\nsetup') def test_1(setup): print('test_1()') def test_2(setup): print('test_2()') def test_3(): print("test3()")
下面是運行結果,test_1和test_2運行之前都調用了setup,test_3沒有參數沒有傳fixture標識的函數所以不會調用setup。默認情況下,fixture是每個測試用例如果調用了該fixture就會執行一次的。
-
使用autos調用fixture
fixture decorator一個optional的參數是autouse, 默認設置為False。
當默認為False,就可以選擇用上面方式來調用fixture標識的函數。
當設置為True時,在一個session內的所有的test都會自動調用這個fixture。
權限大,責任也大,所以用該功能時也要謹慎小心。
import time import pytest @pytest.fixture(scope="module", autouse=True) def mod_header(request): print('\n-----------------') print('module : %s' % request.module.__name__) print('-----------------') @pytest.fixture(scope="function", autouse=True) def func_header(request): print('\n-----------------') print('function : %s' % request.function.__name__) print('time : %s' % time.asctime()) print('-----------------') def test_one(): print('in test_one()') def test_two(): print('in test_two()')
從下面的運行結果,可以看到mod_header在該module內運行了一次,而func_header對於每個test都運行了一次,總共兩次。該方式如果用得好,還是可以使代碼更為簡潔。
但是對於不熟悉自己組的測試框架的人來說,在pytest里面去新寫測試用例,需要去了解是否已有一些fixture是module或者function級別的需要注意。
fixture scope
- function:每個test都運行,默認是function的scope
- module:每個module的所有test只運行一次
- class:每個class的所有test只運行一次
- session:每個session只運行一次
-
fixture 返回值
在上面的例子中,fixture返回值都是默認None,我們可以選擇讓fixture返回我們需要的東西。如果你的fixture需要配置一些數據,讀個文件,或者連接一個數據庫,那么你可以讓fixture返回這些數據或資源。
如何帶參數
fixture還可以帶參數,可以把參數賦值給params,默認是None。對於param里面的每個值,fixture都會去調用執行一次,就像執行for循環一樣把params里的值遍歷一次。
import pytest @pytest.fixture(params=[1, 2, 3]) def test_data(request): return request.param def test_not_2(test_data): print('test_data: %s' % test_data) assert test_data != 2
可以看到test_not_2里面把用test_data里面定義的3個參數遍歷了一次。
6. 使用IDEL執行測試用例
-
使用OS創建一個子shell執行測試用例
import os # 在當前進程中打開一個子shell(子進程)來執行系統命令。 cmd = os.system(r"pytest -s -v D:\Users\sangfor\AppData\Local\Programs\Python\Python37\Scripts\testcase") print(cmd)
運行結果如下
-
使用pytest.main()運行測試用例
import pytest # 注意()中使用list,多個參數用","隔開,path路徑前用r
pytest.main(["-s", f"{case_path}\\TestCase", "--alluredir=report"])
運行結果如下