Pytest接口测试框架实战项目搭建(二)

news2024/11/24 1:02:24

一、前言

  业务系统的登录均要经过统一登录系统S,本篇演示统一登录处理,一个是内部业务系统C(其余内部业务系统AB用的都是相同账号密码),一个是外部用户使用的系统W,因为账号密码以及headers信息都不一样,所以要分开处理登录。这里要先贴一下请求要用到的数据。

  说明:登录进了S系统,拿到token即可直接请求内部业务系统ABC的接口,同理外部业务系统W亦是如此。所以本篇主要讲述的是如何登录S系统

1、conf/config.ini

  接口请求时需要拿到配置文件中的域名地址,env可切换环境,即不用改业务代码,直接改配置文件即可适配不同测试环境的接口自动化测试。

     y_api_url,是业务系统ABCW的接口域名,s_api_url是登录系统S的接口域名。

[ENV]
env = QA1

[QA1]
y_api_url = https://qa1-api.y.cn
s_api_url = https://qa-s-xxx.cn

[QA2]
y_api_url = https://qa1-api.y.cn
s_api_url = https://qa-s-xxx.cn

2、data/userInfo.yaml

  要拿到登录token,需要先登录S系统,S登录接口是嵌入到各个业务系统,所以请求体是一样的只是账号密码不一样,故要分开来,内部业务系统ABC均可用s_login_info的用户信息,外部业务系统W用的是w_login_info的用户信息。

QA1:
  s_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉该参数,password传输可不加密
    username: zhangsan
    password: 1231234
    verification:

  w_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉该参数,password传输可不加密
    username: lisi
    password: 123456
    verification:

QA2:
  s_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉该参数,password传输可不加密
    username: zhangsan111
    password: 1231234
    verification:

  w_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉该参数,password传输可不加密
    username: lisi222
    password: 123456
    verification:

3、data/headers.json

  内部业务系统ABC均可用s_login_info的用户信息,外部业务系统W用的是w_login_info的用户信息,其实请求体是一样的只是账号密码不一样,所以要分开来。

{
  "QA1": {
    "s_login_headers": {
      "Content-Type": "application/x-www-form-urlencoded",
      "Accept": "application/json, text/plain, */*"
    },
    "s_headers": {
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    },
    "c_headers": {
      "T-Id": "7",
      "System-Code": "C",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    },
    "w_headers": {
      "T-Id": "12095",
      "System-Code": "W",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    }
  },
  "QA2": {
    "s_login_headers": {
      "Content-Type": "application/x-www-form-urlencoded",
      "Accept": "application/json, text/plain, */*"
    },
    "c_headers": {
      "T-Id": "7",
      "System-Code": "C",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    }
  }
}

4、conf/api_path.py

  该文件存储的是项目中用到的所有接口路径,目前只展示统一登录需要用到的api。

# -*- coding:utf-8 -*-
'''
@Date:2022/10/3  20:56
@Author:一加一
'''

from tools.operate_config import OperateConfig
from urllib.parse import urljoin

class ApiPath:

    '''管理api地址'''

    def __init__(self,env=None):
        if env is None:
            self.env = OperateConfig().get_node_value('ENV', 'env')
        else:
            self.env = env
     self.y_api_url = OperateConfig().get_node_value(self.env,'y_api_url') # 读取配置文件config.ini的业务系统接口域名
        self.s_api_url = OperateConfig().get_node_value(self.env, 's_api_url') #读取配置文件config.ini 的s系统接口域名

        # s系统 api
        self.s_login_url = urljoin(self.s_api_url, "/saas-xxx/login") #登录
        self.s_exchangeToken_url = urljoin(self.s_api_url, "/saas-xxx/exchangeToken") #生成sToken
        self.employee_paging_list = urljoin(self.s_api_url,"/saas-xxx/list") #查询员工列表获取companyId

二、封装方法:获取JSON

  要登录的话肯定要涉及接口请求了,所以这里首先封装下读取json文件的方法,具体如下。

1、tools/get_userjson.py

  tools文件夹下新建get_userjson.py文件,源码如下:

  • get_yaml主要用于读取data/userInfo.yaml里的用户信息
  • OperateConfig主要读取config.ini里的域名地址

from tools.operate_config import get_yaml,OperateConfig

