httprunnerV4.X的基本使用详解

目录

1、httprunner概述

1.1、httprunner的优点

2、httprunner的安装

3、基本命令的使用

3.1、生成脚手架

3.2、将har文件转换为测试用例文件

3.3、执行测试用例

3.4、为项目创建虚拟环境,然后安装httprunner库

3.4、执行测试用例生成测试报告

4、httprunner各个模块的使用

4.1、httprunner命名规范

4.2、httprunner的各个模块介绍

4.3、使用RunRequest完成一次接口的请求

4.3.1、测试用例名

4.3.2、请求方式

4.3.3、请求头信息添加

4.3.4、cookie信息添加

4.3.5、请求参数添加

4.3.6、参数提取

4.3.7、断言

5、全局变量的配置与使用

6、局部变量的配置与使用

7、辅助函数的使用

8、接口参数关联使用

8.1、获取当前用例文件其他已执行Step提取的参数

8.2、获取执行引用测试用例提取出的参数

9、数据驱动

9.1、单组数据驱动

9.2、多组数据驱动

10、文件上传


注:本文使用的httprunner v4.3.0版本与v3.X版本的使用略有不同

1、httprunner概述

  • HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,继承request的全部特性,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。

1.1、httprunner的优点

  • 可使用抓包工具导入请求为har文件,在httprunner内支持har文件转换成json、yaml、pytest文件 。
  • httprunner集成了loguru日志模块,添加日志更加方便。
  • httprunner集成了locust模块,支持了性能测试:
  • httprunner支持响应结果参数提取,接口参数关联。
  • 生成脚手架功能
  • httprunner集成了pytest框架,支持pytest的所有命令

2、httprunner的安装

  • 说明:以下命令是安装官网最新版本的编译工具:
    • 此处安装的是一个exe文件,v4版本后httprunner可作为一个外部工具使用,可用于生成脚手架,用例执行,用例转换,要在具体的代码中使用还需重新安装httprunner库

pip install httprunner

  • 安装指定版本

pip install httprunner==4.3.0

  • 查看版本号,检查是否安装成功

hrp -v

3、基本命令的使用

3.1、生成脚手架

  • 命令:

hrp startproject prodject_name

  • har: har文件夹存放har文件,har文件可以通过charles或者其他抓包工具来获取
  • reports:存放测试报告
  • testcases:存放测试用例的文件集(在脚手架生成后,会自动带入两个yaml示例文件)
  • debugtalk.py: 在这里写入的方法,可以拿到测试用例中调用

3.2、将har文件转换为测试用例文件

  • 1、从fiddler中导出请求为har文件

  • 2、将har用例转换为py、yaml、json格式的用例
    • 查看hrp帮助命令

hrp --help

  • 查看转换帮助命令

hrp convert --help

  • 可以看到转换成不同的用例格式的命令

# 转换为json格式
hrp convert demo.har --to-json

# 转换为pytest格式
hrp convert demo.har --to-pytest

# 转换为yaml格式
hrp convert demo.har --to-yaml

3.3、执行测试用例

  • 使用命令执行测试用例

hrp run demo_test.json
hrp run demo_test.yaml
hrp run demo_test_test.py

3.4、为项目创建虚拟环境,然后安装httprunner库

  • 1、进入项目目录,创建虚拟环境env_demo

virtualenv env_demo

  • 2、激活虚拟环境

cd env_demo\Scripts
activate

  • 3、安装httprunner库

pip install httprunner==4.3.0

  • 4、安装httprunner库之后可以使用pytest相关所有命令,如:

# 使用pytest执行测试用例
pytest demo_test.py


# 使用pytest执行测试用例,并在控制台输出详细日志信息
pytest -s demo_test.py

3.4、执行测试用例生成测试报告

  • httprunner 集成了pytest,支持allure。但是httprunner 默认并未安装 allure,需要另外安装。
  • 安装有两种方式:
    • 1、安装allure 的pytest依赖库allure-pytest

