Python测试框架之pytest参数化

发表于:2021-3-01 09:25

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:小菜鸟qing    来源:博客园

  Fixture参数之params参数可实现参数化:
  (参数可以为list和tuple,或者字典列表,字典元祖等)
  参数化传单个参数
  # -*-coding: utf-8 -*-
  import pytest
  import requests
  def userinfo():
      users = ['13630000009','18290000007','13040000004']
      return users
  @pytest.fixture(params=userinfo())
  def login(request):
      yield request.param
      #删除节点的操作,新增合作方、新增商场、新增出入口
  @pytest.fixture(params=userinfo())
  def login1(request):
      yield request.param
      #删除节点的操作,新增合作方、新增商场、新增出入口
  def test_login(login,login1,):
      url= "https://172.16.100.154/auth/getAccessTokenV2"
      data = {
          "username": login,
          "passwd": 'a34fca232356ab316d3bb293b3f3d82d',
          "randStr": None,
          "ticket": None,
      }
      r = requests.post(url=url,json=data,verify=False)
      print('登录结果',r.text)
      print('调用的测试数据:' + login)
  此例中test_login方法被执行了三次,分别使用的数据为'13630000009','18290000007','13040000004',此结果类似于ddt数据驱动的功能。特别注意:这里的request参数名是固定的,然后request.param的param没有s。
  可以把return request.param改成yield request.param,yield也是返回的意思,它和return的区别在于return返回后后面不能接代码,但是yield返回后,后面还可以接代码。
  yield:方法调用夹具时,有删除依赖时,记住先进后出原则,即放在最后面最先删除。
  参数化传多个参数
  import pytest
  import requests
  # 测试账号数据
  test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"},
                    {"user": "15310000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}]
  @pytest.fixture(params=test_user_data)
  def login(request):
      user = request.param["user"]
      passwd = request.param["passwd"]
      print("\n")
      print("登录账户:%s" % user)
      print("登录密码:%s" % passwd)
      yield user,passwd
  def test_login(login):
      """登录用例"""
      url= "https://172.16.100.154/auth/getAccessTokenV2"
      data = {
          "username": login[0],
          "passwd": login[1],
          "randStr": None,
          "ticket": None,
      }
      r = requests.post(url=url,json=data,verify=False)
      print('登录结果',r.text)
      print("\n")
  Fixture其他参数:
  1.autouse参数:在夹具中设置autouse=True为自动调用执行:
  import pytest
  # @pytest.fixture(autouse=True) #设置为True让autouse生效
  # def setUp():
  #     print('\nsetUp')
  #     yield
  #     print('\ntearDown')
  #
  # def testcase01():
  #     print('1111111111')
  #
  # def testcase02():
  #     print('2222222222')
  # if __name__=='__main__':
  #     pytest.main(['-s', '-v', "test13.py"])\
  #
  @pytest.fixture() #不设置autouse是默认autouse为false
  def setUp():
      print('\nsetUp')
      yield
      print('\ntearDown')
  def testcase01(setUp):
      print('1111111111')
  def testcase02():
      print('2222222222')
  if __name__=='__main__':
      pytest.main(['-s', '-v', "test13.py"])
  2.ids参数:ids参数用于描述每个用例的运行场景:
  import pytest
  import requests
  # 测试账号数据
  test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"},
                    {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}]
  @pytest.fixture(params=test_user_data,ids=[
                               "输入账号1,密码1,登录成功",
                               "输入账号2,密码2,登录成功",
                           ])
  def login(request):
      user = request.param["user"]
      passwd = request.param["passwd"]
      yield user,passwd
  def test_login(login):
      """登录用例"""
      url= "https://172.16.100.154/auth/getAccessTokenV2"
      data = {
          "username": login[0],
          "passwd": login[1],
          "randStr": None,
          "ticket": None,
      }
      r = requests.post(url=url,json=data,verify=False)
  运行结果
  3.name参数:相对于把被fixture标记的方法重命名,主要是命名为中文,让使用起来更易读。如下图所示案例:
  注意点:设置了name即夹具的别名,就不能再使用函数名调用了,使用函数名调用会报错:
  使用@pytest.mark.parametrize()方法实现参数化
  方法详情: parametrize(argnames,argvalues,indirect=False,ids=None,scope=None)
  常用参数:
  argnames:参数名
  argnames:参数值(可以为list和tuple,或者字典列表,字典元组等),参数值有N个,用例就会执行N次。
  1、使用方式一:
  # -*-coding: utf-8 -*-
  import pytest
  import requests
  # 测试账号数据
  test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"},
                    {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}]
  @pytest.mark.parametrize("case_info",test_user_data)
  def test_login(case_info):
      print("\n")
      print("用户名",case_info['user'])
      print("密码",case_info['passwd'])
      url= "https://172.16.100.154/auth/getAccessTokenV2"
      data = {
          "username": case_info['user'],
          "passwd": case_info['passwd'],
          "randStr": None,
          "ticket": None,
      }
      r = requests.post(url=url,json=data,verify=False)
      print('登录结果',r.text)
  2、使用方式二:类似于@unpack解包功能实现参数
  # -*-coding: utf-8 -*-
  import pytest
  import requests
  # 测试账号数据
  test_user_data = [('17530000005', 'b1b3e46675227369bd396eb44df1c900'),
                    ('15300000000', 'b1b3e46675227369bd396eb44df1c900')]
  @pytest.mark.parametrize('user,passwd',test_user_data)
  def test_login(user,passwd):
      print("\n")
      print("用户名",user)
      print("密码",passwd)
      url= "https://172.16.100.154/auth/getAccessTokenV2"
      data = {
          "username": user,
          "passwd": passwd,
          "randStr": None,
          "ticket": None,
      }
      r = requests.post(url=url,json=data,verify=False)
      print('登录结果',r.text)
  数据驱动 Vs 关键字驱动
  数据驱动自动化测试
  在自动化测试框架中,从csv或excel或ymal读取数据、输出数据都在文件中执行,一个业务的实际返回值与业务的预期返回值都在数据文件中操作而不是在脚本里去执行校验,这时候数据文件和脚本驱动为数据驱动框架。
  优点和缺点
  1)优点:
  1.解耦合、测试数据预期结果与脚本分开
  2.对于业务的改版或字段的增删只需去修改脚本或者数据源
  3.避免重复编写脚本数据
  2)缺点:
  1.随着业务量的增加、改版迭代次数快不方便维护
  2.长时间可能会丢失数据
  3.数据文件多、难以修改业务数据
  关键字驱动
  基于数据驱动之上建立的关键字驱动,从一个关键字的整合面对不同测试方法调用。从多个测试方法函数整合完成进阶的关键字驱动,从数据和关键字的组合达到一个关键字驱动的效果。
  关键字自动化测试驱动
  在关键字驱动框架中,你可以创建一些函数或者一些测试方法。从函数库中读取关键字然后做相关调用。这种自动化驱动模型主要核心由数据驱动引擎、组件函数、支持库和应用映射表组成。自动化测试首先由初始化脚本执行,这个脚本把高层测试表传递给高层驱动,高层驱动在处理这些表过程中,遇到中层驱动,中层处理也做中层处理。在底层处理时,尝试底层测试同步 ,关键字驱动是对数据驱动做改善。
  有哪几种数据驱动方式
  1.以硬编码的方式写在代码里,简单直观,但代码和数据未分离,不方便以后维护。
  2.从文件读取数据,如csv,excel、txt、xml等格式文件。不用修改测试逻辑,只需要维护测试数据。
  excel表读数据代码示例:
  import pytest, xlrd, os, requests, json
  # 获取excel用例数据
  def get_case_data():
      case_path = r"E:\scripts\newplatform\linshi\interface\yanshi\test_data.xlsx"
      book = xlrd.open_workbook(case_path)
      sheet = book.sheet_by_name('Sheet1')
      case = []
      for i in range(0, sheet.nrows):
          if sheet.row_values(i)[0] == 'mall用户登录':
              case.append(sheet.row_values(i))
      return case
  #注意点:excel中的json数据应为双引号,否在json.loads时会报错JsonEncodeError
  class Test():
      # 调用获取测试用例数据
      case_data = get_case_data()
      # 使用装饰器参数化用例数据
      @pytest.mark.parametrize('Function,TestCase,URL,Parameters', case_data) #注意此处填写的参数应与表格一致,及表格多少列就将其参数名都写出来,否则会报错
      def test_login1(self, Function, TestCase,URL, Parameters):
          print(json.loads(Parameters))
          r = requests.post(url=URL,json=json.loads(Parameters),verify=False)
          print(r.text)
          assert  r.text==r.text
  if __name__ == "__main__":
      pytest.main(["-s","-v","-w", "exceltest.py"])
  3.直接调用接口获取数据源。
  4.本地封装一些生成数据的方法。
  Redis
  数据驱动的优点
  1.像在循环里一样,自动遍历所有数据组合。
  2.某一组数据执行测试方法失败,不会影响其他数据组合继续执行。
  3.测试代码不用加过多的数据判断,要的只是对被测代码的数据输出和结果断言。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号