class GetuserJson:

    def __init__(self, env=None):
        if env is None:
            env = OperateConfig().get_node_value('ENV', 'env')
        self.env = env
        self.user_info = get_yaml(self.env)

    # 统一登录系统s 登陆的用户信息
    def  get_s_login_info(self):
        s_login_info = self.user_info['s_login_info']
        return s_login_info

    # 业务系统W 登陆的用户信息
    def  get_w_login_info(self):
        w_login_info = self.user_info['w_login_info']
        return w_login_info

2、tools/get_headerjson.py

  tools文件夹下新建get_headerjson.py文件,源码如下:

  • 用于登录S系统用到的:get_s_login_headers,获取headers.json里名为"s_login_headers”的json串
  • 用于S系统查询公司id用到的:get_s_headers,获取headers.json里名为"s_headers”的json串
  • 用于登录成功将获取到的token值set进去:set_s_headers,往json文件里set字段值
# -*- coding:utf-8 -*-
from conf.setting import CASE_DATA_PATH
from tools.operate_json import OperationJson
import os
from tools.operate_config import get_yaml,OperateConfig

class GetHeaderjson:

    def __init__(self,env=None):
        if env is not None:
            self.env = env
        else:
            self.env = OperateConfig().get_node_value('ENV', 'env')
        self.headers_json = os.path.join(CASE_DATA_PATH, "headers.json")

    def get_s_login_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"s_login_headers")
    def get_s_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"s_headers")
    def set_s_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "s_headers", "sToken")
def get_c_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"c_headers")
    def set_c_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "c_headers", "sToken")

    def get_w_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env, "w_headers")
    def set_w_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "w_headers", "sToken")
    def set_w_headers_companyId(self,companyId):
        OperationJson(self.headers_json).write_datas(companyId,self.env, "w_headers", "T-Id")

三、统一登录处理conftest.py

1、conftest.py源码如下

  conftest文件之前的博客有讲过,常用来处理用例的前置条件,文件名称是pytest框架写死的,即是在执行用例前框架会先执行一次conftest.py的代码。

  框架思想:

  1)内部业务系统 储如ABC,接口请求时header的token需要实时获取,所以需要在接口请求前先完成登录,并且将登录后成功的token值set到headers.json里相应json串对应的token字段,如此token便不会过期,永远都是最新的,可看test_s_login函数处理。

  2)外部业务系统W,同理token需要取最新,以及接口请求头的T-Id也是,所以需要在接口请求前先完成登录,并且登录成功后将最新的tooken,T-id值set到headers.json里相应json串对应的token字段,可看test_w_login函数处理。

'''
@Date:2022/10/2  14:22
@Author:一加一
'''

import pytest
from tools.common import *
from tools.get_headerjson import GetHeaderjson
from conf.api_path import ApiPath
from tools.get_userjson import GetuserJson
from tools.get_wjson import *
'''处理登录:统一登录S、业务系统登录W'''

# 实例化对象
api_path = ApiPath()
get_header = GetHeaderjson(None)
get_userinfo = GetuserJson(None)
get_wjson = GetwJson(None)


@pytest.fixture(scope="session",autouse=True)
def test_s_login():
    # s登录:用户名密码登录
    url = api_path.s_login_url #调用api_path方法获取url
    headers = get_header.get_s_login_headers() #调用get_header获取s系统接口请求头
    data = get_userinfo.get_s_login_info() #调用get_userinfo获取入参
    res_json = Common.r_post_form(url=url, headers=headers, data=data)
    # 获取code
    code = res_json['data'].split('?')[-1]

    # 生成stoken
    res_json = Common.r_post_form(url=api_path.s_exchangeToken_url,headers=get_header.get_s_login_headers(),data=code)
    # 将生成的sToken写入headers.json文件
    get_header.set_c_headers(res_json['data']['sToken'])
    get_header.set_p_headers(res_json['data']['sToken'])

