一 . Pytest 簡介
Pytest是python的一種單元測試框架。
1. pytest 特點
- 入門簡單,文檔豐富
- 支持單元測試,功能測試
- 支持參數(shù)化,重復執(zhí)行,部分執(zhí)行,測試跳過
- 兼容其他測試框架(nose,unittest 等)
- 支持生成html報告
- 可集成CI環(huán)境(Jenkins 等)
- 第三方插件豐富,良好的自定義擴展性
2. pytest 與 unittest
(1)unittest
- 測試文件必須先 import unittest
- 測試類必須繼承unittest.TestCase
- 測試方法必須以“test_”開頭
- 測試類必須要有unittest.main()方法
- unittest只有setup/teardown裝載測試用例
- ...
(2)pytest
- 測試文件名必須以“test_”開頭
- 測試類以Test開頭,并且不能帶有 init 方法
- 測試方法必須以“test_”開頭
- 除了有setup/teardown,還能更自由的定義fixture裝載測試用例
- ...
(3)Comparison Table
Pytest vs Unittest
二 . Pytest 安裝
# 安裝
pip install -U pytest
# 查看安裝版本
pip show pytest
# 或者
pytest --version
三 . Pytest 運行
一個簡單的例子 test_class.py:
# test_class.py
class TestClass:
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
1. cmd 中運行測試用例
# cmd中 cd到 test_class.py所在文件夾
# 運行 該文件夾中所有測試用例
pytest
# 或者
py.test
# 運行指定測試用例,加上-q參數(shù)用來指定執(zhí)行的文件
pytest -q test_class.py
pytest運行規(guī)則:
查找當前目錄及其子目錄下以test_.py或_test.py文件,
找到文件后,在文件中找到以test開頭函數(shù)并執(zhí)行。
2. pycharm 中運行測試用例
一個簡單的例子 test_sample.py:
# content of test_sample.py
import pytest
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
if __name__ == "__main__":
pytest.main('-q test_sample.py')
pycharm中運行pytest:
- file->Setting->Tools->Python Integrated Tools->項目名稱->Default test runner->選擇py.test
- 右鍵選擇pytest運行或者直接運行.py文件
四 . Pytest 裝飾器
1. setup 與 teardown
裝載運行級別:
- 模塊級(setup_module/teardown_module)開始于模塊始末
- 類級(setup_class/teardown_class)只在類中前后運行一次(在類中)
- 方法級(setup_method/teardown_method)開始于方法始末(在類中)
- 類里面的(setup/teardown)運行在調(diào)用方法的前后
- 函數(shù)級(setup_function/teardown_function)只對函數(shù)用例生效(不在類中)
一個簡單的例子 test_module.py:
# -*- coding: utf-8 -*-
# Version : V1.0
# Author : Seven
# Date : 2018/8/2 19:41
import pytest
# 模塊中的方法
def setup_module():
print("setup_module:整個.py模塊只執(zhí)行一次")
def teardown_module():
print("teardown_module:整個test_module.py模塊只執(zhí)行一次")
def setup_function():
print("setup_function:每個用例開始前都會執(zhí)行")
def teardown_function():
print("teardown_function:每個用例結(jié)束后都會執(zhí)行")
# 測試模塊中的用例1
def test_one():
print("正在執(zhí)行測試模塊----test_one")
x = "this"
assert 'h' in x
# 測試模塊中的用例2
def test_two():
print("正在執(zhí)行測試模塊----test_two")
x = "hello"
assert hasattr(x, 'check')
# 測試類
class TestCase():
def setup_class(self):
print("setup_class:所有用例執(zhí)行之前")
def teardown_class(self):
print("teardown_class:所有用例執(zhí)行之后")
def setup(self):
print("setup:每個用例開始前都會執(zhí)行")
def teardown(self):
print("teardown:每個用例結(jié)束后都會執(zhí)行")
def test_three(self):
print("正在執(zhí)行測試類----test_three")
x = "this"
assert 'h' in x
def test_four(self):
print("正在執(zhí)行測試類----test_four")
x = "hello"
assert hasattr(x, 'check')
if __name__ == "__main__":
pytest.main(["-s", "test_module.py"])
運行的效果:
collected 4 items
test_module.py setup_module:整個.py模塊只執(zhí)行一次
setup_function:每個用例開始前都會執(zhí)行
正在執(zhí)行測試模塊----test_one
.teardown_function:每個用例結(jié)束后都會執(zhí)行
setup_function:每個用例開始前都會執(zhí)行
正在執(zhí)行測試模塊----test_two
Fteardown_function:每個用例結(jié)束后都會執(zhí)行
setup_class:所有用例執(zhí)行之前
setup:每個用例開始前都會執(zhí)行
正在執(zhí)行測試類----test_three
.teardown:每個用例結(jié)束后都會執(zhí)行
setup:每個用例開始前都會執(zhí)行
正在執(zhí)行測試類----test_four
Fteardown:每個用例結(jié)束后都會執(zhí)行
teardown_class:所有用例執(zhí)行之后
teardown_module:整個test_module.py模塊只執(zhí)行一次
從結(jié)果看出:
- setup_module/teardown_module的優(yōu)先級是最大的
- 然后函數(shù)里面的setup_function/teardown_function與類里面的setup_class/teardown_class互不干涉
2. fixture
一個簡單的例子 test_fixture.py:
# conftest.py
# -*- coding: utf-8 -*-
import pytest
@pytest.fixture(scope="function")
def login():
print("請先輸入賬號和密碼,然后登陸")
yield
print("退出登陸")
# test_1.py
# -*- coding: utf-8 -*-
import pytest
def test_fix1(login):
print("test_fix1 in test_1.py:需要登陸再執(zhí)行操作")
def test_fix2():
print("test_fix2 in test_1.py:不需要登陸再執(zhí)行操作")
def test_fix3(login):
print("test_fix3 in test_1.py:需要登陸再執(zhí)行操作")
if __name__ == "__main__":
pytest.main(['-s', 'test_1.py'])
# test_2.py
# -*- coding: utf-8 -*-
import pytest
def test_fix3():
print("test_fix3 in test_2.py:不需要登陸再執(zhí)行操作")
def test_fix4(login):
print("test_fix4 in test_2.py:需要登陸再執(zhí)行操作")
if __name__ == "__main__":
pytest.main(['-s', 'test_2.py'])
文件結(jié)構(gòu):
conftest configuration
運行效果:
pytest -s test_1.py
collected 3 items
test_1.py 請先輸入賬號和密碼,然后登陸
test_fix1 in test_1.py:需要登陸再執(zhí)行操作
.退出登陸
test_fix2 in test_1.py:不需要登陸再執(zhí)行操作
.請先輸入賬號和密碼,然后登陸
test_fix3 in test_1.py:需要登陸再執(zhí)行操作
.退出登陸
pytest -s test_2.py
collected 2 items
test_2.py test_fix3 in test_2.py:不需要登陸再執(zhí)行操作
.請先輸入賬號和密碼,然后登陸
test_fix4 in test_2.py:需要登陸再執(zhí)行操作
.退出登陸
從結(jié)果看出:
(1) scope 參數(shù) 實現(xiàn)控制 setup 級別
(2) conftest.py 配置 實現(xiàn)跨文件調(diào)用裝飾器
(3) yield 實現(xiàn) teardown
五 . Pytest 斷言
- pytest允許使用python的標準assert語句進行斷言處理
六 . Pytest 自動生成報告
# 生成xml格式的報告
pytest -v test_1.py --junitxml=Path
# 生成txt格式的報告
pytest -v test_1.py --resultlog=Path
# 生成html格式的報告
# 需預先裝上pytest-html
pip install pytest_html
pytest -v test_1.py --html=Path
生成報告效果圖:
pytest_report