pip install allure-pytest

  •  2、安装httprunner的allure依赖库httprunner[allure]

pip install "httprunner[allure]"

  • 1、使用hrun命令(是安装的httprunner库中带有的,不是外部安装的hrp)生成测试报告

hrun testcase --alluredir=allure-results --clean-alluredir

参数说明:

  • --alluredir=DIR::生成 allure 报告的结果数据到指定目录
  • --clean-alluredir:在生成结果数据之前清理--alluredir参数指定的目录
  • --allure-no-capture:pytest 捕获的日志记录(logging)、标准输出(stdout)、标准错误(stderr)不会附加到报告中

  • 2、生成测试报告
    • 说明:生成测试有两种方式:
      • 1、根据结果数据文件生成HTML形式的allure报告,然后再pycharm中使用浏览器打开生成的这个HTML文件
      • 2、直接使用allure服务生成allure报告,该方式是在本地启动一个allure报告服务,报告直接在浏览器端开关
  • 方式一:
    • 命令:

allure generate allure-results-path -o allure-report-path  -c

参数说明:
-o 指定生成报告的文件夹
-c 在生成报告之前先清理之前的报告目录

  • 方式二:
    • 命令

allure serve allure-results-path

4、httprunner各个模块的使用

4.1、httprunner命名规范

  • 类名开头必须是Test,且必须继承httprunner
  • teststeps为测试步骤,每一个测试步骤叫做Step
  • Step里的RunRequest,是每个Step测试的API
  • 测试用例文件的后缀必须是_test.py

4.2、httprunner的各个模块介绍

from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

  • HttpRunner:所有的测试用例类必须继承于HttpRunner
  • Config:当前测试用文件的全局配置,可以配置全局变量,base_url,导出变量
  • Step:测试步骤,每一条测试用例对应一个Step
  • RunRequest:每一条测试用例的执行封装
  • RunTestCase:用于在当前测试用例类中引入其他测试用例并执行,实现了不同接口之间的参数关联

不同模块之间相互关系,以及使用方式:

class TestCaseDemoTest(HttpRunner):config = Config("testcase description")teststeps = [Step(RunRequest("")),Step(RunTestCase("")),]

4.3、使用RunRequest完成一次接口的请求

4.3.1、测试用例名

  • 支持中文

RunRequest("auth")

示例:

4.3.2、请求方式

  • httprunner支持:get、post、put、head、delete、options、patch等请求方式

示例:

  • get:表示这是一个get请求方式的接口
  • post:表示这是一个post请求方式的接口

接口里面参数可以是完整的api URL地址,也可以是只有资源路径的URL地址(这时需要再Config中配置base_url)

如:

或者

4.3.3、请求头信息添加

  • 请求接口的headers的参数使用with_headers存放格式为字典格式,但是需要加上**才能正常获取到参数。
.with_headers(**{":method": "POST",":path": "/auth-ws/auth/auth",":scheme": "https","accept": "application/json, text/javascript, */*; q=0.01","accept-encoding": "gzip, deflate, br","accept-language": "zh-CN,zh;q=0.9","content-length": "59","content-type": "application/x-www-form-urlencoded; charset=UTF-8","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",}
)

4.3.4、cookie信息添加

  • 请求接口的cookie的参数使用with_cookies存放格式为字典格式,但是需要加上**才能正常获取到参数。
with_cookies(**{"JSESSIONID": "dgssdggdfhdfghEF6B9487sdgsg4FE","lc_cookieid": "a393cbfcfsdfsd94c2537a2","lc_sub_client": "h5","ngx-auth-ws": "307fdsf192efdsfsdsdgsdsd99bfsd730e",}
)

4.3.5、请求参数添加

1、data类型的参数

  • 使用with_data()函数添加
.with_data({"password": "admin","userName": "test","validateCode": "1",}
)

2、json类型的参数

  • 使用with_json()函数添加
.with_json({"password": "admin","userName": "test","validateCode": "1",}
)