@pytest.fixture(scope="session",autouse=True)
def test_w_login():
    # s登录:用户名密码登录
    url = api_path.s_login_url #调用api_path方法获取url
    headers = get_header.get_s_login_headers() #调用get_header获取s请求头
    data = get_userinfo.get_w_login_info() #调用get_userinfo获取入参
    res_json = Common.r_post_form(url=url, headers=headers, data=data)
    # 获取code
    code = res_json['data'].split('?')[-1]

    # 生成stoken
    res_json = Common.r_post_form(url=api_path.s_exchangeToken_url,headers=get_header.get_s_login_headers(),data=code)
    # 将生成的sToken写入headers.json文件
    get_header.set_w_headers(res_json['data']['sToken'])
    get_header.set_s_headers(res_json['data']['sToken'])

    # 查询s系统员工列表获取T-id写入headers.json文件的T-Id
    res_json = Common.r_s_post(url=api_path.employee_paging_list,
                             headers=get_header.get_s_headers(),
                             json=get_wjson.get_w_companyId())
    # 将响应结果转换成json格式
    rep_json = res_json.json()
    # 断言
    Common.assert_s_code_message(rep_json)
    # 将生成的companyId写入headers.json文件(w_headers对应的T-Id)
    TenantId = str(rep_json['data']['pageData'][0]['companyId'])
    get_header.set_w_headers_companyId(TenantId)

四、新建测试用例 testcase/test_case.py

  主要用于调试执行用例前是否会先处理conftest.py代码,以及调试conftest.py的登录代码

'''
@Date:2022/11/12  13:35
@Author:一加一
'''

import allure

@allure.feature("测试业务")
@allure.story("测试订单")
class TestCase:
    @allure.title("case1:获取列表")
    def test_case1(self):
        with allure.step("step1:获取列表"):
            print("测试第一步")
        with allure.step("step2:获取响应结果"):
            print("测试第二步")

 五、执行test_case.py文件后,生成的日志如下

  由日志可知用例执行前会正确先执行conftest.py的代码

  

重点:学习资料  

600g的学习资料懂的都懂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46415.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DCDC--Burst Mode和Pulse Skipping Mode

1、Burst Mode和Pulse Skipping Mode(PSM)的区别 Burst Mode ≠ Pulse Skipping Mode,论坛有人认为Burst Mode就是Pulse Skipping Mode,这是不对的。 以LTC3624为例: Burst Mode operation provides the highest ef…

大数据(9h)FlinkSQL双流JOIN、Lookup Join

文章目录1、环境2、Temporal Joins2.1、基于处理时间(重点)2.1.1、设置状态保留时间2.2、基于事件时间3、Lookup Join(重点)4、Interval Joins(基于间隔JOIN)重点是Lookup Join和Processing Time Temporal …

SpringBoot+Vue实现前后端分离的餐饮点餐系统

文末获取源码 开发语言:Java 使用框架:spring boot 前端技术:JavaScript、Vue.js 、css3 开发工具:IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库:MySQL 5.7/8.0 数据库管理工具:phpstudy/Navicat JD…

线性表01- 数组与简易接口设计

线性表的定义 线性表: 具有n个相同类型元素的有限序列 n>0 线性表的元素特点是有索引, 可以通过索引快速查找到元素. a1是a2的前驱, a2是a1的后继 常见的线性表 数组链表栈队列哈希表 (散列表) 数组 数组是一种顺序存储的线性表, 所有的元素的内存地址是连续的. int arr…

Python用广义加性模型GAM进行时间序列分析

每当你发现一个与时间对应的趋势时,你就会看到一个时间序列。我们围绕广义加性模型GAM技术进行一些咨询,帮助客户解决独特的业务问题。研究金融市场表现和天气预报的事实上的选择,时间序列是最普遍的分析技术之一,因为它与时间有着…

matlab图像的运算有点运算、代数运算、逻辑运算和几何运算

1.图像的点运算 2.图像的代数运算 3.图像的逻辑运算 4.图像的几何运算 一、图像的点运算 图像的点运算:对图像中的每个像素值进行计算,从而改善图像显示效果的操作,常用于改变图像的灰度范围及分布,有时也被称为对比度增强和拉伸…

Arduino开发实例-DIY酒精浓度检测计

DIY酒精浓度检测计 在本文中,将详细介绍如何创建一个简单的酒精检测器。 它可以在各种应用领域中使用。市场上有许多先进的酒精传感器,价格合理,但我们在这里使用一些基本的微控制器来制作这个项目,如 Arduino、LED、蜂鸣器和 MQ3 酒精传感器。 1、MQ-3传感器介绍 MQ-3传…

外卖项目(项目优化2)11---读写分离

