目錄:
-
pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-yaml
- 數(shù)據(jù)驅(qū)動(dòng)
- yaml文件介紹
- yaml文件使用
- 代碼實(shí)例:
-
pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-excel
- 讀取Excel文件
- openpyxl庫的安裝
- openpyxl庫的操作
- 代碼實(shí)例:
-
pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-csv
- csv文件介紹
- csv文件使用
- 代碼實(shí)例:
-
pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-json
- json文件介紹
- json文件使用
-
pytest測試用例生命周期管理(一)
- Fixture特點(diǎn)及優(yōu)勢
-
pytest測試用例生命周期管理(二)
- Fixture在自動(dòng)化中的應(yīng)用-作用域
-
pytest測試用例生命周期管理(三)
- Fixture在自動(dòng)化中的應(yīng)用-yield關(guān)鍵字
-
pytest測試用例生命周期管理-自動(dòng)注冊
- Fixture在自動(dòng)化中的應(yīng)用-數(shù)據(jù)共享
-
pytest測試用例生命周期管理-自動(dòng)生效
- Fixture在自動(dòng)化中的應(yīng)用-自動(dòng)應(yīng)用
-
pytestfixture實(shí)現(xiàn)參數(shù)化
- Fixture在自動(dòng)化中的應(yīng)用-參數(shù)化
- Fixture的用法總結(jié)
1.pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-yaml
數(shù)據(jù)驅(qū)動(dòng)
-
什么是數(shù)據(jù)驅(qū)動(dòng)?
- 數(shù)據(jù)驅(qū)動(dòng)就是數(shù)據(jù)的改變從而驅(qū)動(dòng)自動(dòng)化測試的執(zhí)行,最終引起測試結(jié)果的改變。簡單來說,就是參數(shù)化的應(yīng)用。數(shù)據(jù)量小的測試用例可以使用代碼的參數(shù)化來實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng),數(shù)據(jù)量大的情況下建議大家使用一種結(jié)構(gòu)化的文件(例如 yaml,json 等)來對數(shù)據(jù)進(jìn)行存儲(chǔ),然后在測試用例中讀取這些數(shù)據(jù)。
-
應(yīng)用:
- App、Web、接口自動(dòng)化測試
- 測試步驟的數(shù)據(jù)驅(qū)動(dòng)
- 測試數(shù)據(jù)的數(shù)據(jù)驅(qū)動(dòng)
- 配置的數(shù)據(jù)驅(qū)動(dòng)
yaml 文件介紹?
- 對象:鍵值對的集合,用冒號(hào) “:” 表示
- 數(shù)組:一組按次序排列的值,前加 “-”
- 純量:單個(gè)的、不可再分的值
- 字符串
- 布爾值
- 整數(shù)
- 浮點(diǎn)數(shù)
- Null
- 時(shí)間
- 日期
# 編程語言
languages:
- PHP
- Java
- Python
book:
Python入門: # 書籍名稱
price: 55.5
author: Lily
available: True
repertory: 20
date: 2018-02-17
Java入門:
price: 60
author: Lily
available: False
repertory: Null
date: 2018-05-11
yaml 文件使用
- 查看 yaml 文件
- pycharm
- txt 記事本
- 讀取 yaml 文件
- 安裝:
pip install pyyaml
- 方法:
yaml.safe_load(f)
- 方法:
yaml.safe_dump(f)
- 安裝:
import yaml
file_path = './my.yaml'
with open(file_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
代碼實(shí)例:
工程目錄結(jié)構(gòu)
- data 目錄:存放 yaml 數(shù)據(jù)文件
- func 目錄:存放被測函數(shù)文件
- testcase 目錄:存放測試用例文件
# 工程目錄結(jié)構(gòu)
.
├── data
│ └── data.yaml
├── func
│ ├── __init__.py
│ └── operation.py
└── testcase
├── __init__.py
└── test_add.py
?測試準(zhǔn)備
- 被測對象:
operation.py
- 測試用例:
test_add.py
- 測試數(shù)據(jù):
data.yaml
# operation.py 文件內(nèi)容
def my_add(x, y):
result = x + y
return result
# test_add.py 文件內(nèi)容
class TestWithYAML:
@pytest.mark.parametrize('x,y,expected', [[1, 1, 2]])
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
# data.yaml 文件內(nèi)容
-
- 1
- 1
- 2
-
- 3
- 6
- 9
-
- 100
- 200
- 300
import pytest
import yaml
from func.operation import my_add
# 方法一
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', [[1, 1, 2], [3, 6, 9], [100, 200, 300]])
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法二
def get_data():
with open("../data/data.yaml", encoding='utf-8') as f:
data = yaml.safe_load(f)
return data
class TestWithYAML:
@pytest.mark.parametrize('x,y,expected', get_data())
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
2.pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-excel
讀取 Excel 文件
-
第三方庫
xlrd
xlwings
pandas
-
openpyxl
- 官方文檔: https://openpyxl.readthedocs.io/en/stable/
openpyxl 庫的安裝
- 安裝:
pip install openpyxl
- 導(dǎo)入:
import openpyxl
openpyxl 庫的操作
-
讀取工作簿
-
讀取工作表
-
讀取單元格
import openpyxl
# 獲取工作簿
book = openpyxl.load_workbook('./data/test.xlsx')
# 讀取工作表
sheet = book.active
print(sheet)
# 讀取單個(gè)單元格
cell_a1 = sheet['A1']
print(cell_a1.value)
cell_a3 = sheet.cell(column=1, row=3) # A3
print(cell_a3.value)
# 讀取多個(gè)連續(xù)單元格
cells = sheet["A1":"C3"]
for i in cells:
for j in i:
print(j.value,end=' ')
print()
?代碼實(shí)例:
import openpyxl
import pytest
import yaml
from func.operation import my_add
# 方法一
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', [[1, 1, 2], [3, 6, 9], [100, 200, 300]])
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法二
# def get_data():
# with open("../data/data.yaml", encoding='utf-8') as f:
# data = yaml.safe_load(f)
# return data
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_data())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法三
def get_excel():
book = openpyxl.load_workbook("../data/test.xlsx")
sheet = book.active
cells = sheet["A1":"C3"]
values = []
for row in cells:
data = []
for cell in row:
data.append(cell.value)
values.append(data)
return values
class TestWithYAML:
@pytest.mark.parametrize('x,y,expected', get_excel())
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
3.pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-csv
csv 文件介紹
- csv:逗號(hào)分隔值
- 是 Comma-Separated Values 的縮寫
- 以純文本形式存儲(chǔ)數(shù)字和文本
- 文件由任意數(shù)目的記錄組成
- 每行記錄由多個(gè)字段組成
Linux從入門到高級(jí),linux,¥5000
web自動(dòng)化測試進(jìn)階,python,¥3000
app自動(dòng)化測試進(jìn)階,python,¥6000
Docker容器化技術(shù),linux,¥5000
測試平臺(tái)開發(fā)與實(shí)戰(zhàn),python,¥8000
?csv 文件使用
-
讀取數(shù)據(jù)
- 內(nèi)置函數(shù):
open()
- 內(nèi)置模塊:
csv
- 內(nèi)置函數(shù):
-
方法:
csv.reader(iterable)
- 參數(shù):iterable ,文件或列表對象
- 返回:迭代器,每次迭代會(huì)返回一行數(shù)據(jù)。
import csv
def get_csv():
with open('./data/params.csv', 'r', encoding='utf-8') as file:
raw = csv.reader(file)
for line in raw:
print(line)
if __name__ == '__main__':
get_csv()
代碼實(shí)例:
測試準(zhǔn)備
-
被測對象:
operation.py
-
測試用例:
test_add.py
-
測試數(shù)據(jù):
params.csv
# operation.py 文件內(nèi)容
def my_add(x, y):
result = x + y
return result
# test_add.py 文件內(nèi)容
class TestWithCSV:
@pytest.mark.parametrize('x,y,expected', [[1, 1, 2]])
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
# params.csv 文件內(nèi)容
1,1,2
3,6,9
100,200,300
import csv
import openpyxl
import pytest
import yaml
from func.operation import my_add
# 方法一
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', [[1, 1, 2], [3, 6, 9], [100, 200, 300]])
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法二
# def get_data():
# with open("../data/data.yaml", encoding='utf-8') as f:
# data = yaml.safe_load(f)
# return data
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_data())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法三
# def get_excel():
# book = openpyxl.load_workbook("../data/test.xlsx")
# sheet = book.active
# cells = sheet["A1":"C3"]
# values = []
# for row in cells:
# data = []
# for cell in row:
# data.append(cell.value)
# values.append(data)
# return values
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_excel())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法四
def get_csv():
with open('../data/test.csv', encoding='utf-8') as f:
raw = csv.reader(f)
data = []
for line in raw:
data.append(line)
return data
class TestWithYAML:
@pytest.mark.parametrize('x,y,expected', get_csv())
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
4.pytest結(jié)合數(shù)據(jù)驅(qū)動(dòng)-json
json 文件介紹
-
json 是 JS 對象
-
全稱是 JavaScript Object Notation
-
是一種輕量級(jí)的數(shù)據(jù)交換格式
-
json 結(jié)構(gòu)
- 對象?
{"key": value}
- 數(shù)組?
[value1, value2 ...]
- 對象?
{
"name:": "tom",
"detail": {
"course": "python",
"city": "北京"
},
"remark": [1000, 666, 888]
}
?json 文件使用
- 查看 json 文件
- pycharm
- txt 記事本
- 讀取 json 文件
- 內(nèi)置函數(shù) open()
- 內(nèi)置庫 json
- 方法:
json.loads()
- 方法:
json.dumps()
?params.json
{
"case1": [1, 1, 2],
"case2": [3, 6, 9],
"case3": [100, 200, 300]
}
import json
def get_json():
with open('./data/params.json', 'r') as f:
data = json.loads(f.read())
print(data)
print(type(data))
s = json.dumps(data, ensure_ascii=False)
print(s)
print(type(s))
if __name__ == '__main__':
get_json()
代碼示例:
測試準(zhǔn)備
-
被測對象:
operation.py
-
測試用例:
test_add.py
-
測試數(shù)據(jù):
params.json
# operation.py 文件內(nèi)容
def my_add(x, y):
result = x + y
return result
# test_add.py 文件內(nèi)容
class TestWithJSON:
@pytest.mark.parametrize('x,y,expected', [[1, 1, 2]])
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
# params.json 文件內(nèi)容
{
"case1": [1, 1, 2],
"case2": [3, 6, 9],
"case3": [100, 200, 300]
}
import csv
import json
import openpyxl
import pytest
import yaml
from func.operation import my_add
# 方法一
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', [[1, 1, 2], [3, 6, 9], [100, 200, 300]])
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法二
# def get_data():
# with open("../data/data.yaml", encoding='utf-8') as f:
# data = yaml.safe_load(f)
# return data
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_data())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法三
# def get_excel():
# book = openpyxl.load_workbook("../data/test.xlsx")
# sheet = book.active
# cells = sheet["A1":"C3"]
# values = []
# for row in cells:
# data = []
# for cell in row:
# data.append(cell.value)
# values.append(data)
# return values
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_excel())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法四
# def get_csv():
# with open('../data/test.csv', encoding='utf-8') as f:
# raw = csv.reader(f)
# data = []
# for line in raw:
# data.append(line)
# return data
#
#
# class TestWithYAML:
# @pytest.mark.parametrize('x,y,expected', get_csv())
# def test_add(self, x, y, expected):
# assert my_add(int(x), int(y)) == int(expected)
# 方法五
def get_json():
with open('../data/params.json', 'r') as f:
data = json.loads(f.read())
print(data)
print(type(data))
print(list(data.values()))
return list(data.values())
class TestWithYAML:
@pytest.mark.parametrize('x,y,expected', get_json())
def test_add(self, x, y, expected):
assert my_add(int(x), int(y)) == int(expected)
5.pytest測試用例生命周期管理(一)
Fixture 特點(diǎn)及優(yōu)勢
- 1?命令靈活:對于 setup,teardown,可以不起這兩個(gè)名字
- 2?數(shù)據(jù)共享:在 conftest.py 配置?寫?法可以實(shí)現(xiàn)數(shù)據(jù)共享,不需要 import 導(dǎo)???梢钥?件共享
- 3?scope 的層次及神奇的?yield?組合相當(dāng)于各種 setup 和 teardown
- 4、實(shí)現(xiàn)參數(shù)化
Fixture 在自動(dòng)化中的應(yīng)用- 基本用法
- 場景:
測試?例執(zhí)?時(shí),有的?例需要登陸才能執(zhí)?,有些?例不需要登陸。
setup 和 teardown ?法滿?。fixture 可以。默認(rèn) scope(范圍)function
-
步驟:
- 1.導(dǎo)? pytest
- 2.在登陸的函數(shù)上?加@pytest.fixture()
- 3.在要使?的測試?法中傳?(登陸函數(shù)名稱),就先登陸
- 4.不傳?的就不登陸直接執(zhí)?測試?法。
import pytest
@pytest.fixture()
def login():
print('完成登錄操作')
def test_search():
print('搜索')
# def test_cart():
# login()
# print('購物車')
def test_cart(login):
print('購物車')
def test_order(login):
print('下單功能')
6.pytest測試用例生命周期管理(二)
Fixture 在自動(dòng)化中的應(yīng)用 - 作用域
取值 | 范圍 | 說明 |
---|---|---|
function | 函數(shù)級(jí) | 每一個(gè)函數(shù)或方法都會(huì)調(diào)用 |
class | 類級(jí)別 | 每個(gè)測試類只運(yùn)行一次 |
module | 模塊級(jí) | 每一個(gè).py 文件調(diào)用一次 |
package | 包級(jí) | 每一個(gè) python 包只調(diào)用一次(暫不支持) |
session | 會(huì)話級(jí) | 每次會(huì)話只需要運(yùn)行一次,會(huì)話內(nèi)所有方法及類,模塊都共享這個(gè)方法 |
import pytest
@pytest.fixture(scope="function")
def login():
print('完成登錄操作')
def test_search():
print('搜索')
# def test_cart():
# login()
# print('購物車')
def test_cart(login):
print('購物車')
def test_order(login):
print('下單功能')
class TestDemo:
def test_case1(self, login):
print("case1")
def test_case2(self, login):
print("case2")
7.pytest測試用例生命周期管理(三)
Fixture 在自動(dòng)化中的應(yīng)用 - yield 關(guān)鍵字
- 場景:
你已經(jīng)可以將測試?法【前要執(zhí)?的或依賴的】解決了,測試?法后銷毀清除數(shù)據(jù)的要如何進(jìn)?呢?
- 解決:
通過在 fixture 函數(shù)中加? yield 關(guān)鍵字,yield 是調(diào)?第?次返回結(jié)果,第?次執(zhí)?它下?的語句返回。
- 步驟:
在@pytest.fixture(scope=module)。在登陸的?法中加 yield,之后加銷毀清除的步驟
import pytest
'''
@pytest.fixture
def fixture_name():
setup 操作
yield 返回值
teardown 操作
'''
@pytest.fixture(scope="function")
def login():
#setup操作
print('完成登錄操作')
tocken = "abcdafafasdfds"
username = 'tom'
yield tocken,username #相當(dāng)于return
#teardown操作
print('完成登出操作')
def test_search():
print('搜索')
# def test_cart():
# login()
# print('購物車')
def test_cart(login):
print('購物車')
def test_order(login):
print('下單功能')
class TestDemo:
def test_case1(self, login):
print("case1")
def test_case2(self, login):
print("case2")
8.pytest測試用例生命周期管理-自動(dòng)注冊
Fixture 在自動(dòng)化中的應(yīng)用 - 數(shù)據(jù)共享
- 場景:
與其他測試?程師合作?起開發(fā)時(shí),公共的模塊要放在?家都訪問到的地?。
- 解決:
使? conftest.py 這個(gè)?件進(jìn)?數(shù)據(jù)共享,并且他可以放在不同位置起著不同的范圍共享作?。
-
前提:
- conftest ?件名是不能換的
- 放在項(xiàng)?下是全局的數(shù)據(jù)共享的地?
-
執(zhí)?:
- 系統(tǒng)執(zhí)?到參數(shù) login 時(shí)先從本模塊中查找是否有這個(gè)名字的變量什么的,
- 之后在 conftest.py 中找是否有。
-
步驟:
將登陸模塊帶@pytest.fixture 寫在 conftest.py 里面
代碼示例:
conftest.py
# conftest.py名字是固定的,不能改變
import pytest
@pytest.fixture(scope="function")
def login():
# setup操作
print('完成登錄操作')
tocken = "abcdafafasdfds"
username = 'tom'
yield tocken, username # 相當(dāng)于return
# teardown操作
print('完成登出操作')
test_test1.py
import pytest
'''
@pytest.fixture
def fixture_name():
setup 操作
yield 返回值
teardown 操作
'''
def test_search():
print('搜索')
# def test_cart():
# login()
# print('購物車')
def test_cart(login):
print('購物車')
def test_order(login):
print('下單功能')
class TestDemo:
def test_case1(self, login):
print("case1")
def test_case2(self, login):
print("case2")
項(xiàng)目結(jié)構(gòu):
9.pytest測試用例生命周期管理-自動(dòng)生效
Fixture 在自動(dòng)化中的應(yīng)用 - 自動(dòng)應(yīng)用
場景:
不想原測試?法有任何改動(dòng),或全部都?動(dòng)實(shí)現(xiàn)?動(dòng)應(yīng)?,
沒特例,也都不需要返回值時(shí)可以選擇?動(dòng)應(yīng)?
解決:
使? fixture 中參數(shù) autouse=True 實(shí)現(xiàn)
步驟:
在?法上?加?@pytest.fixture(autouse=True)
test_test1.py
import pytest
'''
@pytest.fixture
def fixture_name():
setup 操作
yield 返回值
teardown 操作
'''
def test_search():
print('搜索')
# def test_cart():
# login()
# print('購物車')
# def test_cart(login):
# print('購物車')
def test_cart():
print('購物車')
# def test_order(login):
# print('下單功能')
def test_order():
print('下單功能')
class TestDemo:
# def test_case1(self, login):
# print("case1")
def test_case1(self):
print("case1")
# def test_case2(self, login):
# print("case2")
def test_case2(self):
print("case2")
?conftest.py
# conftest.py名字是固定的,不能改變
import pytest
@pytest.fixture(scope="function", autouse=True)
def login():
# setup操作
print('完成登錄操作')
tocken = "abcdafafasdfds"
username = 'tom'
yield tocken, username # 相當(dāng)于return
# teardown操作
print('完成登出操作')
運(yùn)行結(jié)果:
?
?10.pytestfixture實(shí)現(xiàn)參數(shù)化
Fixture 在自動(dòng)化中的應(yīng)用 -參數(shù)化
場景:
測試離不開數(shù)據(jù),為了數(shù)據(jù)靈活,?般數(shù)據(jù)都是通過參數(shù)傳的
解決:
fixture 通過固定參數(shù) request 傳遞
步驟:
在 fixture 中增加@pytest.fixture(params=[1, 2, 3, ‘linda’])文章來源:http://www.zghlxwxcb.cn/news/detail-631892.html
在?法參數(shù)寫 request,方法體里面使用 request.param 接收參數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-631892.html
# @pytest.fixture(params=['tom', 'jenny'])
# def login(request):
# print(f"用戶名:{request.param}")
# return request.param
#
#
# def test_demo1(login):
# print(f'demo1 case:數(shù)據(jù)為{login}')
@pytest.fixture(params=[['tom', 'harry'], ['jenny', 'jack']])
def login(request):
print(f"用戶名:{request.param}")
return request.param
def test_demo1(login):
print(f'demo1 case:數(shù)據(jù)為{login}')
Fixture 的用法總結(jié)
- 模擬 setup,teardown(一個(gè)用例可以引用多個(gè) fixture)
- yield 的用法
- 作用域( session,module, 類級(jí)別,方法級(jí)別 )
- 自動(dòng)執(zhí)行 (autouse 參數(shù))
- conftest.py 用法,一般會(huì)把 fixture 寫在 conftest.py 文件中(這個(gè)文件名字是固定的,不能改)
- 實(shí)現(xiàn)參數(shù)化
到了這里,關(guān)于Pytest測試框架3的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!