接口自动化测试框架搭建全部过程

2023-09-22 15:28:16

思想:
    1、基本目录的搭建
        report:静态输出目录(报告或者日志)
        
        data:静态输入目录(可以存放Excel数据,被读取的一些数据)
        
        utils:实用方法层(这里存放的是项目的公共方法,一般拿到别的项目可以直接使用,列如:读取Excel中的数据,连接数据库,)
        
        apis:接口请求层(这里封装的方法一般都是和项目有关系,列如:发送post请求,发送get请求,登录接口,注册接口,支付接口,加入购物车接口)
        
        testcases:用例目录(用来存放项目中涉及到的用例,用例即包含单接口用例,也包含关联接口用例,管理目录时,也可以通过目录分层结构管理)
        
        conftest:这里存放的是fixture,只对文件的所在目录生效,如果只是单目录用例那么可以在根目录下创建,如果分为分层目录结构的用例,那么为了
                 
                 满足当前目录的用例,可以在该目录下创建一个conftest,用来存放fixture,fixture是pytest框架的根髓
        
        pytest.ini:是pytest的配置文件,可用来存放一些运行配置项,如:-v -s ;或者配置日志输出渠道;该文件的具体配置,可百度学习
        
    2、接口框架的重要思想=======》金字塔的配置
        
        ①report=data---》utils=apis=---》conftest---》pytest.ini---》testcases
        
        ②以上相当于金字塔结构,从左至右为从底部到顶部的过程
        
        ③金字塔精髓之处在于,(上部依赖底部,底部不依赖于上部),举一个列子,(testcases中的用例,需要调用apis目录中的接口请求方法,而apis不会去主动调用testcases),所以
        
            在工作中,我们如果修改了某一个文件,需要往上找,看看谁调用了这个文件,相对应的进行修改

##########################utils中的db.py的封装
import pymysql
 
#
# # 1. 连接数据库
# conn = pymysql.connect(
#     host='服务器地址',
#     port=3306,
#     user='用户名',
#     password='密码',
#     db='数据库名'
# )
# # 2. 建立游标
# cur = conn.cursor(pymysql.cursors.DictCursor)  # 没有s 有括号
#
# # 3. 执行sql
# # 3.1 执行查询
# cur.execute("SELECT * FROM cardInfo WHERE cardNumber='hzc_00011';")
# conn.commit()
# # 获取结果
# result = cur.fetchall()
# # result = cur.fetchone() # 取一条少一条
# # cur.fetchmany(3)
# print(result)
#
# # 3.2 执行修改
# # cur.execute("DELETE FROM cardInfo WHERE cardNumber='hzc_00011';")
# # conn.commit()
#
# # 4. 关闭
# cur.close()
# conn.close()
 
 
class DB(object):
    def __init__(self):
        self.conn = pymysql.connect(
            host='服务器地址',
            port=3306,
            user='用户名',
            password='密码',
            db='数据库名',
            autocommit=True
        )
        self.cur = self.conn.cursor(pymysql.cursors.DictCursor)    #添加此配置项,默认commit了,即建立游标
 
    def do_sql(self, sql):
        print('执行sql', sql)
        self.cur.execute(sql)    #执行sql语句
        # self.conn.commit()    
        return self.cur.fetchall()    #返回查询到的所有结果
 
 
class FuelCardDB(DB):    #继承DB
    """执行具体的sql语句"""
    def del_card(self, card_number):
        """执行删除语句"""
        self.do_sql(f"DELETE FROM cardInfo WHERE cardNumber='{card_number}'")
 
    def check_card(self, card_number):
        """执行查询语句"""
        result = self.do_sql(f"SELECT * FROM cardInfo WHERE cardNumber='{card_number}';")
        if result:
            return True
        return False
 
    def add_card(self, card_number):
        """执行添加语句"""
        result = self.check_card(card_number)
        if not result:
            self.do_sql(f"INSERT INTO cardInfo (cardNumber) VALUES ('{card_number}');")

#######################api文件的封装

思想:该文件可以将不同的请求方法,不同的请求地址接口,封装成一个类,然后在用例层用到了哪一个就去调取哪一个
以下实列是添加加油卡项目

