文章目錄
-
-
-
- 參數化 parametrize
-
- 适用場景
- 一個典型的例子
- 前置fixture+參數化
-
- 适用場景
- 一個典型的例子
- 示例2
- 個人疑問?
-
-
pytest既可以用來做單元測試,也可以用來做自動化接口測試,pytest可以結合allure生成漂亮的測試報告,經過一段時間的學習,記錄下在單元測試中用到的比較常用的方法
參數化 parametrize
适用場景
在學習pytest的時候學的時候用的最多且最先學習的是參數化,
- 他的應用場景是:比如我需要用自己設計的用例來調用某一個函數多次,當我設計了10個不同的用例,那麼我就需要調用十次函數。
- 以正常的思路想,循環也可以做到啊。但是pytest有參數化這個強大的功能。
一個典型的例子
# content of test_expectation.py
# coding:utf-8
import pytest
#這裡設定了三組測試用例,每組用例用()來表示,用例之間用“,”隔開
@pytest.mark.parametrize("test_input,expected",
[ ("3+5", 8),
("2+4", 6),
("6 * 9", 42),
])
def test_eval(test_input, expected): #此處用參數化命名的參數名
assert eval(test_input) == expected
#
if __name__ == "__main__":
pytest.main(["-s", "test_canshu1.py"])
運作結果:
================================== FAILURES ===================================
_____________________________ test_eval[6 * 9-42] _____________________________
test_input = '6 * 9', expected = 42
@pytest.mark.parametrize("test_input,expected",
[ ("3+5", 8),
("2+4", 6),
("6 * 9", 42),
])
def test_eval(test_input, expected):
> assert eval(test_input) == expected
E AssertionError: assert 54 == 42
E + where 54 = eval('6 * 9')
test_canshu1.py:11: AssertionError
===================== 1 failed, 2 passed in 1.98 seconds ======================
前置fixture+參數化
适用場景
在繼參數化之後用到的一個功能強大的是前置fixture
-
應用場景1:用例1需要先登入,用例2不需要登入,用例3需要
先登入
- 應用場景2:比如說你需要執行個體化一個類之後再分别調用裡面的各個函數,而且是需要在執行個體化的時候傳入幾個不同的用例(參數化解決)
- 以正常的做法來做場景2,需要在每個函數調用的時候都執行個體化一次,是以fixture前置來做執行個體化(例2會有示例)
一個典型的例子
# coding:utf-8
import pytest
# 不帶參數時預設scope="function"
@pytest.fixture()
def login():
print("輸入賬号,密碼先登入")
def test_s1(login):
print("用例1:登入之後其它動作111")
def test_s2(): # 不傳login
print("用例2:不需要登入,操作222")
def test_s3(login):
print("用例3:登入之後其它動作333")
if __name__ == "__main__":
pytest.main(["-s", "test_fix.py"])
運作結果:
============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: E:\YOYO, inifile:
collected 3 items
test_fix.py 輸入賬号,密碼先登入
用例1:登入之後其它動作111
.用例2:不需要登入,操作222
.輸入賬号,密碼先登入
用例3:登入之後其它動作333
.
========================== 3 passed in 0.06 seconds ===========================
示例2
#coding = utf-8
import os,re
import sys
lib_path = os.path.abspath(os.path.join('E:\測試項目\models'))
sys.path.append(lib_path)
import pytest
import dataModel as A
import logging
import pandas as pd
import numpy as np
from utils.type_processing import stringToTime
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
#五個需要測試的用例,參數化需要用到的參數
data = [("E:\測試項目\講話.xlsx"),
("E:\測試項目\黨章黨規目錄(2019年6月26日版).xls"),
("E:\測試項目\lilun.txt"),
("E:\\測試項目\\test1.xlsx"),
("E:\\測試項目\\test1.txt")]
#前置fixture,範圍為module,代表每個class執行一次
@pytest.fixture(scope = "module")
def a(request):
filepath = request.param
x = A.DataModel(filepath) #此處是執行個體化
print("現在測試的是檔案 %s" % filepath)
return x
#參數化,把上面五個用例傳入,a代表前置fixture
@pytest.mark.parametrize("a",data,indirect=True)
class TestData(object):
#存在title的檔案
def test_title(self,a):
C = a
if C.df.empty:
print("檔案為空")
else:
msg = "檔案的标題為空"
title = C.extract_title()
assert title != -1,msg
def test_author(self,a):
C = a
if C.df.empty:
print("檔案為空")
else:
msg = "檔案的作者為空"
author = C.extract_author()
assert author != -1,msg
def test_content(self,a):
C = a
if C.df.empty:
print("檔案為空")
else:
#msg = "檔案的标題為空"
content = C.extract_content()
assert content is not None
def test_time(self,a):
C = a
if C.df.empty:
print("檔案為空")
else:
msg = "檔案的時間為空"
time = C.extract_time()
assert time != -1,msg
為什麼參數化函數@pytest.mark.parametrize("a",data,indirect=True)
參數a為前置fixture?
解答:注意在參數化那裡寫了一個indirect=True的參數,是以前面“a”為前置,後面的data為參數化的參數名。
個人疑問?
- pytest的應用場景那麼廣,但是為什麼網上的單元測試的代碼或者博文卻很少,大多數都是做的接口自動化?
- 如果pytest應用于單元測試,那麼斷言對于我來說,通常是一個比較大的障礙,因為大多時候一個函數的輸出,在用參數化的時候,輸出的結果不能用統一的assert來做出判斷。
- 單元測試似乎不受到特别的重視,或者說一個項目沒有完整的單元測試?
- 還需努力呀!