pytest框架介绍
Posted dadaizi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytest框架介绍相关的知识,希望对你有一定的参考价值。
一、基础
1、运行规则
# 首先安装pytest模块
pip install -U pytest
pytest -q test_class.py # -q --quiet decrease verbosity( 显示简单结果)
pytest -x test_class.py # x 遇到错误时停止测试
pytest –maxfail=1 # 当用例错诨个数达到指定数量时,停止测试
1
# 首先安装pytest模块
2
pip install -U pytest
3
pytest -q test_class.py # -q --quiet decrease verbosity( 显示简单结果)
4
pytest -x test_class.py # x 遇到错误时停止测试
5
pytest –maxfail=1 # 当用例错诨个数达到指定数量时,停止测试
pytest 运行规则:**查找当前目录及其子目录下以 test_*.py 或*_test.py 文件,找到文件后,在文件中找到以 test 开头函数并执行
1)测试文件以 test_开头(以_test 结尾也可以)
2)测试类以 Test 开头,并且不能带有 init 方法
3)测试函数以 test_开头
4)断言使用 assert (不像unittest里面各种类型的断言)
2、用例的设计原则
1) 文件名以 test_*.py 文件呾*_test.py
2) 以 test_开头的函数
3) 以 Test 开头的类
4) 以 test_开头的方法
5) 所有的包 pakege 必项要有__init__.py 文件
3、执行用例的规则
1)执行某个目录下的测试用例, pytest work_dir/ (默认在当前目录的子目录)
2) 执行某个模块下的测试用例, pytest test_demo.py (执行当前目录下的test_demo.py)
3)执行带某些关键字的用例
备注: 行包含与给定字符串表达式匹配的名称的测试,其中包括 Python使用文件名,类名和函数名作为变量的运算符。
# 执行带某些关键字的用例
pytest -k "MyClass and not method" #(执行带有Myclass关键字的利用,但是不包括带method的那种用例)
#上面的例子将运行 TestMyClass.test_something 但不运行 TestMyClass.test_method_simple
1
# 执行带某些关键字的用例
2
pytest -k "MyClass and not method" #(执行带有Myclass关键字的利用,但是不包括带method的那种用例)
3
#上面的例子将运行 TestMyClass.test_something 但不运行 TestMyClass.test_method_simple
4) 按节点运行
pytest test_demo.py::test_function1 # 运行某个模块下的函数
pytest test_demo2.py::Test_class::test_method # 运行某个类下的方法
1
pytest test_demo.py::test_function1 # 运行某个模块下的函数
2
pytest test_demo2.py::Test_class::test_method # 运行某个类下的方法
5)标记表达式
pytest -m slow
# 将运行用@ pytest.mark.slow 装饰器修饰的所有测试。后面章节会讲自定义标记 mark 的功能
1
pytest -m slow
2
# 将运行用@ pytest.mark.slow 装饰器修饰的所有测试。后面章节会讲自定义标记 mark 的功能
7)从包里面运行
pytest --pyargs pkg.testing
# 返将导入 pkg.testing 并使用其文件系统位置来查找和运行测试
1
pytest --pyargs pkg.testing
2
# 返将导入 pkg.testing 并使用其文件系统位置来查找和运行测试
二、前置和后置
简介:setup 和teardown
1)模块级(setup_module/teardown_module)开始于模块始末全局的
2)函数级(setup_function/teardown_function)叧对函数用例生效(不在类中)
3)类级(setup_class/teardown_class)叧在类中前后运行一次(在类中)
4)方法级(setup_method/teardown_method)开始于方法始末(在类中)
5)类里面的(setup/teardown)运行在调用方法的前后
# 排序如下
# 行的优先级:setup_class》setup_method》setup 》用例》teardown》teardown_method》teardown_class
1
# 排序如下
2
# 行的优先级:setup_class》setup_method》setup 》用例》teardown》teardown_method》teardown_class
三、fixture装饰器
fixture的优势:
1)命名方式灵活,不局限于setup和teardown
2)conftest.py配置里面可以实现数据共享,且不需要import
3)scope=“module” 可以实现多个Py文件共享前置;scope=“session”,可以实现多个py文件使用
一个session来完成多个用例
1、conftest.py
一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用。在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效。
1)conftest.py 配置脚本名称是固定的,不能改名称
2)conftest.py 不运行的用例要在同一个 pakage 下,并且有__init__.py 文件
3)不需要 import 导入 conftest.py,pytest 用例会自动查找
fixture的作用范围 fixture里面有个scope参数可以控制fixture的作用范围:session>module>class>function -function:每一个函数或方法都会调用 -class:每一个类调用一次,一个类中可以有多个方法 -module:每一个.py文件调用一次,该文件内又有多个function和class -session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module |
# 1、conftest作用于类级
# ********************conftest.py******************
import pytest
@pytest.fixture(scope=‘class‘)
def login():
print(‘登录函数‘)
# ******************test_pratice_conf.py*************
import pytest
class TestOne:
def test_1(self, login):
print("test_1")
def test_2(self, login):
print("test_2")
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test_pratice_conf.py‘])
# *****************************************************‘
"""
test_pratice_conf.py 登录函数
.test_1
.test_2
[100%]
"""
# 2、conftest作用于函数级
@pytest.fixture("function") # 默认就是作用于function
def log_out():
print("退出登录")
def test_case(log_out):
print(‘执行test_case‘)
# 3、conftest作用于模块机
1
# 1、conftest作用于类级
2
# ********************conftest.py******************
3
import pytest
4
5
6
fixture(scope=‘class‘) .
7
def login():
8
print(‘登录函数‘)
9
# ******************test_pratice_conf.py*************
10
import pytest
11
12
13
class TestOne:
14
def test_1(self, login):
15
print("test_1")
16
17
def test_2(self, login):
18
print("test_2")
19
20
21
if __name__ == ‘__main__‘:
22
pytest.main([‘-s‘, ‘test_pratice_conf.py‘])
23
24
# *****************************************************‘
25
"""
26
test_pratice_conf.py 登录函数
27
.test_1
28
.test_2
29
[100%]
30
"""
31
# 2、conftest作用于函数级
32
fixture("function") # 默认就是作用于function .
33
def log_out():
34
print("退出登录")
35
36
def test_case(log_out):
37
print(‘执行test_case‘)
38
39
# 3、conftest作用于模块机
2、yield实现teardown
fixture通过scope 参数控制setup级别,既然有setup作为用例之前前的操作,用例执行完之后那肯定也有 teardown 操作。返里用到 fixture 的 teardown 操作并丌是独立的函数,用 yield 关键
字呼唤 teardown 操作
@pytest.fixture()
def go_out():
print("前置生效")
yield
print("后置生效")
def test_yield(go_out):
print(‘test_yield‘)
"""
前置生效
.test_yield
后置生效
"""
1
fixture() .
2
def go_out():
3
print("前置生效")
4
yield
5
print("后置生效")
6
7
def test_yield(go_out):
8
print(‘test_yield‘)
9
10
"""
11
前置生效
12
.test_yield
13
后置生效
14
"""
3、autouse
平常写自动化用例会写一些前置的 fixture 操作,用例需要用到就直接传该函数的参数名称就行了。当用例很多的时候,每次都传返个参数,会比较麻烦。
四、fixture详解
fixture(scope="function", params=None, autouse=False, ids=None,name=None):
fixture 里面有个 scope 参数可以控制 fixture 的作用范围:session > module >class > function
fixture 是 pytest 的核心功能,也是亮点功能,必须熟练掌握 fixture 的使用方法。
1) fixture 作为参数传入
定义 fixture 跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture 命名不要用 test_开头,跟用例区分开。用例才是 test_开头的命名。
fixture 是可以有返回值的,如果没 return 默认返回 None。用例调用 fixture 的返回值,直接就是把 fixture 的函数名称当成变量名称,如下案例
import pytest
@pytest.fixture()
def get_user():
print(‘获取用户名‘)
username = ‘admin‘
a = username
return a
def test_demo(get_user):
assert get_user == ‘admin‘
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test.py‘])
1
import pytest
2
3
fixture() .
4
def get_user():
5
print(‘获取用户名‘)
6
username = ‘admin‘
7
a = username
8
return a
9
10
def test_demo(get_user):
11
assert get_user == ‘admin‘
12
13
if __name__ == ‘__main__‘:
14
pytest.main([‘-s‘, ‘test.py‘])
2) 用例出现的error和failed
简单来说就是,在test函数里面出现失败了那么就是failed,如果在fixture里面就出现了失败,那就是error
3)使用多个fixture
如果用例需要用到多个 fixture 的返回数据,fixture 也可以 return 一个元组、list 或字典,然后从里面取出对应数据。
import pytest
@pytest.fixture(scope=‘function‘)
def para_prep():
print("返回两个值")
username = ‘admin‘
password = ‘admin‘
return (username,password)
def test_demo(para_prep):
print("账户名是%s, 密码是%s" % (para_prep[0], [para_prep[1]]))
assert para_prep[1] == ‘admin‘
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test.py‘])
1
import pytest
2
3
fixture(scope=‘function‘) .
4
def para_prep():
5
print("返回两个值")
6
username = ‘admin‘
7
password = ‘admin‘
8
return (username,password)
9
10
def test_demo(para_prep):
11
print("账户名是%s, 密码是%s" % (para_prep[0], [para_prep[1]]))
12
assert para_prep[1] == ‘admin‘
13
14
if __name__ == ‘__main__‘:
15
pytest.main([‘-s‘, ‘test.py‘])
4)装饰器usefixture
作用:当用例需要调用 fixture 时,前面讲到可以直接在用例里加 fixture 参数,如果一个测试 class 都需要用到 fixture,每个用例都去传参,会比较麻烦,这个时
候,可以在 class 外面加 usefixture 装饰器,让整个 class 都调用 fixture调用 fixture 三种方法
(a)用fixture实现全面传参
import pytest
@pytest.fixture(scope="function")
def start():
print("每个类里面的方法都需要传入start")
a = "go"
return a
class TestDemo:
def test_one(self,start):
print("当前case1传入start的参数是%s" % start)
assert start == ‘go‘
def test_two(self, start):
print("当前case2传入start的参数是%s" % start)
assert start == ‘go‘
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test.py‘])
1
import pytest
2
3
fixture(scope="function") .
4
def start():
5
print("每个类里面的方法都需要传入start")
6
a = "go"
7
return a
8
9
class TestDemo:
10
def test_one(self,start):
11
print("当前case1传入start的参数是%s" % start)
12
assert start == ‘go‘
13
14
def test_two(self, start):
15
print("当前case2传入start的参数是%s" % start)
16
assert start == ‘go‘
17
18
if __name__ == ‘__main__‘:
19
pytest.main([‘-s‘, ‘test.py‘])
(b)用usefixture实现全面传参
如果 fixture有返回值,那么 usefixtures 就无法获取到返回值了,返个是它不用例直接传 fixture 参数的区别。
import pytest
@pytest.fixture(scope="function")
def start():
print("每个类里面的方法都需要传入start")
@pytest.mark.usefixtures(‘start‘)
class TestDemo:
def test_one(self):
print("当前case1传入start的参数是%s")
def test_two(self):
print("当前case2传入start的参数是%s")
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test.py‘])
1
import pytest
2
3
fixture(scope="function") .
4
def start():
5
print("每个类里面的方法都需要传入start")
6
7
mark.usefixtures(‘start‘) .
8
class TestDemo:
9
def test_one(self):
10
print("当前case1传入start的参数是%s")
11
12
def test_two(self):
13
print("当前case2传入start的参数是%s")
14
15
if __name__ == ‘__main__‘:
16
pytest.main([‘-s‘, ‘test.py‘])
5) autouse特性
import pytest
@pytest.fixture(scope=‘module‘, autouse=True)
def mo_kuai():
print("这个是一个模块前置方法,模块中只调用一次")
@pytest.fixture(scope=‘function‘, autouse=True)
def func():
print("这个是一个函数前置,每个函数自动调用")
def test_demo1():
print("test case one is doing")
class TestCase:
def test_me1(self):
print("这是一个类中的普通方法,test_me1")
def test_me2(self):
print("这是一个类中的普通方法,test_me2")
if __name__ == ‘__main__‘:
pytest.main([‘-s‘, ‘test.py‘])
1
import pytest
2
3
fixture(scope=‘module‘, autouse=True) .
4
def mo_kuai():
5
print("这个是一个模块前置方法,模块中只调用一次")
6
7
fixture(scope=‘function‘, autouse=True) .
8
def func():
9
print("这个是一个函数前置,每个函数自动调用")
10
11
def test_demo1():
12
print("test case one is doing")
13
14
class TestCase:
15
def test_me1(self):
16
print("这是一个类中的普通方法,test_me1")
17
18
def test_me2(self):
19
print("这是一个类中的普通方法,test_me2")
20
21
if __name__ == ‘__main__‘:
22
pytest.main([‘-s‘, ‘test.py‘])
以上是关于pytest框架介绍的主要内容,如果未能解决你的问题,请参考以下文章