pytest 使用
pytest的使用
安装
pip install pytest
pytest 测试发现约定
- 如未指定任何参数,则收集从testpaths (如果已配置:可以通过pytest.ini配置文件发现路径,配置文件只在当前目录下生效),或当前目录开始。
pytest.ini文件
[pytest]
testpaths = testing doc
注意格式:用例发现路径用空格隔开,关键字不能写错
- 命令行参数可以在目录,文件名或者节点ID的任何组合中使用。
if __name__ == '__main__':
# pytest.main(['-s']) # '-s' 表示输出打印信息,pytest默认是不输出打印信息的
pytest.main(['-s','./testing/test_demo1.py::test_001'])
- 在当前目录及其子目录中运行所有格式为test_.py或者_test.py文件,从这些文件中收集测试项目。
- 在类之外拥有test前缀的测试函数或方法
test_demo1.py
def test_demo1():
print("hello world")
- 在拥有Test前缀中的测试类(不含_init_方法)中的拥有test前缀的测试函数或方法
test_demo2.py
class TestDemo():
#测试 方法
def test_range_match(self,kdtid,expected):
print("hello world")
- 可以自定义测试发现规则,比如忽略掉一些目录
if __name__ == '__main__':
# 自定义测试发现规则,比如忽略掉一些目录
pytest.main(['-s', '--ignore=testing/', '--ignore=doc/'])
- pytest也可以发现使用标准的unittest.TestCase子类技术的测试用例(完全兼容unittest)
pytest参数化
当一组测试用例有固定的测试数据时,就可以通过参数化的方式简化测试用例的编写。通过pytest.mark.parametrzie()方法设置参数:
- 参数名:"user,pw,expected"用来定义参数的名称
- 参数值:通过数组定义参数值时,每一个元祖都是一条测试用例的测试数据
- ids参数:默认None,用来重新定义测试用例的名称
@pytest.mark.parametrize(
"user,pwd,expected",
[( "test1","aaa","ok"),
( "test2","bbb","false"),
( "test3","ccc","unknow")],
ids=["test_case1","test_case2","test_case3"]
)
def test_parametrize(user,pwd,expected):
print(user,pwd,expected)
pytest中的setup和tearDow
有些测试用例需要在跑测试case前先初始化一下数据,当测试case 结束的时候就需要清理一下测试环境的数据。在java 中存在 @BeforeClass,@AfterClass
pytest 中也存在
import pytest
def setup_module(module):
"""
这是一个module级别的setup,它会在本module(test_website.py)里
所有test执行之前,被调用一次。
注意,它是直接定义为一个module里的函数"""
print()
print("-------------- setup before module --------------")
def teardown_module(module):
"""
这是一个module级别的teardown,它会在本module(test_website.py)里
所有test执行完成之后,被调用一次。
注意,它是直接定义为一个module里的函数"""
print("-------------- teardown after module --------------")
# Test前缀中的测试类
class TestDemo1(object):
def test_login(self):
print("test baidu login function")
assert True == True
class TestSohu(object):
@classmethod
def setup_class(cls):
""" 这是一个class级别的setup函数,它会在这个测试类TestSohu里
所有test执行之前,被调用一次.
注意它是一个@classmethod
"""
print("------ setup before class TestSohu ------")
@classmethod
def teardown_class(cls):
""" 这是一个class级别的teardown函数,它会在这个测试
类TestSohu里所有test执行完之后,被调用一次.
注意它是一个@classmethod
"""
print("------ teardown after class TestSohu ------")
def setup_method(self, method):
""" 这是一个method级别的setup函数,它会在这个测试
类TestSohu里,每一个test执行之前,被调用一次.
"""
print("--- setup before each method ---")
def teardown_method(self, method):
""" 这是一个method级别的teardown函数,它会在这个测试
类TestSohu里,每一个test执行之后,被调用一次.
"""
print("--- teardown after each method ---")
def test_login(self):
print("sohu login")
assert True == True
def test_logout(self):
print("sohu logout")
pytest.skip()
pytest.ini 配置文件
将这个配置文件放在项目目录的最外层
[pytest]
; 命令行窗口日志输出配置
; log_cli 可以输入0, False 代码不输出日志, 1、True 代表开启日志输出
; log_cli_level 代表日志输出级别
; log_cli_date_format 日期格式
; log_cli_format 日志模板格式
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S
; 日志输出到文件配置
; log_file 日志文件
; log_file_level 代表日志输出级别
; log_file_date_format 日期格式
; log_file_format 日志模板格式
log_file=outputs/logs/test.log
log_file_level=INFO
log_file_date_format=%Y-%m-%d %H:%M:%S
log_file_format=%(asctime)s %(filename)s %(module)s %(funcName)s %(lineno)d %(levelname)s: %(message)s
; 在配置文件中加上启动参数选项
; -v 详细信息, -s 打印信息
; --reruns=1 --reruns-delay=5 表示失败延迟5秒重新运行一次,需要 pip install pytest-rerunfailures
; --html=reports.html --self-contained-html 生成html 报告 pip install pytest-html
addopts = -v -s --reruns=1 --reruns-delay=5 --html=reports.html --self-contained-html
运行测试用例
pytest 存在两种方式运行测试用例,一种是使用pytest
命令 一种是卸载 main
函数中
命令行的方式运行
#指定测试方法,当前项目目录下的demo_test.py的TestDemo是类,test_demo1 是测试方法
pytest py-test/demo/demo_test.py::TestDemo::test_demo1
# 如果没有类的话也可以直接指定方法
pytest py-test/demo/demo_test.py::test_demo2
# --pdb 当测试方法遇到错误的时候会中断,可以进行调试
pytest --pdb py-test/demo/demo_test.py::TestDemo::test_demo1
代码中执行
if __name__ == '__main__':
pytest.main(['-s','py-test/demo/demo_test.py::TestDemo::test_demo1'])
参考
不自见,故明;不自是,故彰;不自伐,故有功;不自矜,故长