全网火爆,Python接口自动化测试Mock服务详细总结(实战场景)

news2024/11/22 21:16:38

目录:导读

    • 前言
    • 一、Python编程入门到精通
    • 二、接口自动化项目实战
    • 三、Web自动化项目实战
    • 四、App自动化项目实战
    • 五、一线大厂简历
    • 六、测试开发DevOps体系
    • 七、常用自动化测试工具
    • 八、JMeter性能测试
    • 九、总结(尾部小惊喜)


前言

1、Mock实现原理与实现机制

在某些时候,后端在开发接口的时候,处理逻辑非常复杂,在测试的时候,后端在未完成接口的情况下该如何去测试呢?

1)什么是Mock?

Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西。准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代掉指定的Python对象,以达到模拟对象的行为。

2)为什么要使用Mock?

之所以使用mock测试,是因为真实场景很难实现或者短期实现起来很困难。

主要场景有:

  • 真实对象可能还不存在(接口还没有完成开发)
  • 真实对象很难搭建起来(第三方支付联调)
  • 真实对象的行为很难触发(例如网络错误)
  • 真实对象速度很慢(例如一个完整的数据库,在测试之前可能需要初始化)
  • 真实对象可能包含不能用作测试(而不是为实际工作)的信息和方法
  • 真实的对象是用户界面,或包括用户页面在内
  • 真实的对象使用了回调机制
  • 真实对象的行为是不确定的(例如当前的时间或当前的温度)

3)Mock对象适用场景

需要将当前被测单元和其依赖模块独立开来,构造一个独立的测试环境,不关注被测单元的依赖对象,只关注被测单元的功能逻辑。

比如被测代码中需要依赖第三方接口返回值进行逻辑处理,可能因为网络或者其他环境因素,调用第三方经常会中断或者失败,无法对被测单元进行测试,这个时候就可以使用mock技术来将被测单元和依赖模块独立开来,使得测试可以进行下去。

场景如下:

被测单元依赖的模块尚未开发完成,而被测单元需要依赖模块的返回值进行后续处理。
前后端项目中,后端接口开发完成之前,接口联调;

依赖的上游项目的接口尚未开发完成,需要接口联调测试;

比如service层的代码中,包含对Dao层的调用,但是,DAO层代码尚未实现,被测单元依赖的对象较难模拟或者构造比较复杂。

比如,支付宝支付的异常条件有很多,但是模拟这种异常条件很复杂或者无法模拟,比如,查询聚划算的订单结果,无法在测试环境进行模拟。

4)Mock测试存在的问题

使用Mock测试有时可以提高团队的开发效率,但当B、C都开发完成代码后,这时应该把E2E测试代码从使用Mock测试改为调用真实的模块,以避免出现模块之间集成部分漏测的问题。

这里说mock存在的问题,主要是让开发和测试不要过分的依赖/相信mock接口。
使用mock时,切记的几点:

测试人员不应该被覆盖率高的E2E自动化测试所迷惑,覆盖率高不代表没有问题。尤其在接手新项目中,需要查看E2E测试中有没有使用Mock测试,进一步去判断这些地方使用Mock测试是否合理,这些Mock测试是否应该换成真实模块间的调用和集成。

当把mock接口换成实际接口后,测试/开发也必须把之前的测试重新做一遍。

ps: 当你使用mock接口来提高效率,请注意:你的工作量其实是比 直接只用实际接口 多了 一倍的。
如果测试时,偷懒,替换成实际接口后,只是简单测试,那么 当实际接口和mock预期接口有差异时,故障便和你相遇了。

建议: mock接口只能主流程联调/ 异常返回测试,不要过分依赖mock接口进行测试。

测试完毕,上线前,请一定确保 为了mock而做的相关代码/配置文件的修改,已经完全恢复了。

建议:上线checklist中条条列出,并上线前review

2、Mock的使用

1)如何使用mock

思路:
通过代码制造假的输出(结果)
通过代码去模拟假的接口返回数据(模拟的是:访问真实接口的过程就可以省略)

2)Mock的安装和导入

在Python 3.3以前的版本中,需要另外安装mock模块,可以使用pip命令来安装:

pip install mock

然后在代码中就可以直接import进来:

