zoukankan      html  css  js  c++  java
  • Python 自动化测试(三): pytest 参数化测试用例构建

    本文节选自霍格沃玆测试学院内部教材,进阶学习,文末加群!

    在之前的文章中主要分享了 pytest 的实用特性,接下来讲 Pytest 参数化用例的构建。

    如果待测试的输入与输出是一组数据,可以把测试数据组织起来用不同的测试数据调用相同的测试方法。参数化顾名思义就是把不同的参数,写到一个集合里,然后程序会自动取值运行用例,直到集合为空便结束。pytest
    中可以使用 @pytest.mark.parametrize 来参数化。

    使用 parametrize 实现参数化

    parametrize( ) 方法源码:

    def parametrize(self,argnames, argvalues, indirect=False, ids=None, \  
        scope=None):  
    
    • 主要参数说明

    • argsnames :参数名,是个字符串,如中间用逗号分隔则表示为多个参数名

    • argsvalues :参数值,参数组成的列表,列表中有几个元素,就会生成几条用例

    • 使用方法

    • 使用 @pytest.mak.paramtrize() 装饰测试方法

    • parametrize('data', param) 中的 “data” 是自定义的参数名,param 是引入的参数列表

    • 将自定义的参数名 data 作为参数传给测试用例 test_func

    • 然后就可以在测试用例内部使用 data 的参数了

    创建测试用例,传入三组参数,每组两个元素,判断每组参数里面表达式和值是否相等,代码如下:

    @pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+5",7),("7*5",30)])  
    def test_eval(test_input,expected):  
        # eval 将字符串str当成有效的表达式来求值,并返回结果  
        assert eval(test_input) == expected  
    

    运行结果:

    plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6, \  
    forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0  
    collecting ... collected 3 items  
      
    test_mark_paramize.py::test_eval[3+5-8]   
    test_mark_paramize.py::test_eval[2+5-7]   
    test_mark_paramize.py::test_eval[7*5-35]   
      
    ============================== 3 passed in 0.02s ===============================  
    

    整个执行过程中,pytest 将参数列表 [("3+5",8),("2+5",7),("7*5",30)]
    中的三组数据取出来,每组数据生成一条测试用例,并且将每组数据中的两个元素分别赋值到方法中,作为测试方法的参数由测试用例使用。

    多次使用 parametrize

    同一个测试用例还可以同时添加多个 @pytest.mark.parametrize 装饰器, 多个 parametrize
    的所有元素互相组合(类似笛卡儿乘积),生成大量测试用例。

    场景:比如登录场景,用户名输入情况有 n 种,密码的输入情况有 m 种,希望验证用户名和密码,就会涉及到 n*m
    种组合的测试用例,如果把这些数据一一的列出来,工作量也是非常大的。pytest
    提供了一种参数化的方式,将多组测试数据自动组合,生成大量的测试用例。示例代码如下:

    @pytest.mark.parametrize("x",[1,2])  
    @pytest.mark.parametrize("y",[8,10,11])  
    def test_foo(x,y):  
        print(f"测试数据组合x: {x} , y:{y}")  
    

    运行结果:

    plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6,\  
     forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0  
    collecting ... collected 6 items  
      
    test_mark_paramize.py::test_foo[8-1]   
    test_mark_paramize.py::test_foo[8-2]   
    test_mark_paramize.py::test_foo[10-1]   
    test_mark_paramize.py::test_foo[10-2]   
    test_mark_paramize.py::test_foo[11-1]   
    test_mark_paramize.py::test_foo[11-2]   
    

    分析如上运行结果,测试方法 test_foo( ) 添加了两个 @pytest.mark.parametrize()
    装饰器,两个装饰器分别提供两个参数值的列表,2 * 3 = 6 种结合,pytest 便会生成 6
    条测试用例。在测试中通常使用这种方法是所有变量、所有取值的完全组合,可以实现全面的测试。

    @pytest.fixture 与 @pytest.mark.parametrize 结合

    下面讲结合 @pytest.fixture 与 @pytest.mark.parametrize 实现参数化。

    如果测试数据需要在 fixture 方法中使用,同时也需要在测试用例中使用,可以在使用 parametrize 的时候添加一个参数
    indirect=True,pytest 可以实现将参数传入到 fixture 方法中,也可以在当前的测试用例中使用。

    parametrize 源码:

        def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):  
    

    indirect 参数设置为 True,pytest 会把 argnames 当作函数去执行,将 argvalues 作为参数传入到 argnames
    这个函数里。创建“test_param.py”文件,代码如下:

    # 方法名作为参数  
    test_user_data = ['Tome', 'Jerry']  
    @pytest.fixture(scope="module")  
    def login_r(request):  
        # 通过request.param获取参数  
        user = request.param  
        print(f"\n 登录用户:{user}")  
        return user  
      
    @pytest.mark.parametrize("login_r", test_user_data,indirect=True)  
    def test_login(login_r):  
        a = login_r  
        print(f"测试用例中login的返回值; {a}")  
        assert a != ""  
    

    运行结果:

    plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6,\  
     forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0  
    collecting ... collected 2 items  
      
    test_mark_paramize.py::test_login[Tome]   
    test_mark_paramize.py::test_login[Jerry]   
      
    ============================== 2 passed in 0.02s ===============================  
      
    Process finished with exit code 0  
      
     登录用户:Tome PASSED           [ 50%]测试用例中login的返回值; Tome  
      
     登录用户:Jerry PASSED           [100%]测试用例中login的返回值; Jerry  
    

    上面的结果可以看出,当 indirect=True 时,会将 login_r 作为参数,test_user_data 被当作参数传入到
    login_r 方法中,生成多条测试用例。通过 return 将结果返回,当调用 login_r 可以获取到 login_r
    这个方法的返回数据。

    【相关阅读】


    **
    来霍格沃兹测试开发学社,学习更多软件测试与测试开发的进阶技术,知识点涵盖web自动化测试 app自动化测试、接口自动化测试、测试框架、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移、测试右移、精准测试、测试平台开发、测试管理等内容,课程技术涵盖bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相关技术,全面提升测试开发工程师的技术实力
    QQ交流群:484590337
    公众号 TestingStudio
    点击获取更多信息

  • 相关阅读:
    转:关于JAVA多线程同步
    转:Java HashMap实现详解
    索引创建规则:
    数据库为什么要分库分表
    [设计模式] javascript 之 桥接模式
    [百度地图] ZMap 与 MultiZMap 封装类说明;
    [设计模式] Javascript 之 外观模式
    [设计模式] javascript 之 代理模式
    [设计模式] javascript 之 装饰者模式
    [设计模式] javascript 之 适配器模式
  • 原文地址:https://www.cnblogs.com/hogwarts/p/15821981.html
Copyright © 2011-2022 走看看