zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    Codeforces 1009F Dominant Indices
    C++之++运算符重载问题
    Codeforces 1010D Mars rover
    这是一个开始
    MoreEffectiveC++Item35(异常)(条款9-15)
    C++隐式类类型转化
    MoreEffectiveC++Item35(操作符)(条款5-8)
    MoreEffectiveC++Item35(基础议题)(条款1-4)
    php+mysql网站无限级栏目分类-递归获取树形结构函数
    JavaScript简易动画
  • 原文地址:https://www.cnblogs.com/dadaizi/p/11964769.html
Copyright © 2011-2022 走看看