[TOC]python
pytest
安装与入门
1.pip install -U pytest
2.建立一个test01.py的文件
def func(x): return x + 1 def test_answer(): assert func(3) == 5
3.在该目录下执行pytest(venv)
D:\4_code\study>pytest ============================= test session starts ============================= platform win32 -- Python 3.6.2, pytest-3.7.1, py-1.5.4, pluggy-0.7.1 rootdir: D:\4_code\study, inifile: collected 1 itemjson
test01.py . [100%]session
========================== 1 passed in 0.19 seconds ===========================ide
(venv) D:\4_code\study>pytest测试
4.执行多个,新建一个py文件 test02.py
def add(x, y): return x + y def test_add(): assert add(1, 0) == 1 assert add(1, 1) == 2 assert add(1, 99) == 100
执行pytestui
(venv) D:\4_code\study>pytest ============================= test session starts ============================= platform win32 -- Python 3.6.2, pytest-3.7.1, py-1.5.4, pluggy-0.7.1 rootdir: D:\4_code\study, inifile: collected 2 itemsthis
test01.py . [ 50%] test02.py . [100%]url
========================== 2 passed in 0.30 seconds ===========================spa
pytest
将在当前目录及其子目录中运行test _ * .py或* _test.py形式的全部文件。.net
5.在一个类中组合多个测试
一旦开发了多个测试,您可能但愿将它们分组到一个类中。pytest能够很容易地建立一个包含多个测试的类:
class TestClass(object): def test_one(self): x = "this" assert 'h' in x def test_two(self): x = "hello" assert hasattr(x, 'check')
(venv) D:\4_code\study>pytest ============================= test session starts ============================= platform win32 -- Python 3.6.2, pytest-3.7.1, py-1.5.4, pluggy-0.7.1 rootdir: D:\4_code\study, inifile: collected 4 items
test_calc.py . [ 25%] test_class.py .F [ 75%] test_quick_start.py . [100%]
================================== FAILURES =================================== _____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass object at 0x058A59F0>
def test_two(self): x = "hello"
assert hasattr(x, 'check') E AssertionError: assert False E + where False = hasattr('hello', 'check')
test_class.py:16: AssertionError ===================== 1 failed, 3 passed in 0.37 seconds ======================
6.指定测试 用例
(venv) D:\4_code\study>pytest -q test_calc.py . [100%] 1 passed in 0.02 seconds
7.Assert
pytest使用的是python自带的assert关键字来进行断言 assert关键字后面能够接一个表达式,只要表达式的最终结果为True,那么断言经过,用例执行成功,不然用例执行失败
断言异常抛出 如
import pytest def test_zero_division(): with pytest.raises(ZeroDivisionError): 1 / 0
1/0的时候应该抛出ZeroDivisionError,不然用例失败,断言不经过。
8.Fixture
如测试数据为
[ {"name":"jack","password":"Iloverose"}, {"name":"rose","password":"Ilovejack"}, {"name":"tom","password":"password123"} ]
import pytest import json class TestUserPassword(object): @pytest.fixture def users(self): return json.loads(open('./users.dev.json', 'r').read()) # 读取当前路径下的users.dev.json文件,返回的结果是dict def test_user_password(self, users): # 遍历每条user数据 for user in users: passwd = user['password'] assert len(passwd) >= 6 msg = "user %s has a weak password" %(user['name']) assert passwd != 'password', msg assert passwd != 'password123', msg
(venv) D:\4_code\study>pytest test_user_password.py ============================= test session starts ============================= platform win32 -- Python 3.6.2, pytest-3.7.1, py-1.5.4, pluggy-0.7.1 rootdir: D:\4_code\study, inifile: collected 1 item test_user_password.py F [100%] ================================== FAILURES =================================== _____________________ TestUserPassword.test_user_password _____________________ self = <test_user_password.TestUserPassword object at 0x044783B0> users = [{'name': 'jack', 'password': 'Iloverose'}, {'name': 'rose', 'password': 'Ilovejack'}, {'name': 'tom', 'password': 'password123'}] def test_user_password(self, users): # 遍历每条user数据 for user in users: passwd = user['password'] assert len(passwd) >= 6 msg = "user %s has a weak password" %(user['name']) assert passwd != 'password', msg > assert passwd != 'password123', msg E AssertionError: user tom has a weak password E assert 'password123' != 'password123' test_user_password.py:16: AssertionError ========================== 1 failed in 0.26 seconds ===========================
使用@pytest.fixture装饰器能够定义feature 在用例的参数中传递fixture的名称以便直接调用fixture,拿到fixture的返回值 3个assert是递进关系,前1个assert断言失败后,后面的assert是不会运行的,所以重要的assert放到前面 E AssertionError: user tom has a weak password能够很容易的判断出是哪条数据出了问题,因此定制可读性好的错误信息是很必要的 任何1个断言失败之后,for循环就会退出,因此上面的用例1次只能发现1条错误数据,换句话说任何1个assert失败后,用例就终止运行了
执行顺序
pytest找到以test_开头的方法,也就是test_user_password方法,执行该方法时发现传入的参数里有跟fixture users名称相同的参数 pytest认定users是fixture,执行该fixture,读取json文件解析成dict实例 test_user_password方法真正被执行,users fixture被传入到该方法
使用下面的命令来查看用例中可用的fixtures
pytest --fixtures test_user_password.py
------------------ fixtures defined from test_user_password ------------------- users test_user_password.py:6: no docstring available ======================== no tests ran in 0.07 seconds =========================
数据清理
有时候咱们须要在用例结束的时候去清理一些测试数据,或清除测试过程当中建立的对象,咱们能够使用下面的方式
import smtplib import pytest @pytest.fixture(scope="module") def smtp(): smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5) yield smtp # provide the fixture value print("teardown smtp") smtp.close() yield 关键字返回了fixture中实例化的对象smtp module中的用例执行完成后smtp.close()方法会执行,不管用例的运行状态是怎么样的,都会执行