1、简介
pytest是Python的另一个第三方单元测试库。它的目的是让单元测试变得更容易,并且也能扩展到支持应用层面复杂的功能测试。
特性:
- 支持用简单的assert语句实现丰富的断言,无需复杂的self.assert*函数
- 自动识别测试模块和测试函数
- 模块化夹具用以管理各类测试资源
- 对unittest完全兼容,对nose基本兼容
- 支持Python3和PyPy3
- 丰富的插件生态,已有300多个各式各样的插件,社区繁荣
2、pytest与unittest的区别
3、pytest安装
安装命令:pip install pytest
验证命令:pytest --version
(打印版本号即为成功)
示例:
4、pytest规则
pytest是如何去寻找要执行的测试用例的
- pytest将在当前目录及其子目录中运行所有格式为test_.py或者_test.py的文件
- 类必须以Test开头
官方:它遵循标准的测试发现规则,官方文档如下:
1、如果未指定任何参数,则从当前目录或testpaths(如果pytest.ini已配置)开始,另外,命令行参数可以在目录、文件名、节点ID的任何组合中使用
2、递归到目录,除非它们匹配norecursedirs(pytest.ini配置)
3、在这些目录中,搜索test_*.py或*_test.py,在这个文件中,搜索测试项目
* 在类之外拥有test前缀的测试函数或方法
* 在拥有Test前缀中的测试类(不含__init__方法)中拥有test前缀的测试函数或方法
4、也可以自定义测试发现规则(兼容unittest的原因)
5、pytest断言
代码示例:
import pytest
from selenium import webdriver
from time import sleep
"""
借助python的运算符号和关键字实现不同数据类型的断言
"""
# 百度搜索案例
def test_baidu_search():
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
driver.find_element_by_id("kw").send_keys("哈哈哈")
driver.find_element_by_id("su").click()
sleep(3)
# == 断言
# 窗口的 title判断
web_title = driver.title
assert "哈哈哈_百度搜索" == web_title
driver.quit()
print("driver已退出!")
# != 测试不相等
# <= 测试小于等于
# >= 测试大于等于
# in 测试包含
# not in 测试不包含
# 判断是否为true
# 判断是否为False
if __name__ == '__main__':
# -s:打印测试用例的print信息
# test_assert.py : 只扫描该文件
pytest.main(["-s", "test_assert.py"])
6、pytest参数化
import pytest
from selenium import webdriver
from time import sleep
"""
pytest 参数化
当一组测试用例有固定的测试数据时,就可以通过参数化的方式简化测试用例的编写
通过pytest.mark.parametrzie()方法设置参数:
参数名:"search_key,expected"
参数值:通过数组定义参数值时,每一个元组都是一条测试用例的测试数据
ids参数:默认None,用来重新定义测试用例的名称
"""
# 百度搜索案例
# 参数化
@pytest.mark.parametrize(
"search_key,expected",
[
("哈哈哈", "哈哈哈_百度搜索"),
("呵呵呵", "呵呵呵_百度不想搜索"),
],
ids=["case1", "case2"]
)
def test_baidu_search(search_key, expected):
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
driver.find_element_by_id("kw").send_keys(search_key)
driver.find_element_by_id("su").click()
sleep(3)
# == 断言
# 窗口的 title判断
web_title = driver.title
assert expected == web_title
driver.quit()
print("driver已退出!")
if __name__ == '__main__':
pytest.main(["-s", "test_param.py"])
7、pytest常用运行参数
-s 打印信息
-v 显示详细信息
-k 运行包含某个字符串的测用例
-q 简化控制台输出信息
-x 如果执行到失败的用例,则停止测试
运行测试目录:pytest.main["-s","/test_dir"]
指定特定类或方法:pytest.main("-s","xxx.py::类名") pytest.main("-s","xxx.py::方法名")
import pytest
from selenium import webdriver
from time import sleep
"""
借助python的运算符号和关键字实现不同数据类型的断言
"""
# 百度搜索案例
def test_baidu_search():
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
driver.find_element_by_id("kw").send_keys("哈哈哈")
driver.find_element_by_id("su").click()
sleep(3)
# == 断言
# 窗口的 title判断
web_title = driver.title
assert "哈哈哈_百度搜索" == web_title
driver.quit()
print("driver已退出!")
def test_fun1():
assert 1 == 1
print("fun1")
if __name__ == '__main__':
# -s:打印测试用例的print信息
# test_assert.py : 只扫描该文件
pytest.main(["-s", "test_assert.py"])
# pytest.main(["-v", "-s", "test_assert.py"])
# pytest.main(["-k", "fun", "-s", "test_assert.py"])
# pytest.main(["-q", "test_assert.py"])
# pytest.main(["-x", "test_assert.py"])
# pytest.main(["-s", "test_assert.py::test_fun1"])
8、生成测试报告
8.1、生成JunitXML测试报告:
cmd进入测试用例目录,执行:
pytest xxx.py --junit-xml=./report/log01.xml
8.2、生成在线测试报告:
cmd进入测试用例目录,执行:
pytest xxx.py --pastebin=all
控制台最后会生成URL链接
9、控制测试用例执行
- 出现n个测试用例失败,则结束测试执行
pytest --maxfail=2 #出现2个用例失败则终止测试
import pytest
# 失败
def test_fail01():
print("第一次失败")
assert 1 == 2
def test_fail02():
print("第二次失败")
assert 1 == 2
def test_fail03():
print("第三次成功")
assert 1 == 1
if __name__ == '__main__':
# 失败两次停止测试,第三条用例不会执行
pytest.main(["--maxfail=2", "test_fail.py"])
10、多进程运行用例
- 安装pytest-xdist
pip install pytest-xdist
- 运行模式
pytest -n NUMCPUS
- 代码示例
import pytest
def test_case01():
assert 1 == 1
def test_case02():
assert 1 == 1
if __name__ == '__main__':
# 使用两核CPU跑用例
# pytest.main(["-s", "-n", "2", "test_many.py"])
# CPU满核跑用例
pytest.main(["-s", "-n", "auto", "test_many.py"])
11、通过标记执行用例
pytest -m flag
这条命令会执行被装饰器@pytest.mark.flag 装饰的所有测试用例
1、在测试用例.py同目录创建初始化文件pytest.ini
2、新建标记名,示例
[pytest]
markers =
flag
代码示例:
import pytest
@pytest.mark.flag
def test_case01():
assert 1 == 1
def test_case02():
assert 1 == 2
if __name__ == '__main__':
# 只会执行带flag标记的用例
# pytest.main(["-m", "flag", "test_mark.py"])
# 不会执行带flag标记的用例
pytest.main(["-m", "not flag", "test_mark.py"])