• fixture参数化精简测试代码


    一、前言

      Pytest测试框架中的fixture,可以将自动化测试用例中的前置、后置部分分离出来放入其中,然后在写测试用例的时候只需要写测试逻辑相关的代码,提高代码的复用性,同时也有利于代码的维护。

      本文重点介绍的是fixture参数化,关于fixture的基础知识可以查看这个链接:https://www.cnblogs.com/zdx20/p/14948134.html

    二、测试场景介绍

      我们以下面App自动化测试,订酒店的测试场景为例,来说明:

      上图中有三个测试场景:

       1、编辑姓名;

       2、编辑手机号;

       3、编辑身份证。

      这三个场景主要的测试逻辑都在酒店的编辑订单页,通过fixture参数化功能可以很好的精简测试代码。

     三、fixture和fixture参数化

         1、按照上面的流程编写自动化测试用例:

    import pytest
    
    login_data = [{"user_name": "xiaowang", "pwd": 123456, "date": 1, "name": "小王"}]
    
    @pytest.mark.parametrize("test_data", login_data)
    def test_hotel(test_data):
        # 登录App
        print("
    " + "1、登录App, 账号和密码是:", test_data["user_name"], test_data["pwd"])
        # 酒店首页选择入住日期
        print("2、酒店首页选择日期:{}号".format(test_data["date"]))
        # 酒店列表选择酒店
        print("3、选择想要预订的酒店和房型")
        # 编辑酒店页面,输入入住人姓名
        print("4、输入入住人姓名:", test_data["name"])
        # 断言下单结果
        print("5、恭喜,酒店预订成功了!!!")

      上面的用例就是没有使用前置/后置分离代码,虽然可以完成UI自动化测试的一个测试场景任务,但是后续用例多了维护会非常头疼,而且不具有扩展性。

      2、fixture的前置、后置

      在每条用例中都需要登录App,然后执行测试过程,最后断言测试结果。我们可以将登录,和测试结果断言剥离出来放在fixture当中,这样同类型的测试场景就可以直接调用。

    import pytest
    
    hotel_data = [{"date": 1, "name": "小王"}]
    
    @pytest.fixture()
    def fix_login():
        # 登录App
        print("
    " + "1、前置条件--登录App, 账号和密码是:", "xiaowang", 123456)
        yield
        # 断言下单结果
        print("5、后置条件--恭喜,酒店预订成功了!!!")
    
    @pytest.mark.parametrize("test_data", hotel_data)     # 测试数据的参数化
    def test_hotel(test_data, fix_login):
        # 酒店首页选择入住日期
        print("2、酒店首页选择日期:{}号".format(test_data["date"]))
        # 酒店列表选择酒店
        print("3、选择想要预订的酒店和房型")
        # 编辑酒店页面,输入入住人姓名
        print("4、输入入住人姓名:", test_data["name"])

     执行结果如下:

     1、前置条件--登录App, 账号和密码是: xiaowang 123456
     2、酒店首页选择日期:1号
     3、选择想要预订的酒店和房型
     4、输入入住人姓名: 小王
     5、后置条件--恭喜,酒店预订成功了!!!

      上面的测试用例方法中,测试数据是通过@pytest.mark.parametrize()传入的,有几组测试数据就会生成几条测试用例,详细的使用方法可以查看“前言”部分提到的链接。

      3、fixture参数化

      通过fixture我们将用例的前置和后置条件摘出来了,但是前置条件登录的数据是固定的,通用性不强,需要将fixture的测试数据也参数化。

      fixture参数化传参的方法与用例的传参是一样的,也是使用@pytest.mark.parametrize()传入,但是需要加一个参数:indirect=True,指定将参数传入fixture测试夹具中。fixture测试夹具的方法中使用request接受传入的参数,然后通过request.param使用具体的数据。

    import pytest
    
    login_data = [{"user_name": "xiaowang", "pwd": 1234}, {"user_name": "zhaosi", "pwd": 6789}]
    test_data = [{"date": 1, "name": "小王"}]
    
    @pytest.fixture()
    def fix_login(request):
        # 接收传入的数据
        test_info = request.param
        # 登录App
        print("
    " + "1、前置条件--登录App, 账号和密码是:", test_info["user_name"], test_info["pwd"])
        yield
        # 断言下单结果
        print("5、后置条件--恭喜,酒店预订成功了!!!")
    
    @pytest.mark.parametrize("fix_login", login_data, indirect=True)       # fixture测试夹具的参数化
    @pytest.mark.parametrize("test_info", test_data)                       # 测试用例的参数化
    def test_hotel(test_info, fix_login):
        # 酒店首页选择入住日期
        print("2、酒店首页选择日期:{}号".format(test_info["date"]))
        # 酒店列表选择酒店
        print("3、选择想要预订的酒店和房型")
        # 编辑酒店页面,输入入住人姓名
        print("4、输入入住人姓名:", test_info["name"])

      上面登录的前置条件中,传入了两组账号、密码数据,那么在执行用例时,同一个用例场景会分别使用两个账号测试一遍。

      同时等到两个执行结果:

         fixture参数化,需要注意接收参数的标识符,用例中调用测试夹具的标识符,以及测试夹具的方法名要一致。

       现在测试场景只写了一个:编辑姓名,后面的编辑手机号、编辑身份证号两个场景,直接套用现有的测试用例即可。

      4、拆分多个fixture

      前面提到我们需要测试的三个酒店场景,前面几个步骤“酒店首页”、“酒店列表页”都是一样的,而且后续还有其他用例也需要用到“酒店首页”或者“酒店列表页”,因此我们需要不同页面的前置条件来满足不同测试场景,这就有了很多个测试夹具,不利于代码的维护。我们可以按照一个页面一个前置夹具的方法来细分测试场景,写用例时按照顺序去调用即可。

    import pytest
    
    login_data = [{"user_name": "xiaowang", "pwd": 1234}]
    test_data = [{"date": 11, "name": "小王", "result_data": "通过"}]
    
    @pytest.fixture()
    def fix_login(request):
        # 接收传入的数据
        test_info = request.param
        # 登录App
        print("
    " + "1、前置条件--登录App, 账号和密码是:", test_info["user_name"], test_info["pwd"])
    
    @pytest.fixture()
    def home_page(request):
        # 接收传入的数据
        test_info = request.param
        # 酒店首页选择入住日期
        print("2、酒店首页选择日期:{}号".format(test_info["date"]))
    
    @pytest.fixture()
    def list_page():
        # 酒店列表选择酒店
        print("3、选择想要预订的酒店和房型")
    
    @pytest.fixture()
    def result(request):
        yield
        # 接收传入的数据
        test_info = request.param
        # 断言下单结果
        print("5、后置条件--恭喜,酒店预订成功了,结果:{}!!!".format(test_info["result_data"]))
    
    @pytest.mark.parametrize("result", test_data, indirect=True)
    @pytest.mark.parametrize("home_page", test_data, indirect=True)
    @pytest.mark.parametrize("fix_login", login_data, indirect=True)
    @pytest.mark.parametrize("test_info", test_data)
    def test_name(test_info, fix_login, home_page, list_page, result):
        # 编辑酒店页面,输入入住人姓名
        print("4、输入入住人姓名:", test_info["name"])

      执行结果如下:

      1、前置条件--登录App, 账号和密码是: xiaowang 1234
      2、酒店首页选择日期:11号
      3、选择想要预订的酒店和房型
      4、输入入住人姓名: 小王
      5、后置条件--恭喜,酒店预订成功了,结果:通过!!!

      ###注意:在测试用例方法中同时调用多个fixture夹具时,一定要按照测试逻辑顺序来,执行用例时会按照测试夹具调用先后顺序执行。

      4.1、fixture测试夹具添加顺序

      测试用例方法中调用测试夹具时需要注意先后顺序,不然测试逻辑会混乱。如果你不想在调用时出现这个问题,可以在编写多个测试夹具时,测试夹具之间按照逻辑先后顺序调用,这样在写用例时就不用考虑先后顺序问题,而且不需要传参的测试夹具不用调用也能执行。

     测试用例方法调用:

    、使用params参数

      1、fixture的params参数

      fixture测试夹具的参数化除了上面用到的@pytest.mark.parametrize(),还有一种是直接在测试夹具的fixture中传参,使用params=即可。

    import pytest
    
    login_data = [{"user_name": "xiaowang", "pwd": 1234}, {"user_name": "zhaosi", "pwd": 6789}]
    test_data = [{"date": 1, "name": "小王"}]
    
    @pytest.fixture(params=login_data)          # fixture测试夹具的参数化
    def fix_login(request):
        # 接收传入的数据
        test_info = request.param
        # 登录App
        print("
    " + "1、前置条件--登录App, 账号和密码是:", test_info["user_name"], test_info["pwd"])
        yield
        # 断言下单结果
        print("5、后置条件--恭喜,酒店预订成功了!!!")
    
    @pytest.mark.parametrize("test_info", test_data)          # 测试用例的参数化
    def test_hotel(test_info, fix_login):
        # 酒店首页选择入住日期
        print("2、酒店首页选择日期:{}号".format(test_info["date"]))
        # 酒店列表选择酒店
        print("3、选择想要预订的酒店和房型")
        # 编辑酒店页面,输入入住人姓名
        print("4、输入入住人姓名:", test_info["name"])

      fixture的参数化就介绍到这里。

  • 相关阅读:
    20165329 《Java程序设计》第九周学习总结
    20165329 四则运算2
    20165329 第八周补做
    20165329 《Java程序设计》第八周学习总结
    2017-2018-2 学号20165329 实验二《Java面向对象程序设计》实验报告
    20165329 结对编程项目-四则运算
    20165329 第七周学习总结
    20165329 第六周学习总结
    20165329 实验一 java环境的熟悉
    20165329 第五周学习总结
  • 原文地址:https://www.cnblogs.com/zdx20/p/15203408.html
Copyright © 2020-2023  润新知