iOS App自动化测试:从环境搭建到实际应用(Python+pytest+appium+allure框架)

iOS App自动化测试:Python+pytest+appium+allure

一、环境准备:

1.1 Appium环境搭建

  1. Windows端:Windows端appium环境搭建
  2. Mac端:Mac端appium环境搭建

总结:appium-doctor 是用来检测环境配的是否完整,安装完成之后,重新打开新的命令行窗口,输入命令 appium-doctor。根据提示安装缺少的内容。

1.2 自动化测试依赖工具:Mac端安装WebDriverAgent

参考文章:【iOS】WebDriverAgent 配置-Build-Test 全过程
(开发者账号可以自己购买,或者可以找公司iOS开发团队借用)

1.3 iOS App元素识别工具:Appium Inspector

  1. 从官网下载:appium inspector官网 ,且官网有使用说明
  2. appium inspector使用方法

1、启动Appium Server,设置Host地址为127.0.0.1,Port默认为4723(可改);
2、要启动WebDriverAgent,并停止运行针对同一应用的Python测试脚本;
3、连接真机/模拟器,并获取相应手机参数及测试APP参数。(获取iOS真机的udid、应用的bund id,可以使用工具py-ios-device
4、打开Appium inspector app,输入参数,然后点击Start Session即可。
note:Appium Server中填的就是我们之前启动服务器的参数
Desired Capabilities中填写手机参数(及App参数)
appium inspector示例
获取元素

ios app使用appium inspactor定位元素的手机参数
{"platformName": "ios","appium:platformVersion": "16.0","appium:bundleId": "com.zego.avatar","appium:automationName": "XCUITest","appium:xcodeOrgId": "xxxx",   # 填自己的开发者账号"appium:xcodeSigningId": "iPhone Developer","appium:udid": "401730095f754dd313bbd91c0e000345ab8f638a","appium:deviceName": "iPhone X"
}
android app使用appium inspector定位元素
{"appium:appPackage": "com.zego.goavatar","appium:appActivity": "com.zego.goavatar.view.AvatarMainActivity","platformName": "Android","appium:deviceName": "YSE0221A12000677" 
}

二、测试用例

1. pytest 测试框架组织用例

可参考:Python 自动化测试框架unittest与pytest的区别

1.1 pytest用例编写规则:
  1. 测试文件名必须以"test_“开头或者以”_test"结尾(如test_avatarAPI_iOS.py)
  2. 测试方法必须以”test_"开头
  3. 测试类名必须以"Test_"开头
  4. pytest继承unittest框架,可以兼容unittest用例
1.2 前置后置条件
1.2.1 setup和teardown:pytest提供了模块级、函数级、类级、方法级的setup/teardown

详细可参考:pytest测试用例setup和teardown

  1. 模块级(setup_mode/teardown_mode)开始于模块始末,作用全局
  2. 函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
  3. 类级(setup_class/teardown_class)只在类中的所有用例前/所有用例后运行(在类中)
  4. 方法级(setup_method/teardown_method)只在类中的每条用例前/每条用例后运行(在类中)
  5. 类里面的(setup/teardown)运行在调用方法的前后
1.2.2 pytest常用装饰器
参数化装饰器:@pytest.mark.parametrize()

详细可参考pytest-参数化@pytest.mark.parametrize()
可单参数,多参数(笛卡尔积)

	# 定义@pytest.mark.parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None))
	# 单参数示例gender = [male,female]@allure.story("test_creatAvatar_male:创建默认的男性/女性形象")@pytest.mark.flaky(reruns=0, reruns_delay=3)  # 用例执行失败后,再重试2次,间隔3s@pytest.mark.parametrize('gender', gender)  # 性别:gender=[male,female]def test_createAvatar(self, gender):
装饰器:@pytest.mark.flaky(),用例执行失败后,自动重试
# reruns:重试次数,reruns_delay:重试之间的最小间隔时间
@pytest.mark.flaky(reruns=2, reruns_delay=3)  # 用例执行失败后,再重试2次,间隔3s

2.测试用例

2.1 初始化参数说明
# 导入webdriver
from appium import webdriver
# 初始化参数
desired_caps = {'platformName': 'Android',  # 被测手机平台:Android/iOS'platformVersion': '10',  # 手机安卓版本'deviceName': 'xxx',  # 设备名,安卓手机可以随意填写'appPackage': 'tv.danmaku.bili',  # 启动APP Package名称'appActivity': '.ui.splash.SplashActivity',  # 启动Activity名称'unicodeKeyboard': True,  # 使用自带输入法,输入中文时填True'resetKeyboard': True,  # 执行完程序恢复原来输入法'noReset': True,  # 不要重置App,如果为False的话,执行完脚本后,app的数据会清空,比如你原本登录了,执行完脚本后就退出登录了'newCommandTimeout': 6000,  # 超时时间可以设置久一些,太短,用例比较多会报错'automationName': 'UiAutomator2'  #  自动化测试引擎 ,默认Appium
}
# 连接Appium Server,初始化自动化环境
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 退出程序
driver.quit()
2.2 初始化参数示例
# 启动参数
iOS_caps = {'automationName': 'XCUITest','bundleId': 'im.xxx.xxx','platformName': 'iOS','platformVersion': '16.0','xcodeOrgId': 'xxxx','xcodeSigningId': 'iPhone Developer','newCommandTimeout': "1200000",   'udid': '401730095f754dd313bbd91c0e000345ab8f638a','deviceName': 'iPhoneX'
}
2.3 appium操作元素

参考文章:appium操作元素总结
Appium之iOS端定位元素中提到:
按查找元素的顺序速度,从快到慢的顺序如下:
ios_predicate >> accessibility_id >> class_name >>xpath
且ios_predicate查找元素最为可靠。

appium定位元素的方式:
find_element_by_*已被废弃,使用find_element来代替
(见WebDriver定位元素(官网)、Appium Python Client(github)

from selenium.webdriver.common.by import Bytext = self.device.find_element(AppiumBy.XPATH, value=self.output_xpath).textclass AppiumBy(By):  # 继承的By类IOS_PREDICATE = '-ios predicate string'IOS_UIAUTOMATION = '-ios uiautomation'IOS_CLASS_CHAIN = '-ios class chain'ANDROID_UIAUTOMATOR = '-android uiautomator'ANDROID_VIEWTAG = '-android viewtag'ANDROID_DATA_MATCHER = '-android datamatcher'ANDROID_VIEW_MATCHER = '-android viewmatcher'# DeprecatedWINDOWS_UI_AUTOMATION = '-windows uiautomation'ACCESSIBILITY_ID = 'accessibility id'IMAGE = '-image'CUSTOM = '-custom'
定位方式:
class By:"""Set of supported locator strategies."""ID = "id"XPATH = "xpath"LINK_TEXT = "link text"PARTIAL_LINK_TEXT = "partial link text"NAME = "name"TAG_NAME = "tag name"CLASS_NAME = "class name"CSS_SELECTOR = "css selector"
2.4 操作元素

在UI自动化测试中用到的click()、drag_and_drop(origin_el=eleA, destination_el=eleB)方法会多一些。
更多方法如下:

# 元素,以IOS_PREDICATE为定位方式举例
element = self.device.find_element(AppiumBy.IOS_PREDICATE,value=self.RE.element('action_predicate')# 1.点击元素
element.click()# 2.清理元素,一般是清空输入框内容
element.clear()# 3.向元素发送文本,一般是向输入框内输入内容
element.send_keys('hello')# 4.提交
element.submit()# 5.拖拽元素从A位置到B的位置
eleA = self.device.find_element(AppiumBy.XPATH,value=self.RE.element('shoes_xpath')
eleB = self.device.find_element(AppiumBy.XPATH,value=self.RE.element('cloth_xpath')
self.device.drag_and_drop(origin_el=eleA, destination_el=eleB)# 6.通过坐标模拟手点击元素
self.device.tap([(100, 20), (100, 60), (100, 100)], 500)
# tap可参考:[appium点击坐标tap方法及封装](https://www.cnblogs.com/syw20170419/p/8192629.html)# 7.截图1:get_screenshot_as_file(filename)参数filename为截图文件保存的绝对路径,图片为png格式,区域全屏幕,如:
self.device.get_screenshot_as_file('../picture/screenshot.png')# 8.截图2:save_screenshot(filename)该方法与get_screenshot_as_file()不同的是,参数为文件名称,保存当前屏幕截图到当前脚本所在的文件,区域全屏幕,如:
self.device.save_screenshot('test_02.png')
2.5 获取元素属性
# 1.获取元素的text
element.text# 2. 获取元素坐标,返回具有元素大小和位置的字典
element.rect# 3.获取元素坐标(返回字典,x,y轴)
element.location# 4.获取元素的size(返回字典)
element.size# 5.获取元素的标签名称
element.tag_name# 6.返回元素是否被启用element.is_enabled() # 7.返回元素是否可选择element.is_selected()# 8.元素是否显示
element.is_displayed()# 9.获取当前会话的活动元素
element = self.device.switch_to.active_element# 10.获取元素属性
element.get_attribute(value)
# 说明:
# value='name' 返回content-desc或者text属性值,二者只能其一
# value='text'返回text的属性值
# value='className'返回class属性值,要API=>18(Android4.2.1以上即可)
# value='resourceId'返回resource-id的属性值,要API=>18(Android4.2.1以上即可)
2.6 断言

在UI自动化测试中,可断言某按钮是否存在,或者截图再通过图片相似度断言图片是否达到预期
(1)断言某个按钮是否存在:

# 如元素element
element = self.device.find_element(AppiumBy.IOS_PREDICATE,value=self.RE.element('action_predicate')
assert element

(2)断言图片相似度
先运行一遍代码,获取截图作为底片,测试时截图作为被测试图片,对比底片和被测图片,获取相似度n(值的范围0~1),再断言n。

截图
appium的截图方法get_screenshot_as_file(filename)截取的是全屏幕,如果要精确截图指定区域,可已使用PIL.Image的crop(box)方法,box位坐标值(x1,y1,x2,y2)

	from PIL import Imagedef screenshot(self, partName, pictureName):# 共用方法:根据坐标区域截图box = (0, 0, 0, 0)if partName == 'default':box = (0, 210, 1110, 1430)  # 区域1elif partName == 'hair':box = (110, 270, 950, 1145)  # 区域2self.device.get_screenshot_as_file('../picture/screenshot.png')  # 路径和名称,图片是.png格式image = Image.open('../picture/screenshot.png')new_image = image.crop(box)new_image.save(pictureName)  # 截取精确区域后的图片

图片相似度
可参考:python OpenCV 图片相似度 5种算法、
Python 五种图片相似度比较方法_佐倉的博客-CSDN博客_python 图片相似度
经过测试,“三直方图算法”比较适合我测试的产品

#! /usr/bin/env python3
# _*_ coding:utf-8 _*_
"""
@Auth : Dora
@Date : 2022/6/13 14:14
"""import cv2
import numpy as np# 三直方图算法
# 通过得到RGB每个通道的直方图来计算相似度
def classify_hist_with_split(image1, image2, size=(256, 256)):# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值image1 = cv2.resize(image1, size)image2 = cv2.resize(image2, size)sub_image1 = cv2.split(image1)sub_image2 = cv2.split(image2)sub_data = 0for im1, im2 in zip(sub_image1, sub_image2):sub_data += calculate(im1, im2)sub_data = sub_data / 3return sub_data# 计算单通道的直方图的相似值
def calculate(image1, image2):hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 计算直方图的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return degreedef runHistHash(image1, image2):img1 = cv2.imread(image1)img2 = cv2.imread(image2)n = classify_hist_with_split(img1, img2)print('三直方图算法相似度:', n)return nif __name__ == "__main__":image1 = '../picture/p11.png'image2 = '../picture/p22.png'runHistHash(image1, image2)

断言插件pytest-assume优化断言,上一个断言失败,可继续执行后续的断言

#!/usr/bin/env python3
#!coding:utf-8
import pytest@pytest.mark.parametrize(('x', 'y'), [(1, 1), (1, 0), (0, 1)])
def test_simple_assume(x, y):assert x == y  #如果这个断言失败,则后续都不会执行assert Trueassert False@pytest.mark.parametrize(('x', 'y'), [(1, 1), (1, 0), (0, 1)])
def test_pytest_assume(x, y):pytest.assume(x == y) #即使这个断言失败,后续仍旧执行pytest.assume(True)pytest.assume(False)

3.测试报告

可参考:Python自动化-allure生成测试报告、
allure自动化测试报告使用详解

3.1 allure在组织用例

格式如下,括号中的说明内容会展示在测试报告中


@allure.feature("Avartar API测试")  # 模块名称
class TestAvatarAPIiOS:@allure.story('创建默认的男性/女性形象')  # 用例名称,对用例的描述@allure.title('test_createAvatar')  # 用例标题def test_createAvatar(self):with allure.step('步骤1:打开应用'):  # 测试用例操作步骤print('应用已打开')with allure.step('步骤2:创建Avatar形象'):print('已生成Avatar形象')print('创建默认形象:创建成功')
3.2 执行用例、生成测试报告并截图
import os
import random
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
import requests
import base64
import hashlib
from WorkWeixinRobot.work_weixin_robot import WWXRobot# 企业微信群机器发消息
webhook = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=d8243e49-47e3-4420-857e-7ffb01c866ec'  # No八哥 群 机器人urlwx_driver = WWXRobot(key=webhook)def runCase_captureReport(runcmd, port):# 执行测试用例-生成报告-并给测试报告截图# 命令执行测试用例# runcmd : 执行测试用例的命令# port:指定的测试报告端口runcmd1 = 'pytest E:/pythonProject/GoAvatarUIAutoTest/testcase/test_GoAvatarUI.py::TestGoAvatar::test_gender_change -s -q --alluredir=../report/result --clean-alluredir'  # 指定单条用例# port = random.randint(1000, 9999)     # 生成随机端口reportcmd = 'allure serve ../report/result -h 192.168.55.183 -p {}'.format(port)  # 测试结果生成报告runcmd2 = 'pytest -v -k change E:/pythonProject/GoAvatarUIAutoTest/testcase/test_GoAvatarUI.py -s -q --alluredir=../report/result --clean-alluredir'  # 指定单条用例runcmdall = 'E:/pythonProject/GoAvatarUIAutoTest/pytest testcase/test_GoAvatarUI.py -s -q --alluredir=./report --clean-alluredir'rungo = os.popen(runcmd)runmsg = rungo.read()print(runmsg)sleep(3)reportrun = os.popen(reportcmd)# 生成allure测试报告并截图driver = webdriver.Chrome()report_url = "http://192.168.55.183:{}/index.html".format(port)  # 192.168.55.183 为电脑ip地址,{}为端口号print("测试报告链接:{}".format(report_url))driver.get(report_url)driver.maximize_window()  # 将浏览器最大化显示sleep(0.5)driver.get_screenshot_as_file('../report/reportOverview-{}.png'.format(port))  # 测试报告首页截图sleep(1)driver.find_element(By.XPATH, '//*[@id="content"]/div/div[1]/div/ul/li[6]/a/div').click()  # 测试报告详情页sleep(0.5)driver.find_element(By.XPATH,'//*[@id="content"]/div/div[2]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]').click()  # 展开测试报告详情sleep(1)driver.get_screenshot_as_file('../report/reportPackages-{}.png'.format(port))  # 测试报告详情截图

QA:关于搭建appium环境遇到的问题及解决办法

Windows端:

Q1.全局安装时提示权限问题
chown -R 当前用户名 /usr/local/lib/node_modules

Q2.以下5步解决 opencv4nodejs cannot be found
先装c-make,再安装opencv4nodejs
安装cmake并配置环境变量https://cmake.org/
安装git并配置环境变量
安装 opencv4nodejs失败的话,可先将镜像设置为淘宝,再执行安装 opencv4nodejs命令
1.设置镜像源
npm config set registry http://registry.npm.taobao.org
2.运行命令
npm i -g npm@6
npm i opencv4nodejs --save
npm i -g npm@latest
3.增大git的缓存
git config --global http.postBuffer 524288000
4.运行命令
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
5.再运行命令
npm i -g opencv4nodejs

Q3.ffmpeg 安装
下载ffmpeg 包,https://ffmpeg.zeranoe.com
解压后,将D:\ffmpeg\bin加入环境变量(我的是D盘,根据自己情况写“\ffmpeg\bin”的完整路径)

Q4.解决 bundletool.jar cannot be found
1.下载bundletool.jar:https://github.com/google/bundletool/releases
(授予bundletool.jar访问权限)
2.放在D:\AndroidSDK\bundle-tools下,并重命名为bundletool.jar
将bundletool.jar路径加入环境变量path
3.将.JAR加入PATHEXT

Q5.解决 mjpeg-consumer cannot be found
安装:npm i -g mjpeg-consumer

Q6.解决gst-launch-1.0.exe and/or gst-inspect-1.0.exe cannot be found
1.手动下载安装,下载地址:https://gstreamer.freedesktop.org/download/
注意:runtime installer 和 development installer 两个应用程序都要下载并安装。
2.安装完成后找到gstreamer路径(安装过程中不能选择安装路径,默认会安装到安装包所在的盘),配置Path系统环境变量:如:E:\gstreamer\1.0\mingw_x86_64\bin(安装路径的bin目录)

Mac端常见报错

Q1.安装opencv4nodejs
1.找个地方新建一个文件夹 nodeOpencv ,打开终端cd进入这个文件夹。
2.⚠️重要⚠️,输入如下命令后回车。
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
3.接着输入如下后等待5、6、7、8分钟左右即可完成 。
cnpm install --save opencv4nodejs

Q2.解决 idb and idb_companion are not installed
brew install facebook/fb/idb-companion
有些库下载失败,就逐个库执行:brew install xx库

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

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

相关文章

java进阶||jdk进阶之循环

从18年学java到现在除了各种各样的数据类型和集合烧不了要遍历这些变量, for循环这时就少不了啦(当然还有8后引入的神器泛型) 先来看一段精髓业务代码, 使用了多个新特性当然也少不了循环和分支判断 代码较长解析在后面 private CommonPage<List<Object>> handle…

【MyBatis】动态SQL

文章目录 前言增加操作\<trim>标签查询操作\<where>标签修改操作\<set>标签删除操作\<foreach>标签\<include>标签 前言 动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架&#xff0c;你应该能理解根据不同条件拼接 SQ…

超声波清洗机可以洗些什么东西?质量比较好的超声波清洗机推荐

超声波清洗机只能清洗眼镜吗&#xff1f;不是的&#xff01;超声波清洗机能够清洗的物品远比我们想象的还多&#xff0c;最常见的还是清洗眼镜&#xff0c;毕竟超声波清洗机最常见就是在眼镜店了&#xff0c;很多朋友都喜欢定期都眼镜店里来清洗一下眼镜&#xff0c;这个习惯其…

vivado Revision Control

2020.2 只需要git 管理 prj.xpr 和 prj.srcs/ https://china.xilinx.com/video/hardware/ip-revision-control.html Using Vivado Design Suite with Revision Control https://www.xilinx.com/video/hardware/vivado-design-suite-revision-control.html http://www.xi…

腾讯实验平台基于 StarRocks 构建湖仓底座

作者&#xff1a; 腾讯大数据平台部科学实验中心Tech Lead、专家工程师 马金勇博士 腾讯大数据平台部科学实验中心数据负责人、专家工程师 胡明杰 StarRocks Contributor、腾讯高级工程师 刘志行 在 2022 年&#xff0c;腾讯 A/B Test 团队启动了海外商业化版本 ABetterChoice …

企业网络两层和三层架构部署有何差异

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 厦门微思网络​​​​​​ https://www.xmws.cn华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle OC…

html的全选反选

一、实验题目 html实现选择框的全选和反选 二、实验代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>全选和反选</title></head><body><ul>兴趣爱好</ul><input id"all"…

【AI】 AIOTSummary

智能物联网(AIoT)是2018年兴起的概念,指系统通过各种信息传感器实时采集 各类信息(一般是在监控、互动、连接情境下的),在终端设备、边缘域或云中心 通过机器学习对数据进行智能化分析,包括定位、比对、预测、调度等。智能物联网(AIoT)是2018年兴起的概念,指系统通过…

微软等开源评估ChatGPT、Phi、Llma等,统一测试平台

微软亚洲研究院、中国科学院自动化研究所、中国科学技术大学和卡内基梅隆大学联合开源了&#xff0c;用于评估、分析大语言模型的统一测试平台——PromptBench。 Prompt Bench支持目前主流的开源、闭源大语言模型&#xff0c;例如&#xff0c;ChatGPT、GPT-4、Phi、Llma1/2、G…

基于虚拟机安装centos且远程连接

基于虚拟机安装centos且远程连接 1、安装虚拟机 目前市面上的虚拟机种类有很多&#xff0c;我们可以选择自己熟悉的虚拟机进行安装&#xff0c;我在这里用的虚拟机是VMware。具体的安装过程很简单&#xff0c;一直点击下一步就可以了。因为VMware虚拟机需要激活&#xff0c;所…

AI语音识别模块--whisper模块

1.下载 ffmpeg&#xff0c;挑一个自己电脑系统的版本&#xff0c;下载&#xff0c;如我win64&#xff1a; 地址&#xff1a; Releases BtbN/FFmpeg-Builds GitHub 下载压缩包zip&#xff0c;到本地 解压安装&#xff0c;其实无需安装&#xff0c;只需把对应的目录下的bin&…

【Matlab】在Matlab中安装优化工具yalmip的方法

最近博主想做一些关于多目标优化的问题&#xff0c;因为之前对Matlab有一定经验&#xff0c;所以直接在网上查找了如何在Matlab上实现多目标优化的文献&#xff0c;看到有人提到了yamip&#xff0c;于是博主就试着在Matlab中安装yamip&#xff0c;将其中遇到的问题和一些经验和…

缓存学习实战篇

缓存练习题&#xff08;用户查询操作&#xff09; public List<ShopType> queryAllType() throws JsonProcessingException {//从缓存中查数据String shopTypeJson stringRedisTemplate.opsForValue().get("cache:shopType");//如果缓存命中&#xff0c;if (S…

申请ZeroSSL泛域名域名证书 并部署阿里云测试

安装acme.sh 安装过程中可能会失败 多试几次就会成功 wget -O - https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m 你的邮箱gmail.com安装完成后重新加载 Bash&#xff1a; source ~/.bashrc然后也可以开启自动更…

客户端请求服务器的步骤

当我们在浏览器地址栏输入’http://www.xxx.com/api/xxx"时&#xff0c;客户端是如何找到服务器并发送请求的&#xff1f; 1.先找到服务器 a.检测浏览器缓存有没有缓存该域名对应的IP地址&#xff0c;有则通过IP地址取找服务器。 b.检测本地的hosts文件&#xff0c;是否有…

FPGA 高端项目:基于 SGMII 接口的 UDP 协议栈,提供2套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的以太网方案本协议栈的 1G-UDP版本本协议栈的 10G-UDP版本本协议栈的 25G-UDP版本1G 千兆网 TCP-->服务器 方案1G 千兆网 TCP-->客户端 方案10G 万兆网 TCP-->服务器客户端 方案 3、该UDP协议栈性能4、详细设计方案设…

NX二次开发PK获取对象类型

PK_ENTITY_ask_class(),获取对象类型建议用这个函数&#xff0c;比较通用&#xff0c;包含所有对象类型&#xff0c;可以替代UF_MODL_ask_edge_type(),UF_MODL_ask_body_type(),UF_MODL_ask_face_type()等函数 PK_ENTITY_t entity; PK_CLASS_t PK_TYPE; PK_ENTITY_ask_class(e…

openAI API key不需要中转,自己就可以使用正版

很多小伙伴因为不知道怎么使用原版&#xff0c;用的都是国内套壳的&#xff0c;国内套壳的有些价格不合适&#xff0c;如何是3.5的话只需要绑定虚拟信用卡就可以使用 想使用openai API key4.0的话你需要先开通ChatGPTplus&#xff0c;在绑定openai API key&#xff0c;绑定ope…

Spring事务失效场景之类内部方法调用及解决方案

一、背景 在日常开发中&#xff0c;经常有需要使用事务来保证数据一致性的情况。简单点的话直接在方法上面加Transactional注解就可以了。 但这样存在一个问题&#xff0c;在整个业务方法层面加注解会把很多并不需要归入事务的操作也归入到了事务里面&#xff0c;这样会可能会…

算法第十七天-构造有效字符串的最少插入数

构造有效字符串的最少插入数 题目要求 解题思路 考虑abc的个数 假设答案有n个"abc"组成&#xff0c;那么需要插入的字符个数为 3 ∗ n − l e n ( s ) 3*n - len(s) 3∗n−len(s)。 对于相邻的两个字符x和y&#xff08;x在y左侧&#xff09;&#xff1a; 如果 x…