读:查询的操作 目录 一、Mysql主从复制 172 1.1Mysql主从复制_配置主库Master&从库Slave 173 配置:主库Master: 配置:从库Slave 二、读写分离案例 175 2.1背景 2.2Sharding-JDBC介绍 2.3读写分离案例---入门案例 17…

Magic Leap 2设计和开发幕后花絮

Magic Leap今年发布新款AR头显Magic Leap 2,相比于上一代Magic Leap 1,新品更专注于B端场景,自公布以来,Magic Leap不仅对公司策略、理念更加透明,也不断公开ML2产品设计背后的思考。相比于ML1,ML2的设计有…

里P7告诉你,接口测试真的很简单,有手就行

一、什么是接口测试? 所谓接口,是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试,则是通过接口的不同情况下的输入,去对比输出,看看是否满足接口规范所规定的功能、…

windows bat批处理文件,实现某个软件的重启

bat批处理实现软件重启功能windows环境需要明确的概念按照启动文件xxx.exe去定位某个程序的Pid根据pid杀死某个进程根据exe文件启动某个软件bat示例,杀死软件进程并重启windows环境 我这里用的是win10企业版,在基础功能上和家庭版区别不大 需要明确的概…

19uec++多人游戏【基础AI导航】

首先把这一期的资源导入一下 创建一个球体类,继承于pawn类 为其添加静态组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "Components")class UStaticMeshComponent * MeshComponent; #include "Components/StaticMeshComponent.h&qu…

具备统一门户功能的内网即时通讯软件才是发展趋势

作为企业领导,我们最害怕的就是下属工作效率不高,没办法为企业带来价值,有时候并不一定是员工自身存在问题,“工欲善其事,必先利其器“正好说明了,如果我们有能力在线的员工加上强大的办公软件辅助&#xf…

如何线上登记版权?

问题一:为什么要登记版权? 告诉你一个行业秘密,其实可以不用登记版权,为什么?因为作品自完成就自动拥有版权,作者可以自己选择登记与否,不登记对版权也没有影响。这里可能有人要问了&#xff0…

xss-labs/level12

这一关首先尝试以下 <script>alert(xss)</script> 不废话 直接看源代码 很明显发现第一个输出点被转义了 根本无法通过script标签来完成弹窗 然后依然是四个隐藏表单 我们可以先试一试在不用抓包工具的前提下 我们能不能将某个隐藏表单给显示出来 构造如下 &l…

Docker的常用基础命令(详细讲解)

首选需要大家搭建好Docker环境&#xff0c;没有环境的可以查看前面的详细讲解安装Docker引擎的文章&#xff08;在CentOS上安装Docker引擎_征服bug的博客-CSDN博客&#xff09; 首先是安装好Docker 引擎 一&#xff0c;如何启动与停止引擎服务 #启动docker systemctl start do…

JAVA-GUI工具的编写-----请求篇

上节我们说到&#xff0c;我们制作了样子货的GUI&#xff0c;但是没有嵌入任何的按钮事件&#xff0c;并且上一次忘记加进去命令执行的确定按钮&#xff0c;让我们简单的回顾一下子吧 import javafx.application.Application; import javafx.collections.FXCollections; impor…

R在GIS中用ggmap地理空间数据分析

概要 做过O2O&#xff08;Online To Offline,在线离线/线上到线下&#xff09;的小伙伴知道&#xff0c;GIS数据需要具体到精准的位置(即经纬度)&#xff1b;对于连锁门店&#xff0c;使用GIS和其它的数据密集型服务遵循一个简单的逻辑&#xff1a;数据有助于企业节省开支&…

Vilatile底层逻辑总结

#### 增加volatile 使用JIT优化的时候 禁止出现语句重排 #### volatile是Java虚拟机提供的轻量级同步机制。 - 保证可见性 - 不保证原子性&#xff08;整体流程成功 整体流程失败&#xff09;如果要保证原子性-加 synchronized 或者直接使用 Automic 原子类 - 禁止指令重排&am…

VBA Regex 正则表达式应用介绍

. VBA正则表达式介绍 正则表达式或 RegEx 用于在字符串中查找特定的字符。 本文将展示一个 VBA RegEx 示例,并演示为什么在 VBA 中使用正则表达式如此强大。 正则表达式是一个比较大的话题,关于这方面的书很多。 同时也是一个让许多人感到害怕的话题,因为它的语法比较神秘和…