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  		 # 当用例错诨个数达到指定数量时,停止测试
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
4) 按节点运行
pytest test_demo.py::test_function1  # 运行某个模块下的函数
pytest test_demo2.py::Test_class::test_method # 运行某个类下的方法
5)标记表达式
pytest -m slow
# 将运行用@ pytest.mark.slow 装饰器修饰的所有测试。后面章节会讲自定义标记 mark 的功能
7)从包里面运行
pytest --pyargs pkg.testing
# 返将导入 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

三、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作用于模块机

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
后置生效
"""

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'])
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'])
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'])
(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'])
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'])


Nobody knows it better than me.
原文地址:https://www.cnblogs.com/dadaizi/p/11964769.html