pytest架构 python_python的pytest框架

pytest

1)简介

官方文档地址:http://www.pytest.org/en/latest/getting-started.html

pytest中定义测试用例有三种方式:

1)兼容unittest,已有的unittest库和文件都可以直接进行调用;

2)可以基于简单的类进行定义,如果一个类里边没有初始化方法并且以test开头,系统便会认为这是一个测试用例(不需要继承,直接定义就行)

3)可以直接定义测试函数来定义测试用例

2)安装:

pip install pytest

3)修改配置:

例1:

importpytest

deffunc(x):

return x + 1

deftest_answer():

assert func(3) == 5

if __name__ == "__main__":

pytest.main()

例2:(修改运行方式后,编写代码生效)

import pytest

def func(x):

return x + 1

def test_answer():

assert func(3) == 5

class TestFunc:

def test_answer(self):

assert func(3) == 5

if __name__ == "__main__":

pytest.main()

4)pytest的用例识别规则:

用例识别:

Test* 类包含的所有的test_*方法

不在class中的所有test_*函数

类中不能初始化方法

文件范围:

test_*.py

*_test.py

5)用例执行顺序:

import pytest

def func(x):

return x + 1

def test_answer():

assert func(5) == 6

class TestFunc:

@classmethod

def setup_class(cls):

print("setup_class")

def setup(self):

print("setup")

def test_answer(self):

assert func(5) == 6

def test_demo(self):

assert func(6) == 7

def teardown(self):

print("teardown")

@classmethod

def teardown_class(cls):

print("teardown_class")

if __name__ == "__main__":

pytest.main()

# 输出:

setup_class

setup

.teardown

setup

.teardown

teardown_class

setup_module: 整个类执行的时候执行

setup_function

pytest-order:调整执行的顺序

6)支持分组:(使用mark进行标记)

pytest.mark.webtest

pytest.mark.sec

Pytest -m "webtest and not sec"

import pytest

def func(x):

return x + 1

class TestFunc:

@classmethod

def setup_class(cls):

print("setup_class")

def setup(self):

print("setup")

@pytest.mark.fail

def test_answer(self):

assert func(5) == 7

@pytest.mark.success

def test_demo(self):

print("success")

assert func(6) == 7

def test_demo2(self):

assert func(7) == 8

def teardown(self):

print("teardown")

@classmethod

def teardown_class(cls):

print("teardown_class")

if __name__ == "__main__":

pytest.main()

# 只运行成功的:

pytest -m "success"

7)fixture功能

简介:在测试函数的前后,由pytest执行的一个外壳函数,主要用来将测试前的准备、测试后的清理工作与核心代码进行分离;

【demo】   @pytest.fixture() 装饰器用于声明一个函数是fixture

import pytest

@pytest.fixture()

def some_data():

return 42

def test_some_data(some_data):

assert some_data == 42

fixture功能函数范围:

1> 放在单独的测试文件里;

2> 若需要多个测试文件共享fixture,可以放在某个公共目录下新建一个conftest,将fixture放在里面;

test_pytest2.py

def test_some_data(some_data):

# assert some_data == 43

print("3333333")

同一级目录下conftest.py

import pytest

@pytest.fixture()

def some_data():

print("1111111")

# return 42

yield

print("2222222")

3> 使用fixture传递接口数据;

import pytest

@pytest.fixture()

def a_list():

return [1,2,3,24,5]

def test_a_list(a_list):

assert a_list[2] == 3

4> fixture作用范围

fixture作用范围从大到小依次是:session>module>class>function

作用于function范围内的fixture:

importpytest

@pytest.fixture()

deffirst():

print("\n获取用户名")

a = 'TEST'

returna

@pytest.fixture(scope="function")

defsecond():

print("\n获取密码")

b = "123456"

returnb