import mock

从Python 3.3开始,mock模块已经被合并到标准库中,被命名为unittest.mock,可以直接import进来使用:

from unittest import mock

mock的本质:

就算接口未开发完,依据约定好的格式要求,进行数据和对象的模拟
摆脱环境问题,如测试服务器可能很不好搭建,或者搭建效率很低。

举个栗子:
基本代码

import requests

url = 'http://localhost:8090/login'
data = {
    "username":"xiaoqiang",
    "password":"1"
}
res=requests.post(url,data).json()
print(res)

接口的呈现角度看应该是个方法,更合理,那么就有了如下:

import requests

url = 'http://localhost:8090/login'
data = {
    "username": "xiaoqiang",
    "password": "1"
}

def requests_post(url, data):
    res = requests.post(url, data).json()
    print(res)
    return res

其实本质来看,就是要模拟的是返回值

3)使用mock进行数据模拟

示例代码

# -*- coding: utf-8 -*-

import unittest
import mock
import requests


def post_request(url, data):
    """
    POST请求
    """
    res = requests.post(url, data).json()
    print(res)
    return res

def get_request(url):
    """
    get请求,返回code码
    """
    res = requests.get(url).status_code
    print(res)
    return res

class TestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()

    def test_case01(self):
        """
        mock测试案例1
        """
        url = 'http://localhost:8090/login'
        # 跟开发约定好的返回示例
        data = {
            "username": "xiaoqiang",
        }
        # 模拟返回的值
        mock_test = mock.Mock(return_value=data)
        # 执行结果的值
        post_request = mock_test
        # 本质我们想模拟的就是他呀!
        # res=post_request(url, data)
        # 这么写将会被执行,要去掉方法
        # res = post_request(url, data)
        # 正确写法
        res = post_request
        self.assertEqual("111", res())

    def test_case02(self):
        """
        mock测试案例2
        """
        # 模拟返回的值
        mock_test =mock.Mock(return_value='200')
        # 执行结果的值
        get_request = mock_test
        res=get_request
        self.assertEqual('200',res())


    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()


if __name__ == '__main__':
    unittest.main()

3、mockrunner的使用

1)启动服务

java -jar moco-runner-0.12.0-standalone.jar http -p 8008 -c config.json

效果:

在这里插入图片描述

2)配置config.json文件

写好配置config.json文件,就可以进行mock数据啦,示例如下:

[
  {
    "response": {
      "text": "This is moco demo!"
    }
  },
  {
    "description": "带参数的get请求示例",
    "request": {
      "uri": "/getwithparam",
      "method": "get",
      "queries": {
        "name": "ztt",
        "age": "18"
      }
    },
    "response": {
      "text": "ztt come back"
    }
  },
  {
    "description": "带参数的post请求示例",
    "request": {
      "uri": "/postwithparam",
      "forms": {
        "name": "ztt",
        "age": "18"
      }
    },
    "response": {
      "json":{
        "name": "ztt",
        "message": "ztt is coming"
      }
    }
  }
]

访问示例:http://localhost:8008/getwithparam?name=ztt&age=18

注意:保存即是热部署

4、Mock在单元测试中的实际使用

1)requests的封装

示例代码

# -*- coding: utf-8 -*-

import json
import sys

import requests
import os

base_path = os.getcwd()
base_path = os.path.dirname(base_path)
sys.path.append(base_path)
host = 'http://localhost:8090/'


