python测试框架 pytest

一:

pytest 是python的一套全功能的测试框架. 优点如下:

1、操作简单,支持多组数据参数化, 支持用例的skip和xfail;

2、支持简单的单元测试和复杂的功能测试,还可以做UI和接口自动化测试;

3、pytest有很多第三方的插件并且支持定义扩展; 如失败重新执行, 断言失败也继续运行,自定义出错停止, 自定义mark标记灵活运行用例....

4、可以很好的集成CI

二:  

框架结构:

类似的setup,teardown同样更灵活,

模块级(setup_module/teardown_module)模块始末,全局的

函数级(setup_function/teardown_function)不在类中的函数有用

类级(setup_class/teardown_class)只在类中前后运行一次。

方法级(setup_method/teardown_methond)运行在类中方法始末

session() 跨文件级

三:

Pytest调用方式和用例设计原则:

1. Pytest/py.test(终端,命令行,pycharm都行,可配置pycharm

使用pytest方式执行)

Pytest –v (最高级别信息—verbose -q静默模式)

pytest -v -s -q 文件名 (s是带控制台输出结果,也是输出详细) 2. pytest将在当前目录及其子目录中运行test _ * .py或* _test.py形式

3. 以test_开头的函数,以Test开头的类,以test_开头的方法。所有包package都要有__init__.py文件。

4. Pytest可以执行unittest框架写的用例和方法

四:

Fixture: 对于setup和teardown  有些场景不适用, 同一个类里的用例  有的用例需要执行setup  有些用例不需要;这时候用fixture比较好用.

用法:

1、对于setup,teardown,可以不起这两个名字,所以命名方式灵活。(可独立命名,声明后激活)

2、数据共享。在conftest.py配置里写方法可以实现数据共享,不需要import导入。可以跨文件共享, 使用的文件与conftest文件在同一文件夹下;

3、 scope的层次及神奇的yield组合相当于各种setup 和 teardown的所有文件.

不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也都不需要返回值时可以选择自动应用

解决: 使用fixture中参数autouse=True实现

步骤:在方法上面加@pytest.fixture(autouse=True) 使用@pytest.mark.usefixtures

步骤:在测试方法上加@pytest.mark.usefixtures("start")

测试离不开数据,为了数据灵活,一般数据都是通过参数传的

解决:fixture通过固定参数request传递;

步骤:在fixture中增加@pytest.fixture(params=[1, 2, 3, 'linda']) ; 在方法参数写request

import pytest
#module模块级,只在运行模块式执行一次。如果不加范围,默认会在该模块中的每一个方法执行前执行;autouse=True设置后实现自动应用,后面模块内所有的函数后面不用加方法名@pytest.fixture(scope="module", autouse=True)def open_browser():
    print("\n打开浏览器,打开网站首页")
yield #模块执行完case后 在最后执行一遍teardown操作。
print('执行teardown')
print('最后关闭浏览器')

def test_soso(login): #login函数写在 conftest文件中 @pytest.fixture() def login():
print('case1: 登际后执行搜索')

def test_cakan():
print('case2:不登陆直接操作')

def test_cart(login):
print('case3,登陆后进行购物')

或者使用装饰器方法:不改变原有代码的情况下增加新功能,灵活的让某个方法经过装饰后具备 setup teardown 或其它功能项
@pytest.fixture()
def open_browser():
    print("\n打开浏览器,打开网站首页")
yield
print('执行teardown')
print('最后关闭浏览器')

@pytest.mark.usefixtures('open_browser')
def test_soso(): #
def test_soso(open_browser) 效果是一样的 但是这样会改变原代码结构,其他地方有复用的话就可能会有问题
    print('case1: 登际后执行搜索')
五:
常用依赖库:

Pip install pytest-sugar
pip install pytest-rerunfailures Pip install pytest-xdist
Pip install pytest-assume
Pip intall pytest-html

 
六:
参数化和数据驱动:
test_user_data = ["zhangsan", "lisi"]

@pytest.fixture()
def login_r(request):
user = request.param
print("\n打开首页准备登陆,登陆用户:%s" % user)
return user

@pytest.mark.parametrize('login_r',test_user_data,indirect=True)
def test_login_s(login_r):
print(login_r)

等同于:
@pytest.fixture(params=test_user_data)
def login_r(request):
user = request.param
print("\n打开首页准备登陆,登陆用户:%s" % user)
return user

def test_login_s(login_r):
print(login_r)

多组数据:
test_user_data1 = [{"user": "linda", "password": "888888"},
{"user": "servenruby", "password": "123456"},
{"user": "test01", "password": ""}]

test_user_data2 = [{"q": "中国平安", "count": 3, "page": 1},
{"q": "阿里巴巴", "count": 2, "page": 2},
{"q": "pdd", "count": 3, "page": 1}]

@pytest.fixture(scope="module")
def login_r(request):
# 这是接收传入的参数,接收一个参数
user = request.param['user']
password = request.param['password']
print("\n用户名:%s,密码:%s" % (user, password))

@pytest.fixture(scope="module")
def query_param(request):
# 这是接收传入的参数,接收一第二个参数
    q = request.param['q']
count = request.param['count']
page = request.param['page']
print("查询的搜索词:%s" % q)
return request.param

# 这是pytest的参数化数据驱动,indeirect=True 是把login_r当作函数去执行,不写的话会当它是参数
# 从下往上执行
# 两个数据进行组合测试有3*3个测试用例执行(test_user_data1的个数*test_user_data2的个数)
@pytest.mark.parametrize("query_param", test_user_data2, indirect=True)
@pytest.mark.parametrize("login_r", test_user_data1, indirect=True)
def test_login(login_r, query_param):
# 登陆用例
print(login_r)
print(query_param)
















猜你喜欢

转载自www.cnblogs.com/1026164853qqcom/p/11280684.html