4.3.6、参数提取

  • 使用with_jmespath()函数来完成响应参数的提取

1、响应头参数提取

extract().with_jmespath('headers.Server', 'server')

2、 cookies参数提取

extract().with_jmespath("cookies.token","token")

3、 body参数的提取

  • 注意:在httprunner中响应体的数据都被封装在了body下,所以在提取响应体的内容时需要加上body
  • 1、提取字符串类型的参数,直接一级一级的提取,示例:
.extract().with_jmespath("body.data.sitePortalUrl", "sitePortalUrl")
  • 2、提取列表类型的中的某个参数,需要指出具体的下标,示例:
.extract().with_jmespath("body.data.info_list[0]", "name")

4.3.7、断言

  • httprunner内置了非常丰富的断言方法,具体使用如下:

  • 1、断言状态码相等
.validate().assert_equal("status_code", 200, "assert response status code")
  • 2、断言获取到的值,是否大于预期值
.validate().assert_greater_than("body.data.count", 100) 

5、全局变量的配置与使用

  • 全局变量的配置在Config中配置,配置后可以在当前测试文件中的所有Step中使用;如:
config = Config("登录流程").variables(**{"userName": "13000000000","password": "222",}
)
  • 在测试用例中使用:
    • 变量的提取:使用:$变量名 或 ${变量名的方式}