class BaseRequest:
    @staticmethod
    def send_post(url, data, **kwargs):
        """
        发送POST请求
        @param url: 请求路径
        @param data: 请求参数
        @param kwargs: 多参
        @return: 响应信息
        """
        res = requests.post(host + url, headers=data, **kwargs).text
        return res

    @staticmethod
    def send_get(url, data, **kwargs):
        """
        发送GET请求
        @param url: 请求路径
        @param data: 请求参数
        @param kwargs: 多参
        @return: 响应信息
        """
        res = requests.get(host + url, params=data, **kwargs).text
        return res

    @staticmethod
    def send_put(url, data, **kwargs):
        """
        发送PUT请求
        @param url: 请求路径
        @param data: 请求参数
        @param kwargs: 多参
        @return: 响应信息
        """
        res = requests.put(host + url, params=data, **kwargs).text
        return res

    @staticmethod
    def send_delete(url, data, **kwargs):
        """
        发送DELETE请求
        @param url: 请求路径
        @param data: 请求参数
        @param kwargs: 多参
        @return: 响应信息
        """
        res = requests.delete(host + url, params=data, **kwargs).text
        return res

    @staticmethod
    def read_json():
        """
        读取json文件
        @return: json文件内容
        """
        with open(base_path + "\\config\\user.json", encoding='utf-8') as f:
            data = json.load(f)
        return data

    @staticmethod
    def get_jsonvalue(caseName, paramName):
        """
        获取配置文件中入参值
        @param caseName: 用例方法
        @param paramName: 用例请求参数名字
        @return: 请求参数值
        """
        json_str = request.read_json()
        request_param = json_str[caseName]
        request_param[paramName]

    def run_main(self, method, url, data, **kwargs):
        """
        执行方法传url
        @param method: 请求方法
        @param url: 请求路径
        @param data:请求参数
        @param kwargs: 多参
        @return: 响应信息
        """

        if method == "get":
            res = self.send_get(url, data, **kwargs)
        elif method == "post":
            res = self.send_post(url, data, **kwargs)
        elif method == "put":
            res = self.send_put(url, data, **kwargs)
        else:
            res = self.send_delete(url, data, **kwargs)
        try:
            res = json.loads(res)
        except:
            print("不是json,只是")
        return res


request = BaseRequest()

if __name__ == '__main__':
    json_str = request.read_json()
    json_str = json_str['test_getStudents']
    print(json_str['method'])

2、结合封装mock的实际应用
示例代码

# -*- coding: utf-8 -*-

import unittest
import mock
from base.base_request import request

config = request.read_json()


