Pytest
- 是一个命令行工具,编写用例简单,可读性强
- 非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考
- 支持单元测试和功能测试
- 支持参数化
- 执行测试过程中可以将某些测试跳过,或者对某些预期失败的Case标记成失败
- 支持重复执行失败的Case
- 支持运行由unittest编写的测试Case
- 具有很多第三方插件,并且可以自定义扩展
- 方便的和持续集成工具集成
- 可以运行以test开头或test结尾的包、文件和方法
- 可以使用assert进行断言
下面是pytest例子
import pytest
def test_1():
print('test_11111111')
def test_2():
print('test_222222222')
def xxx_1(): # 不会执行
print("xxx_11111111")
class TestDemo(object): # 如果类名不是以Test开头,也不执行
def test_3(self):
print('test_33333333')
def test_4(self):
print('test_44444444')
def xxx_2(self): # 不会执行
print("xxx_22222222")
if __name__ == '__main__':
# 默认不打印,需要加上-s参数, []中元素是字符串
pytest.main(['-s'])
=====================================================
pytest -s # 运行当前目录所有test开头的文件
pytest -s xxx.py # 运行指定的文件
# 代码
pytest.main(['-s'])
pytest.main(['-s', 'xxx.py'])
断言的处理
- assert:预期结果、实际结果,对比
- 异常断言:预期异常、实际异常,对比
- 警告断言:预期警告、实际警告,对比
# assert断言语句
def test_1():
num = 1 + 1
# assert 条件, 产生异常的提示信息
assert num == 3, 'num==2条件不满足'
==============================================
# 异常断言
# 前面加上_,为了不让其执行
def _test_1():
# with pytest.raises(预期的异常类型):
# 实际产生的异常
# 如果实际产生的异常和预期的异常类型一样,测试通过
# with pytest.raises(TypeError):
with pytest.raises(ValueError):
is_leap_year('2020') # 产生TypeError
def test_2():
# with pytest.raises(预期的异常类型) as 异常对象:
# 实际产生的异常
# 如果实际产生的异常和预期的异常类型一样,测试通过
with pytest.raises(TypeError) as err_info:
is_leap_year('2020') # 产生TypeError
if err_info.type == TypeError:
print('err_info保存了异常信息')
# 通过异常的内容捕捉异常
def test_3():
# 断言:预期异常为ValueError,同时内容为"传入的参数不是正整数"
with pytest.raises(ValueError, match="传入的参数不是正整数") as err_info:
is_leap_year(-100) # 产生ValueError
if err_info.type == ValueError:
print('err_info保存了异常信息')
==================================================================
# 警告断言
import warnings
import pytest
# 前面加上_,为了不让其执行
def _test_1():
# with pytest.warns(预期的警告类型):
# 实际产生的警告
# 如果实际产生的警告和预期的警告类型一样,测试通过
with pytest.warns(RuntimeWarning):
warnings.warn("my warning", RuntimeWarning)
def _test_2():
# 警告断言,可以同时断言多个,异常不可以
with pytest.warns((RuntimeWarning, UserWarning)) as warn_info:
warnings.warn("my warning aaaaa", RuntimeWarning)
warnings.warn("value must be 0 or None", UserWarning)
# print('11111111111111')
# warn_info对象的成员,它是列表
print(warn_info.__dict__)
print(len(warn_info))
print(warn_info[0].__dict__) # 第0个对象的成员信息
print(warn_info[0].category)
print(warn_info[0].message)
def test_3():
# 断言: 警告为RuntimeWarning,通过内容包含warning
with pytest.warns(RuntimeWarning, match='warning'):
warnings.warn("my warning", RuntimeWarning)
if __name__ == '__main__':
# 默认不打印,需要加上-s参数, []中元素是字符串
pytest.main(['-s', 'test_5_warns.py'])
setup和teardown函数
-
函数级别:
- 作用域为普通函数
- setup_function, teardown_function,普通测试用例函数前后执行一次
-
类级别
- 作用域为类:类、实例方法
- setup_class 和 teardown_class , 类的前后执行1次
- setup_method, teardown_method,测试用例实例方法前后各执行1次
-
模块级别
- 作用域:运行的文件
- setup_module(), teardown_module() 定义在类外
- 文件的前后,执行1次
pytest.mark.parametrize用法
import pytest
@pytest.mark.parametrize(['usrname', 'pwd'], [('mike', '123'), ('yoyo', 'abc')])
def test_login(usrname, pwd):
print('usrname = %s, pwd = %s' % (usrname, pwd))
Yaml
Yaml 是一种所有编程语言可用的友好的数据序列化标准,类似于 json。其语法和其他高阶语言类似, 并且可以简单表达列表、字典、标量等资料形式。
<大部分以空格来间隔数据>
读取yaml文件
{ Search_Data:
{
search_test_001: { value: 456, expect: [ 4, 5, 6 ] },
search_test_002: { value: '你好', expect: { value: '你好' } }
}
}
====================================================================
import yaml
# 1. 只读方式打开文件,文件对象
# 2. 读取内容 = yaml.load(文件对象, Loader=yaml.FullLoader)
with open('./info.yaml') as f:
ret = yaml.load(f, Loader=yaml.FullLoader)
print(ret)
写入yaml文件内容
import yaml
data={'Search_Data': {
'search_test_002': {'expect': {'value': '你好'}, 'value': '你好'},
'search_test_001': {'expect': [4, 5, 6], 'value': 456}
}
}
# 1. 只写方式,指定utf-8编码打开文件,有一个文件对象
# 2. yaml.dump(写入文件的数据, 上一步的文件对象, allow_unicode=True)
with open('xxx.yaml', 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True)