deftest_1(first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

deftest_2(second):

"用例传fixture"

print("测试密码:%s" %second)

assert second == "123456"

# 运行结果

SETUP F first

test_pytest2.py::test_1 (fixtures used: first).

TEARDOWN F first

SETUP F second

test_pytest2.py::test_2 (fixtures used: second).

TEARDOWN F second

用这个命令可以看到具体的执行顺序:pytest --setup-show test_pytest2.py

作用于class范围内的fixture:

importpytest

@pytest.fixture(scope="class")

deffirst():

print("\n获取用户名,scop为class级别只运行一次")

a = "TEST"

returna

classTestCase():

deftest_1(self,first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

deftest_2(self,first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

# 输出:

SETUP C first

test_pytest2.py::TestCase::test_1 (fixtures used: first).

test_pytest2.py::TestCase::test_2 (fixtures used: first).

TEARDOWN C first

作用于module范围内的fixture:

importpytest

@pytest.fixture(scope="module")

deffirst():

print("\n获取用户名,scop为module级别只运行一次")

a = "TEST"

returna

deftest_1(first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

classTestCase():

deftest_2(self,first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"# 输出:

SETUP M first

test_pytest2.py::test_1 (fixtures used: first).

test_pytest2.py::TestCase::test_2 (fixtures used: first).

TEARDOWN M first

作用于session范围内的fixture: 多个文件调用一次,可以跨.py文件,每个py文件是一个module;

[conftest.py]

importpytest

@pytest.fixture(scope="session")

deffirst():

print("\n获取用户名,scop为module级别只运行一次")

a = "TEST"

return a

[test_pytest2.py]

deftest_1(first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

[demo.py]

deftest_2(first):

"用例传fixture"

print("测试账号:%s" %first)

assert first == "TEST"

运行:

pytest --setup-show test_pytest2.py demo.py

输出:

SETUP S first

test_pytest2.py::test_1 (fixtures used: first).

demo.py

demo.py::test_2 (fixtures used: first).

TEARDOWN S first

4> fixture参数化

.pytest.fixture():在fixture级别的function处参数化

importpytest

importrequests

par_to_test =[{

"case":"serach a word:haha",

"headers":{},

"querystring":{

"wd":"hh"},

"payload":{},

"expected":{

"status_code":200}

},

{

"case":"serach a word2:kuku",

"headers":{},

"querystring":{

"wd":"kuku"},

"payload":{},

"expected":{

"status_code":200}

}

]

@pytest.fixture(params=par_to_test)

defclass_scope(request):

print(request.param)

returnrequest.param

deftest_baidu_search(class_scope):

url = "http://www.baidu.com"r = requests.request("GET",url,data=class_scope["payload"],

headers=class_scope["headers"],

params=class_scope["querystring"])

assert r.status_code == class_scope["expected"]["status_code"]

@pytest.mark.parametrize:允许在function或class级别的参数化,为特定的测试函数或类提供多个argument/fixture设置

@pytest.mark.success

@pytest.mark.parametrize("input,expect",

[(5, 6),

(7, 8),

(2, 2)

])

deftest_demo(self, input, expect):

print("success")

assert func(input) == expect

.pytest_generate_tests:实现自定义动态参数化或扩展

8)配置文件:

pytest的非测试文件主要有以下几种:

1> pytest.ini  : pytest的主要测试文件,可以改变pytest的默认行为,有很多可配置项;

设置默认按照python -v xx.py   的方式运行:

所以allure所需要的报告数据会放置在allure-results文件夹下,执行  allure generate allure-results -o allure,生成报告放在当前目录的allure文件夹下;

为了放置拼写错误,可以再pytest.ini中注册标记:     --strict 是一个注册标记,若是运行一个没有注册的marker就会报错

检查是否标记成功: pytest --markers

指定pytest的运行最低版本:若是本地安装低于指定版本,运行报错:

指定pytest忽略某些目录,pytest在执行的时候会递归遍历所有的子目录,包括一些没有必要遍历的目录,可以在pytest.ini中指定忽略,进而缩小pytest的搜索范围;

指定访问目录

避免文件名冲突

在每一个文件夹下增加__init.py__文件

2> conftest.py :  本地的插件库,其中hook函数和fixture作用于conftest.py文件所在的目录及所有子目录;

3>__init__.py : 每个测试子目录都包含此文件时,那么在多个测试目录中可以出现同名文件;

9)运行

设置第N个失败后停止运行:

pytest --maxfail=2 # stop after two failures

指定运行类下的某个方法

pytest test_pytest2.py::TestClass::test_one

指定运行某个方法,py文件中没有类

pytest test_pytest2.py::test_one

运行case名字中包含“baidu”的case,使用 -k 来过滤case;

pytest -v -k "baidu" test_pytest2.py

效果:

通过标记表达式运行:见6:

pytest -v -m "success" test_pytest2.py

展示在给定配置下,哪些case会被运行  --collect-only:

pytest -v -k "baidu" --collect-only test_pytest2.py

运行打印详细信息:

pytest -v test_pytest2.py

效果:

以安静的报告模式执行测试功能

pytest -q test_sysexit.py

输出:

1 passed in 0.12s

10)报告生成:

生成xml风格的报告:

pytest --junitxml=report.xml

生成兼容Junit风格的报告:

JUnit风格的xml报告:

pytest--junitxml = path

下载:

pip install pytest-html

生成HTML风格的报告:

1)pytest-html报告:

pytest--html = report.html

下载:

pip install pytest-html

执行:cd到用例的目录执行:pytest --html=report.html

allure2报告:

pytest--alluredir = /tmp/my_allure_results

安装pytest: pip install pytest

安装allure2:  从这个地址  http://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/  下载最新的安装包,解压到python目录下,进入bin目录,配置系统环境变量;

检查:allure --version

运行case:

pytest test_pytest1.py --alluredir allure-report

生成报告:

allure serve allure-report

*** 若有疑问,欢迎讨论,QQ群号:744419090 ***

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值