import requests
 
DATA_SOURCE_ID = "bHRz"
 
 
class Api(object):
    def __init__(self, base_url):
        self.url = base_url + '/gasStation/process'
        self.session = requests.session()
 
 
    def add_fuelcard(self, card_number):
        json_data = {"dataSourceId": DATA_SOURCE_ID, "methodId": "00A", "CardInfo": {"cardNumber": card_number}}
        res = self.session.post(self.url, json=json_data)
        print(res.text)
        return res
 
 
    def bind_card(self, user_name, id_type, id_number, card_number):
        json_data = {
            "dataSourceId": DATA_SOURCE_ID,
            "methodId": "01A",
            "CardUser": {
                "userName": user_name,
                "idType": id_type,
                "idNumber": id_number
            },
            "CardInfo": {
                "cardNumber": card_number
            }
        }
 
        res = self.session.post(self.url, json=json_data)
        print(res.text)
        return res
 
 
    def query_card(self, user_id, card_number):
        #dataSourceId=bHRjczEx&userId=1039&cardNumber=1111111111&methodId=02A
        params = {
            "dataSourceId": DATA_SOURCE_ID,
            "methodId": "02A",
            "userId": user_id,
            "cardNumber": card_number
        }
        res = self.session.get(self.url, params=params)
        print(res.text)
        return res

思想:该文件下主要封装的是fixtures方法,即为了简化用例层步骤,可以将操作前提步骤和过程步骤在此文件下完成,在该文件下
有一个base_url,这个是安装的插件,安装方法为pip install pytest-base-url

import pytest
from utils.db import FuelCardDB
from apis.fuelcard_api import Api
 
 
@pytest.fixture(scope='session')
def db():
   #实例化一个对象
    return FuelCardDB()
 
 
@pytest.fixture(scope='session')
def api(base_url):
  #实例化一个对象,并将配置文件中的base_url传给Api层的方法
    return Api(base_url)
 
@pytest.fixture
def del_card(db):
 
    def _del_card(card_number):
        db.del_card(card_number)
        yield
        db.del_card(card_number)
 
    return _del_card

#######################pytest.ini文件的封装

思想:上述已说明,该文件为pytest框架的配置文件,即运行用例时会默认执行该文件操纵,注意表达格式,conftest文件和api文件中
都用到了base_url,就是这里的base_url,目的是当服务器地址变了之后,不用去接口层去一一修改服务器地址,只需要修改这里的地址就行,但是
如果接口的请求地址变了,就要去一一修改了,毕竟针对不同的请求地址封装了不同的方法

[pytest]
addopts = -s --html=reports/report.html --self-contained-html
testpaths = testcases
base_url = http://***.***.***.***:***

#######################总结

①接口的主要框架基本已经出来了,当我们需要其他方法时,可以再去相对应的添加,例如读取excel表格数据的方法,可以再封装到utils目录下

②如果需要公共的方法时,可以去百度查一下别人写好的模块,说实话自己写半天也不如人家封装好的实用性更高,我们的目标就是会使用别人封装好的方法就OK了

③如果涉及到自己的业务模块,就要自己去封装了,例如上面所说的,api文件,conftest文件,都是和业务相关的

④对于初级的自动化测试人员,最主要的不是去写框架,而是去运用好别人写好的框架,来设计用例,写用例

⑤一条用例的基本流程:测试环境准备、测试数据准备、发送数据、获取数据响应结果、设置断言、环境清理

7天练完接口自动化测试30个实战项目,28K入职字节测试岗。【自动化测试/接口测试/软件测试/性能测试/Jmeter】

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

在这里插入图片描述

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

更多推荐

夸克扫描王识别精度领跑行业 愿携手各方伙伴探索AIGC应用新范式

日前,在“AIGC与场景化应用创新”主题研讨会上,阿里智能信息事业群夸克视觉技术负责人黄锐华分享了AI技术应用于扫描场景的最新成果。他表示,AIGC给手机扫描产品打开了创新空间,搭载大模型技术的夸克扫描王对识别手写字体、复杂公式和版式理解上的准确率达到了新高度。(夸克视觉技术负责人:黄锐华)经过几十年的发展,扫描技术已

