Pytest是Python实现的一个测试工具,可以用于所有类型和级别的软件测试。
Pytest是一个可以自动查找到你编写的用例并运行后输出结果的测试框架。
Pytest的特点:
Pytest 安装
pip install -U pytest -i https://pypi.tuna.tsinghua.edu.cn/simple
- import pytest
- import requests
-
-
- def test_one():
- r = requests.get('https://www.baidu.com')
- print(r.status_code)
-
- def test_two():
- r = requests.get('https://www.baidu.com')
- print(r.encoding)
-
- class TestTask(object):
- def test_1(self):
- print('test 1')
-
- def test_2(self):
- print('test 2')
-
- if __name__ == '__main__':
- pytest.main() # pytest
- ============================= test session starts ==============================
- platform darwin -- Python 3.7.3, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
- rootdir: /Users/xiaoyidemac/Desktop/测试
- plugins: tavern-1.16.3, openfiles-0.3.2, arraydiff-0.3, allure-pytest-2.9.45, doctestplus-0.3.0, remotedata-0.3.1collected 4 items
-
- pytest_code.py .200
- .ISO-8859-1
- [100%]
-
- ============================== 4 passed in 0.29s ===============================
-
- Process finished with exit code 0
- .test 1
- .test 2
通过代码中pytest.main()可以右键直接运行,相当于python test_1.py;也可以通过命令行的方式启动运行
代码中运行的方式
上述四种方式皆有对应的命令行运行的方式
注意:
- assert expression [, arguments]
- # expression 为 True 则 pass
- # expression 为 False 则 抛出异常,有 argument 则输出 argument
- '''
- expression:
- 1)比较运算
- 2)逻辑运算 and | or | not
- 3)身份运算 is | is not
- 4)成员运算 in | not in
- '''
示例代码:
- import requests
-
- def test_assert():
- r = requests.get('http://www.baidu.com')
- assert r.status_code == 200, "没有返回200,断言失败"
在测试过程中,对某些方法进行测试时,预测输入某些特定数据,会抛出某种异常,若出现该异常,则用例执行通过。
对这预期会出现的异常的断言,可以采用pytest中的pytest.raises()进行处理。
pytest.raises()的使用
- import pytest
-
-
- def is_leap_year(year):
- # 先判断year是不是整型
- if isinstance(year, int) is not True:
- raise TypeError("传入的参数不是整数")
- elif year == 0:
- raise ValueError("公元元年是从公元一年开始!!")
- elif abs(year) != year:
- raise ValueError("传入的参数不是正整数")
- elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
- print("%d年是闰年" % year)
- return True
- else:
- print("%d年不是闰年" % year)
- return False
-
-
- class TestAssert(object):
- """对判断是否是闰年的方法进行测试"""
-
- def test_exception_typeerror(self):
- # 使用 pytest.raises 作为上下文管理器,捕获给定异常类型TypeError
- # is_leap_year('2020')抛出TypeError,被pytest.raises捕获到,则测试用例执行通过
- with pytest.raises(TypeError):
- # 传入字符串引发类型错误
- is_leap_year('2020')
运行结果如下:
- ============================= test session starts ==============================
- platform darwin -- Python 3.7.3, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
- rootdir: /Users/xiaoyidemac/Desktop/测试
- plugins: tavern-1.16.3, openfiles-0.3.2, arraydiff-0.3, allure-pytest-2.9.45, doctestplus-0.3.0, remotedata-0.3.1collected 1 item
-
- pytest_code.py [100%]
-
- ============================== 1 passed in 0.06s ===============================
有时候我们可能需要在测试用到产生的异常信息,我们可以把异常信息存储到一个变量中,变量的类型为 异常类 ,包含异常的 type、value 或者 traceback 等信息。
- import pytest
-
- def is_leap_year(year):
- # 先判断year是不是整型
- if isinstance(year, int) is not True:
- raise TypeError("传入的参数不是整数")
- elif year == 0:
- raise ValueError("公元元年是从公元一年开始!!")
- elif abs(year) != year:
- raise ValueError("传入的参数不是正整数")
- elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
- print("%d年是闰年" % year)
- return True
- else:
- print("%d年不是闰年" % year)
- return False
-
- class TestAssert(object):
- """对判断是否是闰年的方法进行测试"""
-
- def test_exception_typeerror(self):
- # 预测到参数不符合要求,会抛出TypeError异常;若出现该异常,则测试用例执行通过
- with pytest.raises(TypeError) as err_info:
- # 传入字符串引发类型错误
- is_leap_year('2020')
- # 断言异常的类型是 TypeError,断言成功则不会抛出异常
- assert err_info.type == TypeError, '错误类型不匹配'
通过异常的内容捕捉异常
- import pytest
-
- def is_leap_year(year):
- # 先判断year是不是整型
- if isinstance(year, int) is not True:
- raise TypeError("传入的参数不是整数")
- elif year == 0:
- raise ValueError("公元元年是从公元一年开始!!")
- elif abs(year) != year:
- raise ValueError("传入的参数不是正整数")
- elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
- print("%d年是闰年" % year)
- return True
- else:
- print("%d年不是闰年" % year)
- return False
-
-
- class TestAssert(object):
- """对判断是否是闰年的方法进行测试"""
- def test_exception_typeerror(self):
- # 通过异常的内容捕捉异常,但具体是何种异常不清楚
- with pytest.raises(Exception, match='从公元一年开始') as err_info:
- is_leap_year(0)
- # 断言异常的类型是 ValueError,断言成功则不会抛出异常
- assert err_info.type == ValueError
- import pytest
- import warnings
-
- def make_warn():
- # 抛出
- warnings.warn("deprecated", DeprecationWarning)
-
- def not_warn():
- pass
-
- def user_warn():
- warnings.warn("user warn", UserWarning)
-
-
- class TestWarns(object):
- def test_make_warn(self):
- with pytest.warns(DeprecationWarning):
- make_warn()
-
- def test_not_warn(self):
- # 断言not_warn函数将会抛出警告
- # 但实际是没有抛出警告的,所以无法通过测试
- with pytest.warns(Warning):
- not_warn()
-
- def test_user_warn(self):
- with pytest.warns(UserWarning):
- user_warn()
运行结果如下:
-
- ================================================== test session starts ===================================================
- platform linux -- Python 3.6.8, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
- rootdir: /home/python/code/unit_testing/pytest_code
- collected 3 items
-
- test_7.py .F. [100%]
-
- ======================================================== FAILURES ========================================================
- ________________________________________________ TestWarns.test_not_warn _________________________________________________
-
- self =
-
- def test_not_warn(self):
- with pytest.warns(Warning):
- > not_warn()
- E Failed: DID NOT WARN. No warnings of type (,) was emitted. The list of emitted warnings is: [].
-
- test_7.py:24: Failed
- ================================================ short test summary info =================================================
- FAILED test_7.py::TestWarns::test_not_warn - Failed: DID NOT WARN. No warnings of type (,) was emitted...
- ============================================== 1 failed, 2 passed in 0.04s ===============================================
将告警信息存入一个变量中,通过读取这个变量中的信息进行断言,包括:告警的个数、告警信息参数等。
- # pytest_code/test_8.py
- import warnings
- import pytest
-
- def warn_message():
- warnings.warn("user", UserWarning)
- warnings.warn("runtime", RuntimeWarning)
-
- def test_warn_match():
- with pytest.warns((UserWarning, RuntimeWarning)) as record:
- warn_message()
- assert len(record) == 2
- assert str(record[0].message) == "user"
- assert str(record[1].message) == "runtime"
- assert record[0].category == UserWarning
- assert record[1].category == RuntimeWarning
运行结果如下:
- $ pytest test_8.py
- ================================================== test session starts ===================================================
- platform linux -- Python 3.6.8, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
- rootdir: /home/python/code/unit_testing/pytest_code
- collected 1 item
-
- test_8.py . [100%]
-
- =================================================== 1 passed in 0.01s ====================================================
- # pytest_code/test_9.py
- import warnings
- import pytest
-
-
- def make_warn():
- # 抛出
- warnings.warn("deprecated", DeprecationWarning)
-
-
- def not_warn():
- pass
-
- def user_warn():
- warnings.warn("user warn", UserWarning)
-
-
- class TestWarns(object):
- def test_make_warn(self):
- # 捕获警告内容为deprecated的警告
- with pytest.warns(Warning, match='deprecated'):
- make_warn()
这个大纲涵盖了目前市面上企业百分之99的技术,这个大纲很详细的写了你该学习什么内容,企业会用到什么内容。总共十个专题足够你学习
这里我准备了对应上面的每个知识点的学习资料、可以自学神器,已经项目练手。
最后送上一句话:
世界的模样取决于你凝视它的目光,自己的价值取决于你的追求和心态,一切美好的愿望,不在等待中拥有,而是在奋斗中争取。
如果我的博客
对你有帮助、如果你喜欢我的文章内容,请 “点赞” “评论” “收藏” 一键三连哦!