class TestCase(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()

    def test_getStudents(self):
        """
        测试get请求获取学生接口
        """
        param = config['test_getStudents']
        method = param['method']
        url = param['url']
        data = param['data']
        # 模拟的请求方法
        mock_method = mock.Mock(return_value=data)
        request.run_main = mock_method
        res = request.run_main(method, url, None)
        print(res)
        self.assertEqual(res['msg'], 'success')

    def test_studentAdd(self):
        """
        入参为json,带请求头的post请求
        :return:
        """
        param = config['test_studentAdd']
        method = param['method']
        url = param['url']
        headers = param['headers']
        request_body = param['request_body']
        data = param['data']
        # 模拟的请求方法
        request.run_main = mock.Mock(return_value=data)
        res = request.run_main(method, url, headers, json=request_body)
        print(res)
        self.assertEqual(res['msg'], 'success')

    def test_upload(self):
        """
        上传文件接口
        :return:
        """
        param = config['test_upload']
        method = param['method']
        url = param['url']
        data = param['data']
        file = open('D:\\data.xls', 'rb')
        files = {'file': file}
        # 模拟方法调用
        request.run_main = mock.Mock(return_value=data)
        res = request.run_main(method, url, None, files=files)
        file.close()
        print(res)
        self.assertEqual(res['msg'], '上传文件成功!')

    def test_studentUpdate(self):
        """
        put请求示例
        :return:
        """
        param = config['test_studentUpdate']
        method = param['method']
        url = param['url']
        params = param['params']
        data = param['data']
        # 模拟方法调用
        request.run_main = mock.Mock(return_value=data)
        res = request.run_main(method, url, params)
        print(res)
        self.assertEqual(res['msg'], 'success')

    def test_studentDelete(self):
        """
        删除接口
        :return:
        """
        param = config['test_studentDelete']
        method = param['method']
        url = param['url']
        data = param['data']
        # 模拟方法调用
        request.run_main = mock.Mock(return_value=data)
        res = request.run_main(method, url, None)
        print(res)
        self.assertEqual(res['msg'], 'success')

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

成功是需要付出辛勤汗水的,但是只要我们坚信自己有能力实现梦想,勇往直前,不畏艰难,坚持不懈,就一定能够取得成功的喜悦。

不要因为一次失败而灰心丧气,失去信心。相反,要更加坚强,更有勇气,更加坚定地向前走,相信自己能够创造无限可能。

成功的秘诀在于坚持不懈,只有通过不断的磨练和提升自己,才能够真正地取得成功。要始终保持积极的态度,勇往直前,为自己而战。

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

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

相关文章

GitHub加速配置

1. 找到要加速的域名 GitHub:github.com(这只是加载主页面的)GitHub下载:codeload.github.com(不唯一,自己去下载链接看) 2. 用域名到DNS解析服务器地址 ITDOG 3. 修改 Hosts 文件 依据解…

PicoDiagnostics (NVH设备软件)-PS软件设置文件类型介绍

作为远程技术指导人员&#xff0c;下面这个功能对你来说可能非常有帮助。 在PicoScope 7 软件的文件保存格式里&#xff0c;通常选择的是<PS 数据文件>类型&#xff0c;容易忽略其他实用的保存文件类型&#xff0c;下面我们介绍<PS设置文件>类型。 PS 数据文件&…

深入理解计算机系统 笔记

写在前面 记录一下《深入理解计算机系统》中的要点。 一、第一章 计算机系统漫游 1. 程序的编译周期 最初编写的源程序xxx.c是一个文本文件&#xff1b;编译系统把源程序编译到可执行目标程序需要经过如下4个阶段&#xff1b; 1.1 预处理阶段 由预处理器&#xff08;cpp&a…

【带头学C++】----- 六、结构体 ---- 6.1 结构体概述

6.1 结构体概述&#xff08;struct&#xff09; 结构体&#xff08;struct&#xff09;是C中用于自定义数据类型的一种机制&#xff0c;它允许将多个不同类型的变量&#xff08;成员变量&#xff09;组合在一起形成一个新的数据类型。结构体允许程序员创建一个包含不同数据类型…

HPV转阴如何合理饮食,对此HPV专家谭巍主任提出自己看法

HPV感染不是小事&#xff0c;如果体内长期携带病毒不转阴&#xff0c;则有可能引发一系列病变。但在HPV转阴方面饮食有着不可或缺的作用&#xff0c;合理饮食对于促进HPV转阴至关重要。而关于HPV人群合理饮食问题&#xff0c;劲松HPV防治诊疗中心主任谭巍将提出一些建议&#x…

数据同步工具调研选型:SeaTunnel 与 DataX 、Sqoop、Flume、Flink CDC 对比

产品概述 Apache SeaTunnel 是一个非常易用的超高性能分布式数据集成产品&#xff0c;支持海量数据的离线及实时同步。每天可稳定高效同步万亿级数据&#xff0c;已应用于数百家企业生产&#xff0c;也是首个由国人主导贡献到 Apache 基金会的数据集成顶级项目。 SeaTunnel 主…

【shardingjdbc】sharding-jdbc分库分表入门demo及原理分析

文章目录 场景配置&#xff1a;概念及原理:代码:思考: 本文中&#xff0c;demo案例涉及场景为sharding jdbc的分库情况。 通俗点说就是由原来的db0_table水平拆分为 db1 t_table &#xff0c;db2.t_table。 demo本身很简单&#xff0c;难点在于分片策略配置到底该怎么写&#x…

宝马所有发动机号码的位置以及型号说明

每个汽车制造商都会为自己生产的汽车底盘和发动机分配一个内部代码&#xff0c;以标识研发和生产项目&#xff0c;而宝马对这些底盘代码和发动机代码更是规划的井井有条&#xff0c;比如发动机有M、N、B、S、P或W等代码标识&#xff0c;而底盘和车身则有E、F、G或i等代码标识。…

2FRE16-43/160LBK4M比例流量阀放大器

比例阀控制放大器技术是电液比例系统中的一个重要组成部分&#xff0c;它主要负责对比例阀进行控制。这种技术可以实现对液压流量或压力的精确控制&#xff0c;从而使系统以更高的精度和更快的响应速度执行各种操作。 比例阀控制放大器主要由三个部分组成&#xff1a;比例阀、…

58 权限提升-网站权限后台漏洞第三方获取

目录 当前知识点在渗透流程中的点当前知识点在权限提升的重点当前知识点权限提升权限介绍利用成功后的思想需要总结的思路演示案例:某挂壁程序后台权限提升-后台功能某BC广告导航页权限提升-漏洞层面苏丹大西瓜GlassFish中间件-第三方 涉及资源 这里包括网站权限、其它权限、系…

自己搭设开源密码管理工具 bitwarden

简介 Bitwarden是一款自由且开源的密码管理服务&#xff0c;用户可在加密的保管库中存储敏感信息&#xff08;例如网站登录凭据&#xff09;。Bitwarden平台提供有多种客户端应用程序&#xff0c;包括网页用户界面、桌面应用&#xff0c;浏览器扩展、移动应用以及命令行界面。[…

老卫带你学---go语言net/http原理解析

go语言net/http原理解析 对于golang&#xff0c;实现一个最简单的http server 非常简单&#xff0c;代码如下&#xff1a; package mainimport ("net/http""fmt" )func Indexhandler(w http.ResponseWriter,r *http.Request) {fmt.Fprintln(w,"hel…

【操作系统】内存的连续分配管理

文章目录 前言连续分配管理的方式单一连续分配固定分区分配动态分区分配如何记录内存的使用情况如何选择分区如何对分区进行回收 前言 当我们的进程在完成编译以后&#xff0c;需要装入内存&#xff0c;此时就有两种方式来进行内存的分配&#xff1a;连续分配、非连续分配。 …

CNKI上最新硕士博士论文pdf格式文件owner密码找回难度

听人说CNKI上比较早期的硕士博士论文pdf格式文件密码修改权限Owner密码是123456&#xff0c;想办法找了几个文件试了试果然如此。 但又听人说CNKI上最新硕士博士论文pdf格式文件owner密码已经不是了。虽然直接移除这种密码的工具到处都是&#xff0c;推测一下新增的owner密码及…

高并发场景下,如何设计订单库存架构,一共9个关键性问题

库存系统可以分为实物库存和虚拟库存两种类型。实物库存的管理涉及到采购、存储、销售和库存轮换等复杂的活动&#xff0c;需要进行供应链管理和仓库管理等工作。相比之下&#xff0c;虚拟库存的管理相对简单&#xff0c;主要适用于线上资源的数量管理&#xff0c;包括各类虚拟…

Python自动化测试之request库详解(一)

在做接口测试&#xff0c;接口自动化测试的时候都会用到很多工具&#xff0c;如postman、jmeter、pytest等工具&#xff0c;除了这些工具外&#xff0c;我们也会用python的第3方库requests来做接口测试。接下来我会专门讲request的系列专题&#xff0c;希望大家能学好request库…

Ansys Lumerical | 用于增强现实系统的表面浮雕光栅

在本示例中&#xff0c;我们使用 RCWA 求解器设计了一个斜面浮雕光栅 (SRG)&#xff0c;它将用于将光线耦合到单色增强现实 (AR) 系统的波导中。光栅的几何形状经过优化&#xff0c;可将正常入射光导入-1 光栅阶次。 然后我们将光栅特性导出为 Lumerical Sub-Wavelength Model …

八个开源免费单点登录(SSO)系统

使用SSO服务可以提高多系统使用的用户体验和安全性&#xff0c;用户不必记忆多个密码、不必多次登录浪费时间。下面推荐一些市场上最好的开源SSO系统&#xff0c;可作为商业SSO替代。 单点登录&#xff08;SSO&#xff09;是一个登录服务层&#xff0c;通过一次登录访问多个应…

通配符SSL证书

通配符SSL证书是一种特殊的数字证书&#xff0c;用于在互联网上建立安全的连接&#xff0c;其特点是可以保护多个子域名&#xff0c;并且具有很高的兼容性和扩展性。本文将详细介绍通配符SSL证书的相关概念、优点和应用等。 首先&#xff0c;我们需要了解什么是SSL证书。 SSL证…

听我的,日志还是得好好打!

大家好&#xff0c;我是老三&#xff0c;不知道大家有没有经历过这样的场景&#xff0c;线上出了问题&#xff0c;着急火燎地去排查&#xff1a; 唉&#xff0c;问题可能出在这个地方&#xff0c;捞个日志看下&#xff0c;卧槽&#xff0c;怎么找不到……哪个**不打日志&#…