【从入门到起飞】JavaSE—方法引用

🎊专栏【JavaSE】🍔喜欢的诗句:更喜岷山千里雪三军过后尽开颜。🎆音乐分享【Thetruththatyouleave】🥰欢迎并且感谢大家指出我的问题文章目录🍔概述🍔注意🎈如何确定是否是函数式接口🍔示例🎄方法引用的分类🏳️‍🌈引用静态方法🏳️‍🌈引用成员方法🛸注意🏳️‍🌈引用构造方法🛸

python脚本(渗透测试)

python爬取edusrc通过此脚本,可以爬取edusrc的目标信息,生成目标字典,为下一步开发自动化测试工具做准备importqueueimportthreadingimporttimeimportrequestsfrombs4importBeautifulSoupimportredefget_edu_name()

NLP任务评价指标(BLEU,METOR,ROUGH,CIDEr)

BLEU,METEOR,ROUGE一般在机器翻译里用,CIDEr一般在图像字幕生成里用BLEU所谓BLEU,最开始是用于机器翻译中。他的思想其实很native,对于一个给定的句子,有标准译文S1,还有一个神经网络翻译的句子S2。BLEU的思想就是对于出现机器翻译S2的所有短语,看有多少个短语出现在S1中,然后算一下这个

Flink

flink应用场景maven依赖<properties><flink.version>1.17.0</flink.version></properties><dependencies><dependency><groupId>org.apache.flink</groupId><artifactId>flink-str

react 通过ref 获取对应 dom 的位置信息

需求:在点击某个dom元素的时候滚动条要同步滚动进程:获取ref打印,打印出来是一个dom元素,看不到有什么方法查找dom属性信息找到了两个参数,offsetLeft:返回元素的水平偏移位置。offsetTop:返回元素的垂直偏移位置。这两个参数都是基于父节点的,可以直接使用this.cellMainBox.curre

OceanMind海睿思入选弯弓研究院《2023中国营销技术生态图谱8.0》

近日,由国内MarTech领域知名机构弯弓研究院主办的第五届营销数字化大会暨营销科技MarTech交易展在广州成功召开。本次大会发布了《2023中国营销技术生态图谱8.0版》(以下简称“弯弓图谱8.0”),中新赛克海睿思凭借成熟的技术实力成功入选弯弓图谱8.0的中台板块,成为数据与分析领域本土优秀代表服务商之一。随着企

Linux 共享内存

#include<sys/ipc.h>#include<sys/shm.h>intshmget(key_tkey,size_tsize,intshmflg);功能:创建一个新的内存段或者获得一个既有的共享内存段的标识。新创建的内存段中的数据都会被初始化为0参数:-key:key_t类型是一个整型,通过这个创建或者找到一

Linux查看程序和动态库依赖的动态库

一.前言在一些时候,我们需要知道一个程序或者动态库所依赖的动态库有哪些。比如,当我们运行一个程序的时候,发现可能会报错,提示找不到某个符号,这时我们就需要知道程序依赖了什么库,从而添加对应需要的动态库。等等,接下来介绍两种方法查看程序和动态库所依赖的动态库。二.方法介绍1.使用objdump命令objdump-pFIL

Toaster - Android 吐司框架,专治 Toast 各种疑难杂症

官网https://github.com/getActivity/Toaster这可能是性能优、使用简单,支持自定义,不需要通知栏权限的吐司想了解实现原理的可以点击此链接查看:Toaster源码集成步骤如果你的项目Gradle配置是在7.0以下,需要在build.gradle文件中加入allprojects{repos

(总目录)springboot - 实现zip文件上传并对zip文件解压, 包含上传oss

全文目录,一步到位1.本文概述1.1本文简介2.功能实现2.1统一文件校验2.2普通(多)文件上传[服务器]2.2.1controller层2.2.2service层2.2.3业务impl实现类2.2.4FileIOUtils工具包代码2.3zip文件的解压2.4图片文件的压缩2.5oss文件后端上传2.6oss文件前

热文推荐