.with_data({"password": "$password","userName": "$userName","validateCode": "1",}

6、局部变量的配置与使用

  • 局部变量配置在RunRequest或RunTestCase中使用,只针对当前配置的测试用例使用,使用变量方式如上:
Step(RunRequest("用户名密码正确正常登录").with_variables(**{"userName": "13000000000","password": "222",})

7、辅助函数的使用

  • 要想在测试用例文件的某个地方使用自定义的函数,流程如下:
    • 1、先在debugtalk.py文件中自定义函数,如:sum(a, b)函数
    • 2、在测试用例文件引用的方式是:${sum($a, $b)}

示例:

  • 1、在debugtalk.py文件中定义函数

  • 2、在接口请求数据中使用该函数
.with_data({"password": "$password","userName": "${get_username($username)}","validateCode": "1",}
)

8、接口参数关联使用

8.1、获取当前用例文件其他已执行Step提取的参数

  • 注意:下面的Step都是在login.py文件中
  • 获取接口/auth-ws/auth/auth响应的sitePortalUrl参数
Step(RunRequest("auth").with_variables(**{"userName": "13000000000","password": "222",}).post("/auth-ws/auth/auth").with_headers(**{":method": "POST",":path": "/auth-ws/auth/auth",":scheme": "https","accept": "application/json, text/javascript, */*; q=0.01","accept-encoding": "gzip, deflate, br","accept-language": "zh-CN,zh;q=0.9","content-length": "59","content-type": "application/x-www-form-urlencoded; charset=UTF-8","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",}).with_cookies(**{"JSESSIONID": "dasdsadasBdasds444dsadE","lc_cookieid": "asdnksajdkaslsapkfposakf7a2","lc_sub_client": "h5","ngx-auth-ws": "3dsajdfghiaushassadase",}).with_data({"password": "$password","userName": "${get_username($username)}","validateCode": "1",}).extract().with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl").validate().assert_equal("status_code", 200, "assert response status code")
  • 使用接口/auth-ws/auth/auth响应的提取出的sitePortalUrl参数
Step(RunRequest("login").post("/platform-ms/api/user/login").with_headers(**{"content-type": "application/json; charset=UTF-8",}).with_json({"ticket": "${get_ticket($sitePortalUrl)}"}).extract().with_jmespath("headers.token", "token").validate().assert_equal("status_code", 200, "assert response status code")
)

8.2、获取执行引用测试用例提取出的参数

  • 说明:在addMaterial_test_test.py文件引用执行login.py文件,并获取login文件中提取的token变量

9、数据驱动

  • 使用数据驱动模块,需要导入pytest、Parameters模块

import pytest
from httprunner import Parameters

9.1、单组数据驱动

  • 注意:Parameters模块中的数据同样可以来自执行debugtalk.py中的函数返回
from httprunner import HttpRunner, Config, Step, RunRequest, Parameters
import pytestclass TestCaseAuthTest(HttpRunner):config = Config("登录流程").base_url("http://test.com/")teststeps = [Step(RunRequest("auth").post("/auth-ws/auth/auth").with_headers(**{":method": "POST",":path": "/auth-ws/auth/auth",":scheme": "https","accept": "application/json, text/javascript, */*; q=0.01","accept-encoding": "gzip, deflate, br","accept-language": "zh-CN,zh;q=0.9","content-length": "59","content-type": "application/x-www-form-urlencoded; charset=UTF-8","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",}).with_cookies(**{"JSESSIONID": "2D4166B552B9487E","lc_cookieid": "a393cbfc2","lc_sub_client": "h5","ngx-auth-ws": "307f4c81190d0fe99b30e",}).with_data({"password": "$password","userName": "$username","validateCode": "1",}).extract().with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl").validate().assert_equal("status_code", 200, "assert response status code"))]@pytest.mark.parametrize("param",Parameters({"userName": ["test1",  "test2", "test3"]# 也可通过调用debugtalk.py文件中函数获取#  "userName": "${get_username()}"}))def test_start(self, param):super().test_start(param)

9.2、多组数据驱动

  • 数据配置多组,对配置的数据进行笛卡尔积计算,如:3*3,最后需要执行九组测试用例
from httprunner import HttpRunner, Config, Step, RunRequest, Parameters
import pytestclass TestCaseAuthTest(HttpRunner):config = Config("登录流程").base_url("http://test.com/")teststeps = [Step(RunRequest("auth").post("/auth-ws/auth/auth").with_headers(**{":method": "POST",":path": "/auth-ws/auth/auth",":scheme": "https","accept": "application/json, text/javascript, */*; q=0.01","accept-encoding": "gzip, deflate, br","accept-language": "zh-CN,zh;q=0.9","content-length": "59","content-type": "application/x-www-form-urlencoded; charset=UTF-8","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",}).with_cookies(**{"JSESSIONID": "87D154FE","lc_cookieid": "a393c2537a2","lc_sub_client": "h5","ngx-auth-ws": "307f4c8e99b43730e",}).with_data({"password": "$password","userName": "$username","validateCode": "1",}).extract().with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl").validate().assert_equal("status_code", 200, "assert response status code"))]@pytest.mark.parametrize("param",Parameters({"userName": ["test1",  "test2", "test3"]"passWord": [123, 456, 789]}))def test_start(self, param):super().test_start(param)

10、文件上传

  • httprunner使用的是requests-toolbelt模块完成文件上传功能,但是httprunner并没有安装这个库,需要单独安装,使用以下方式安装:
  • 注意:如果使用pip install requests-toolbelt安装可能因为安装到了最新版本requests-toolbelt模块从而导致与httprunner使用的requests-toolbelt版本不相同而导致错误

pip install "httprunner[upload]"

  • 使用pip install "httprunner[upload]"安装的库版本是0.9.1的,这时可能和库中的urllib3发生版本不匹配(如果urllib3库是2.0.0版本以上就会冲突),所以需要将urllib3库删除了再重新安装低版本的,如:1.25.11

pip install urllib3==1.25.11

示例如下:

from httprunner import HttpRunner, Config, Step, RunRequest
class TestCaseAddmaterialTest(HttpRunner):config = Config("testcase description")teststeps = [Step(RunRequest("上传文件").post("http://test.com/platform-ms/api/upload/uploadFile").with_headers(**{"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Authorization": "${get_token()}","Content-Type": "multipart/form-testdatas; boundary=----WebKitFormBoundaryi26ZrOKdu2tMFYa7",}).with_params(**{"businessKey": "material","picUrl": "(binary)"}).upload(**{"file": r"E:\WorkPlace\test\demo\CS.png", "title": "测试图片上传"}).validate().assert_equal("status_code", 200, "assert response status code"))

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

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

相关文章

CSS 双色拼接按钮效果

<template><view class="sss"><button> <!-- 按钮 --><view class="span"> 按钮 </view> <!-- 按钮文本 --></button></view></template><script></script><style>body {b…

【Git】windows系统安装git教程和配置

一、何为Git Git(读音为/gɪt/)是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 二、git安装包 有2种版本&#xff0c;Git for Windows Setup和Git for Windows Portable(便携版)两个版本都可以。 三、Git for Windows Por…

应急响应红蓝工程师白帽子取证Linux和windows入侵排查还原攻击痕迹,追溯攻击者,以及各种木马和病毒以及恶意脚本文件排查和清除

应急响应红蓝工程师白帽子取证Linux入侵排查还原攻击痕迹,追溯攻击者,以及各种木马和病毒以及恶意脚本文件排查和清除。 一般服务器被入侵的迹象,包括但不局限于:由内向外发送大量数据包(DDOS肉鸡)、服务器资源被耗尽(挖矿程序)、不正常的端口连接(反向shell等)、服务…

Go 知识chan

Go 知识chan 1. 基本知识1.1 定义1.2 操作1.3 操作限定1.4 chan 读写 2. 原理2.1 数据结构2.2 环形队列2.3 等待队列2.4 类型消息2.5 读写数据2.6 关闭chan 3. 使用3.1 操作符使用3.2 select3.3 for-range https://a18792721831.github.io/ 1. 基本知识 chan是go里面里面提供…

源码篇--Redis 五种数据类型

文章目录 前言一、 字符串类型&#xff1a;1.1 字符串的编码格式&#xff1a;1.1.1 raw 编码格式:1.1.2 empstr编码格式:1.1.3 int 编码格式:1.1.4 字符串存储结构展示: 二、 list类型&#xff1a;2.1 List 底层数据支持&#xff1a;2.2 List 源码实现&#xff1a;2.3 List 结构…

微信小程序-04

rpx&#xff08;responsive pixel&#xff09;是微信小程序独有的&#xff0c;用来解决屏适配的尺寸单位。 import 后跟需要导入的外联样式表的相对路径&#xff0c;用 ; 表示语句结束。 定义在 app.wxss 中的样式为全局样式&#xff0c;作用于每一个页面。 在页面的 .wxss 文…

独享http代理安全性是更高的吗?

不同于共享代理&#xff0c;独享代理IP为单一用户提供专用的IP&#xff0c;带来了一系列需要考虑的问题。今天我们就一起来看看独享代理IP的优势&#xff0c;到底在哪里。 我们得先来看看什么是代理IP。简单来说&#xff0c;代理服务器充当客户机和互联网之间的中间人。当你使用…

幻兽帕鲁一键开私服?超简单小白教程一看就会!

如何自建幻兽帕鲁服务器&#xff1f;基于阿里云服务器搭建幻兽帕鲁palworld服务器教程来了&#xff0c;一看就懂系列。本文是利用OOS中幻兽帕鲁扩展程序来一键部署幻兽帕鲁服务器&#xff0c;阿里云服务器网aliyunfuwuqi.com分享官方基于阿里云服务器快速创建幻兽帕鲁服务器教程…

Python学习之路-Django基础:PythonWeb

Python学习之路-Django基础:PythonWeb Python Web 框架要点 处理流程 图片来源于未来的小牛的CSDN博客 意义 用于搭建Web应用程序&#xff0c;免去不同Web应用相同代码部分的重复编写&#xff0c;只需关心Web应用核心的业务逻辑实现 Web应用程序的本质 接收并解析HTTP请求…

HCIA学习作业三

要求&#xff1a; 拓扑图&#xff1a; <AR1>ping 5.5.5.1 <AR1>display ip interface brief <AR1>display ip routing-table <AR1>display ip routing-table protocol static <AR2>ping 5.5.5.1 <AR2>display ip interface brief <…

Linux实现:从倒计时到进度条

文章目录 1.回车与换行2.缓冲区的概念3.倒计时4.进度条(第一版无应用场景)5.进度条(第二版有应用场景) 1.回车与换行 2.缓冲区的概念 强制刷新可以使用冲刷函数fflush #include <stdio.h> #include <unistd.h> int main() {printf("I am a \nhandsome man!&q…

排序(1)——直接插入排序、希尔排序

目录 一、直接插入排序 1.简介 2.思路与代码 3.复杂度与稳定性分析 &#xff08;1&#xff09;时间复杂度 &#xff08;2&#xff09;空间复杂度 &#xff08;3&#xff09;稳定性 二、希尔排序 1.简介 2.思路与代码 &#xff08;1&#xff09;分组排序 &#xff08…

系统架构设计师教程(十七)通信系统架构设计理论与实践

通信系统架构设计理论与实践 17.1 通信系统概述17.2 通信系统网络架构17.2.1局域网网络架构17.2.2 广域网网络架构17.2.3 移动通信网网络架构17.2.4存储网络架构17.2.5 软件定义网络架构17.3 网络构建关键技术17.3.1 网络高可用设计17.3.2 IPv4与IPv6融合组网技术17.3.3 SDN技术…

09. Springboot集成sse服务端推流

目录 1、前言 2、什么是SSE 2.1、技术原理 2.2、SSE和WebSocket 2.2.1、SSE (Server-Sent Events) 2.2.2、WebSocket 2.2.3、选择 SSE 还是 WebSocket&#xff1f; 3、Springboot快速集成 3.1、添加依赖 3.2、创建SSE控制器 3.2.1、SSEmitter创建实例 3.2.2、SSEmi…

macOS跨进程通信: Unix Domain Socket 创建实例

macOS跨进程通信: Unix Domain Socket 创建实例 一&#xff1a; 简介 Socket 是 网络传输的抽象概念。 一般我们常用的有Tcp Socket和 UDP Scoket&#xff0c; 和类Unix 系统&#xff08;包括Mac&#xff09;独有的 Unix Domain Socket&#xff08;UDX&#xff09;。 Tcp So…

Scratch:启蒙少儿编程的图形化魔法

在当今这个数字化时代&#xff0c;编程已经成为了一项重要的基础技能。就像学习阅读和写作一样&#xff0c;掌握编程能够打开通往未来世界的大门。对于孩子们来说&#xff0c;Scratch作为一种图形化编程语言&#xff0c;不仅简单有趣&#xff0c;而且非常适合作为编程学习的入门…

科技助力“双碳”:墨水屏电子桌牌在绿色办公中的作用

随着科技的发展&#xff0c;人们对绿色环境可持续发展也越来越重视&#xff0c;所以&#xff0c;我国在几年前&#xff0c;就提出了“双碳”政策&#xff08;即碳达峰与碳中和的简称。2020年9月中国明确提出2030年“碳达峰”与2060年“碳中和”目标&#xff09;&#xff0c;而作…

单调栈第二天(还没写完)

503.下一个更大元素II 力扣题目链接(opens new window) 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更…

卸载软件Geek Uninstaller,MySQl安装不成功

最近刷最右的时候&#xff0c;看到两个帖子都是MySQl安装过程总是出现问题。大概两年前我也遇到了这个问题&#xff0c;推荐一款软件。 是因为在安装的过程之中&#xff0c;出现了问题。然后你再进行安装的时候&#xff0c;没有完全将原来安装的软件卸载掉&#xff0c;导致有注…

垃圾填埋气体监测与告警一体化环保监测5G云网关

数字化时代数据采集和传输我认为变得非常重要。为了满足这一需求&#xff0c;我们推出了一款具备多种功能的数据采集器。这款产品不仅集成了8DI干湿节点、4DO继电器、6AI电流/电压型传感器&#xff0c;还支持与多个云平台进行上行对接。通过这些功能&#xff0c;用户可以轻松实…