pytest +uiautomator2+weditor app自动化从零开始

目录结构1.0
在这里插入图片描述
把设备连接单独移出去了
在这里插入图片描述
模块操作代码,有一些流程操作和断言方法

from devices import dv
from time import sleep
import random
from tool.jt import capture_screenshotdef initialization(func):def wrapper():sleep(1)dv.app_stop('com.visteon.txzing.accountcenter')dv.app_start('com.visteon.txzing.accountcenter')sleep(2)func()return wrapper@initialization
def f1():'''1、打开账号切换,点击其他的账号,点击确认登录,点击取消'''dv(text='账号切换').click()dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()dv(text='确定').click()dv(text='取消').click()@initialization
def f2():'''2、点击设置、点击退出登录、点击取消'''dv(text='设置').click()dv(text='退出登录').click()dv(text='取消').click()@initialization
def f3():'''3、点击设置、点击用户协议,点击返回,点击隐私政策,点击返回,再次点击返回到个人中心主页面'''dv(text='设置').click()dv(text='用户协议').click()sleep(1.5)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()dv(text='隐私政策').click()sleep(1.5)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()sleep(1.5)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()@initialization
def f4():'''4、点击账号关联,点击高德地图绑定,点击确定'''dv(text='账号关联').click()try:dv.xpath('//*[@content-desc="绑定高德地图"]').click()except:dv.xpath('//*[@content-desc="绑定高德地图"]').click()dv(text='确定').click()def f5():'''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''dv(text='问题反馈').click()dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(4)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(1)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()for i in ['多媒体', '导航', '蓝牙电话', '维保类', '设置', '其他']:dv(text=i).click()sleep(1)# 录音秒数随机sleep(random.randint(1, 80))dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()dv(text='提交').click()sleep(2)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.view.ViewGroup[1]').click()def run():while True:try:f1()f2()f3()f5()f4()except Exception as e:capture_screenshot(e)print(f'报错了重新运行{e}')# 通过获取文本来断言
b = '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.widget.TextView[1]'
a = dv.xpath(b).get_text()
print(a)# 通过判断元素是否存在来断言
c = dv.xpath('//*[@text="2023/11/30 15:49"]').exists
print(c)# 通过元素属性是否发生变化来进行断言
d = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]')
# 获取语音条初始状态的info信息
initial_info = d.info
d.click()
clicked_info = d.info
# 比较前后的info信息,找出差异数据
diff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}
print("前后的差异数据:", diff)
if len(diff) == 0:print('状态未发生变化')
else:print('断言成功')if __name__ == '__main__':while True:run()

目录结构1.1
新增test_accountcenter.py编写测试用例
新增run.py执行pytest
新增pytest.ini配置文件
在这里插入图片描述
test_accountcenter.py
删除了3个场景,留下2个场景,每个场景加了2种断言方式f1(ex):f5(ex):,测试用例是test_zhanghao():test_luyin():,f1(ex):f5(ex):内部实现了断言并且返回结果

from devices import dv
from time import sleep
import random
from tool.jt import capture_screenshot
def f1(ex):'''1、打开账号切换,点击其他的账号,点击确认登录,点击取消'''dv.app_stop('com.visteon.txzing.accountcenter')dv.app_start('com.visteon.txzing.accountcenter')dv(text='账号切换').click()dv.xpath('//*[@resource-id="com.visteon.txzing.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()dv(text='确定').click()text= dv(text='请在互联小程序确认登录').get_text()if not dv.xpath('//*[@resource-id="com.visteon.txzing.accountcenter:id/loading_cancel"]').exists:return Falseass =ex==textreturn assdef f5(ex):'''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''dv.app_stop('com.visteon.txzing.accountcenter')dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')dv(text='问题反馈').click()dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(4)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(1)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()lb=['多媒体', '导航', '蓝牙电话', '维保类', '其他', '设置']for i in lb:dv(text=i).click()sleep(1)# 录音秒数随机sleep(random.randint(5, 10))dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()dv(text='提交').click()ass= '设置'==ex'''元素信息变化'''d = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]')# 获取语音条初始状态的info信息initial_info = d.infod.click()clicked_info = d.info# 比较前后的info信息,找出差异数据diff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}print("前后的差异数据:", diff)if len(diff) == 0:return Falsesleep(2)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.view.ViewGroup[1]').click()return assdef test_zhanghao():f1('请在互联小程序确认登录')assert Truedef test_luyin():assert f5('设置')run.py文件
运行文件,暂未配置参数
```python
import pytest
pytest.main([])

pytest.ini文件
配置了下报告的一些参数

[pytest]
addopts = -s --alluredir ./report/data

目录结构1.2
新增断言方法文件
在这里插入图片描述
assertion.py文件
首先dw()判断元素是否存在,不存在不需要进行后续操作,element_existence方法适用于断言元素是否存在,element_info_existence方式适用于判断元素在点击后是否发生了属性变化来断言,element_text_existence适用于判断元素文本和预期结果是否一致

from time import sleep
def dw(dv, element, positioning_method):''':param dv: 设备:param element: 定位元素:param positioning_method: 定位方式:return: 判定元素是否存在,存在则返回元素对象用于后续操作'''if positioning_method == 'xpath':if not dv.xpath(element).exists:print('断言元素不存在,直接判定断言失败')return Falsereturn dv.xpath(element)if positioning_method == 'text':if not dv(text=element).exists:print('断言元素不存在,直接判定断言失败')return Falsereturn dv(text=element)def element_existence(dv, element, positioning_method):''':param dv: 设备:param element: 定位元素:param positioning_method: 定位方式:return:通过元素是否存在来断言'''element_ = dw(dv, element, positioning_method)if not element_:return Falsereturn Truedef element_info_existence(dv, element, positioning_method):''':param dv: 设备:param element: 定位元素:param positioning_method: 定位方式:return:通过元素属性是否发生变化来断言'''if not dw(dv, element, positioning_method):return Falseelse:el = dw(dv, element, positioning_method)initial_info = el.infoel.click()sleep(1)clicked_info = el.infodiff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}print(f'元素差异字段{diff}')if len(diff) == 0:print('元素属性未发生变化,断言失败')return Falsereturn Truedef element_text_existence(dv, element, positioning_method, text):''':param dv: 设备:param element: 定位元素:param positioning_method: 定位方式:param text: 预期结果文本:return: 通过文本是否相等来断言'''if not dw(dv, element, positioning_method):return Falseelse:el = dw(dv, element, positioning_method)el_text=el.get_text()if not text ==el_text :print(f'文本不匹配预期结果{text},实际结果{el_text}')return Falseelse:return True

目录结构1.3
新增case文件夹
case-fun 以每个模块一个文件,里面包含多个场景操作,和场景断言
case-test_case 以每个模块一个文件,和fun文件夹文件一一对应,负责执行模块的每个场景
在这里插入图片描述
accountcenter.py文件

import random
from time import sleep
from tool.assertion import element_existence, element_info_existence, element_text_existencedef f1(dv):'''1、打开账号切换,点击其他的账号,点击确认登录'''dv.app_stop('com.visteon.txzing.accountcenter')dv.app_start('com.visteon.txzing.accountcenter')dv(text='账号切换').click()dv.xpath('//*[@resource-id="com.visteon.txzing.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()dv(text='确定').click()'''断言'''return element_existence(dv, '取消', 'text')def f2(dv):dv.app_stop('com.xxxxxxx.xxxxxxx.accountcenter')dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')'''2、点击设置、点击退出登录、点击取消'''dv(text='设置').click()dv(text='退出登录').click()dv(text='取消').click()return element_text_existence(dv, '退出登录', 'text', '退出登录')def f5(dv):'''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''dv.app_stop('com.xxxxxxx.xxxxxxx.accountcenter')dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')dv(text='问题反馈').click()dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(2)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()sleep(1)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()lb = ['多媒体', '导航', '蓝牙电话', '维保类', '其他', '设置']for i in lb:dv(text=i).click()sleep(1)# 录音秒数随机sleep(random.randint(5, 10))dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()dv(text='提交').click()sleep(2)dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]').click()  # 点击语音条'''断言'''return element_info_existence(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]','xpath')

test_accountcenter.py文件

from case.fun.accountcenter import f1, f2, f5
from devices import dv
def test_f1():assert f1(dv)
def test_f2():assert f2(dv)
def test_f5():assert f5(dv)

familytime.py

import random
from time import sleep
from devices import dv
from tool.assertion import element_existence, element_info_existence, element_text_existence'''这些是通过观察元素属性观察得出的结论,这些是通用值'''def tu(number):'''家人时光每个图片定位'''tu = dv.xpath(f'//*[@resource-id="com.visteon.txzing.familytime:id/recycler_view"]/android.view.ViewGroup[{number}]/android.widget.ImageView[1]')return tu# 设为按钮
set_as = dv(text='设为')
# 设置壁纸
set_wallpaper = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_wallpaper"]')
# 设置屏保
set_screensaver = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_screensaver"]')
# 设为按钮
confirm = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_allow"]')
# 取消按钮
cancel = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_cancel"]')def set_s_w():dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')dv.app_start('com.xxxxxxx.xxxxxxx.familytime')tu(1).click()set_as.click()set_wallpaper.click()set_screensaver.click()confirm.click()# 多个断言处理ass_1 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath','壁纸、屏保设置成功')ass_2 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_label"]', 'xpath','壁纸 屏保')ass_list = [ass_1, ass_2]for i in ass_list:if not i:print(f'断言{i}失败')return Falsereturn Truedef cancel_s_w():dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')dv.app_start('com.xxxxxxx.xxxxxxx.familytime')tu(1).click()set_as.click()set_wallpaper.click()set_screensaver.click()confirm.click()return element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath','壁纸、屏保取消成功')

test_familytime.py

from case.fun.familytime import set_s_w, cancel_s_w
from devices import dv
from time import sleep
def test_set_s_w():set_s_w()
def test_cancel_s_w():cancel_s_w()

目录结构1.4
新增dw.py文件,增加元素定位封装,定位失败截图
新增conftest.py,配合pytest.fixture实现前后置
在这里插入图片描述
dw.py

from time import sleep
from lxml import etree
from tool.screenshot import capture_screenshot
class DwFail(Exception):pass
def jt(case_name, positioning_instructions):print('定位元素不存在,进行截图')info = f'用例标题{case_name},定位元素说明:{positioning_instructions}'capture_screenshot(info)
def find_elements(dv, element, positioning_method, case_name, positioning_instructions):''':param dv: 设备对象:param element:元素定位数据:param positioning_method:元素定位方式:param case_name:测试用例名称:param positioning_instructions: 这个元素测试的对象说明:return:'''sleep(1.5)if positioning_method == 'xpath':try:if dv.xpath(element).exists:print('定位成功')return dv.xpath(element)else:jt(case_name, positioning_instructions)raise DwFail(f'定位失败,用例标题{case_name},定位元素说明:{positioning_instructions}')except etree.XPathEvalError:jt(case_name, positioning_instructions)raise DwFail(f'xpath路径错误定位,用例标题{case_name},定位元素说明:{positioning_instructions}')elif positioning_method == 'text':if dv(text=element).exists:return dv(text=element)else:jt(case_name, positioning_instructions)raise DwFail(f'定位失败,用例标题{case_name},定位元素说明:{positioning_instructions}')else:print('暂时只支持xpath,text定位')if __name__ == '__main__':from devices import dv# find_elements(dv, '.ViewGroup[2]', 'xpath', 'xpath', '点击设12222211111111置')find_elements(dv, '//*[@resource-id="com.visteon.txzing.accountcenter:id/feedback_record_bar_time', 'xpath','进行录音问题反馈', '点击语音条').click()# find_elements(dv, '//*[@resource-id="com.visteon.txzing.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.view.ViewGroup[1]', 'xpath',#               '进行录音问题反馈', '点击语音条').click()

dw.py文件find_elements方法应用

import random
from time import sleep
from devices import dv
from tool.assertion import element_existence, element_info_existence, element_text_existence
from tool.dw import find_elements'''这些是通过观察元素属性观察得出的结论,这些是通用值'''
def tu(number):'''家人时光每个图片定位'''tu = dv.xpath(f'//*[@resource-id="com.visteon.txzing.familytime:id/recycler_view"]/android.view.ViewGroup[{number}]/android.widget.ImageView[1]')return tu# 设为按钮
set_as = dv(text='设为')
# 设置壁纸
set_wallpaper = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_wallpaper"]')
# 设置屏保
set_screensaver = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_screensaver"]')
# 设为按钮
confirm = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_allow"]')
# 取消按钮
cancel = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_cancel"]')
def set_s_w():dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')dv.app_start('com.xxxxxxx.xxxxxxx.familytime')find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/recycler_view"]/android.view.ViewGroup[1]/android.widget.ImageView[1]','xpath', '照片设置为屏保壁纸', '点击照片进入详情').click()find_elements(dv, '设为','text', '照片设置为屏保壁纸', '点击设为按钮').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_wallpaper"]','xpath', '照片设置为屏保壁纸', '勾选壁纸').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_screensaver"]','xpath', '照片设置为屏保壁纸', '勾选屏保').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_allow"]','xpath', '照片设置为屏保壁纸', '进行设置').click()# 多个断言处理ass_1 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath','壁纸、屏保设置成功','照片设置为屏保壁纸断言1')ass_2 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_label"]', 'xpath','壁纸 屏保','照片设置为屏保壁纸断言2')ass_list = [ass_1, ass_2]for i in ass_list:if not i:print(f'断言{i}失败')return Falsereturn Truedef cancel_s_w():dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')dv.app_start('com.xxxxxxx.xxxxxxx.familytime')find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/recycler_view"]/android.view.ViewGroup[1]/android.widget.ImageView[1]','xpath', '照片取消为屏保壁纸', '点击照片进入详情').click()find_elements(dv, '设为', 'text', '照片取消为屏保壁纸', '点击设为按钮').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_wallpaper"]','xpath', '照片取消为屏保壁纸', '取消勾选壁纸').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_screensaver"]','xpath', '照片取消为屏保壁纸', '取消勾选屏保').click()find_elements(dv,'//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_allow"]','xpath', '照片取消为屏保壁纸', '进行设置').click()return element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath','壁纸、屏保取消成功','照片取消为屏保壁纸')

conftest.py文件

import pytest
from uiautomator2 import UiObjectNotFoundError
from tool.screenshot import capture_screenshot
@pytest.fixture(scope='function',autouse=True)
#autouse=True这将使该 fixture 在每个测试用例中自动执行,而无需显式地添加装饰器或参数
def zx(request):print('开始')print(f'用例信息{request}')yieldprint('结束')# def pytest_runtest_protocol(item, nextitem):
#     reports = yield
#     for report in reports:
#         if report.when == "call" and report.failed:
#             # 检查是否是 UiObjectNotFoundError 异常
#             if isinstance(report.longrepr, UiObjectNotFoundError):
#                 # 获取异常信息
#                 err_info = str(report.longrepr)
#
#                 # 调用截图方法
#                 capture_screenshot(err_info)

截图效果
在这里插入图片描述

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

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

相关文章

CSS特效025:旋转的loading状态

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧,主要包含CSS布局,CSS特效,CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点,CSS特效主要是一些动画示例,CSS花边是描述了一些CSS…

Linux学习笔记(九)MISC设备驱动

前言 misc 的意思是混合、杂项的,因此 MISC 驱动也叫做杂项驱动。也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。 MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 platform 总线驱动中,实现复杂的驱动&#xff0…

Mysql 索引概念回顾

一、什么是索引 在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据…

《算法竞赛进阶指南》------图论篇

文章目录 0x01 Telephone Lines POJ - 36620x02 P1073 [NOIP2009 提高组] 最优贸易0x03 道路和航线 BZOJ22000x04 Sorting It All Out POJ - 1094 topo0x05 Sightseeing trip POJ - 1734 最小环问题0x06 Cow Relays POJ - 3613 S到E经过k条边的最短路0x07 走廊泼水节 &#xff…

为什么Java程序员需要掌握多线程?揭秘并发编程的奥秘

为什么Java程序员需要掌握多线程?揭秘并发编程的奥秘 个人简介前言多线程对于Java的意义📌1.提高程序性能:📌2 提高用户体验:📌3支持并发处理:📌4 资源共享和同步:&#…

C# 语法笔记

1.ref、out:参数传递的两种方式 ref:引用传递 using System; namespace CalculatorApplication {class NumberManipulator{public void swap(ref int x, ref int y){int temp;temp x; /* 保存 x 的值 */x y; /* 把 y 赋值给 x */y temp; /* 把 t…

Python中的range()函数详解:掌握迭代的利器

更多资料获取 📚 个人网站:ipengtao.com Python中的range()函数是一个强大的工具,用于生成一系列的数字,常用于循环操作。虽然看似简单,但其灵活性和功能却不容小觑。在本文中,将深入研究range()函数&…

docker容器_自定义上传jenkins镜像(Dockerfile实现)

1.创建jenkins目录,并上传相应的包 mkdir /jenkins/ 2.创建一个Dockerfile文件 FROM daocloud.io/library/centos:7#把当前目录下的jenkins.war包传到内部容器的/ 下 ADD ./jenkins.war /#把当前目录下的jdk传到内部容器的/opt/,并解压 ADD ./jdk-11.0.19_linu…

网络编程基础api

1. IP 协议 1.1 IP 分片 (1)IP 分片和重组主要依靠 IP 头部三个字段:数据报标识、标志和片偏移 以太网帧的 MTU 是 1500 字节; 一个每个分片都有自己的 IP 头部,它们都具有相同的标识值,有不同的片偏移…

css 十字分割线(含四等分布局)

核心技术 伪类选择器含义li:nth-child(2)第2个 lili:nth-child(n)所有的lili:nth-child(2n)所有的第偶数个 lili:nth-child(2n1)所有的第奇数个 lili:nth-child(-n5)前5个 lili:nth-last-child(-n5)最后5个 lili:nth-child(7n)选中7的倍数 border-right: 3px solid white;borde…

EasyExcel-最简单的读写excel工具类

前言&#xff1a; easyExcel 的官网文档给的示例非常全&#xff0c;可以参考https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read 在此我贴出自己的工具类&#xff0c;可以直接用 导包 <dependency><groupId>com.alibaba</groupId><…

机器学习第15天:GBDT模型

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 ​​ 文章目录 GBDT模型介绍 Boosting 残差 GBDT的缺点 python代码实现 代码 模型参数解释 结语 GBDT模型介绍 GBDT&#xff08;Gradient Boos…

php+mysql期末作业小项目

目录 1、登录界面 2、注册界面 3、主界面 4、学生表界面 5 、查询学生界面​编辑 6、修改学生信息界面​编辑 7、删除学生信息界面 8、添加学生信息界面 9、后台数据库​编辑 一个简单的php➕mysql项目学生信息管理系统&#xff0c;用于广大学子完成期末作业的参考&…

测试架构工程师需要具备哪些能力 ?

前言 相比于我们常见的研发架构师&#xff0c;测试架构师是近几年才出现的一个岗位&#xff0c;当然岗位title其实没有特殊的含义&#xff0c;在我看来测试架构师其实更像对某一类人的抽象称呼和对其复合能力的期待及认可。 在聊这篇文章的主题之前&#xff0c;先来看这样一个…

TCP通信

第二十一章 网络通信 本章节主要讲解的是TCP和UDP两种通信方式它们都有着自己的优点和缺点 这两种通讯方式不通的地方就是TCP是一对一通信 UDP是一对多的通信方式 接下来会一一讲解 TCP通信 TCP通信方式呢 主要的通讯方式是一对一的通讯方式&#xff0c;也有着优点和缺点…

如何在Android平板上远程连接Ubuntu服务器使用code-server代码开发

目录 1.ubuntu本地安装code-server 2. 安装cpolar内网穿透 3. 创建隧道映射本地端口 4. 安卓平板测试访问 5.固定域名公网地址 6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以&#xff0c;这里以VMwhere ubuntu系统为例 下载code server服务…

el-table 表格多选(后端接口搜索分页)实现已选中的记忆功能。实现表格数据和已选数据(前端分页)动态同步更新。

实现效果&#xff1a;&#xff08;可拉代码下来看&#xff1a;vue-demo: vueDemo&#xff09; 左侧表格为点击查询调用接口查询出来的数据&#xff0c;右侧表格为左侧表格所有选择的数据&#xff0c;由前端实现分页。 两个el-table勾选数据联动更新 实现逻辑&#xff1a; el-…

低代码开发到底是补品还是垃圾食品?

2023&#xff0c;低代码彻底火了&#xff0c;甚至火到没有点相关经验&#xff0c;都不好意思出去面试的程度。 从业者对低代码的发展充满了想象&#xff0c;都认为未来低代码的商业价值不可估量。 据Gartner的最新报告显示&#xff0c;2023年全球低代码开发技术市场规模预计将…

内部文件上传以及渲染-接口API

文件上传 地址http://172.16.0.118:8090/api/pm/base/affix/upload请求类型POSTContent-Type:text/plain;charsetutf-8参数 prjData {"prjId":"", "jobId":"3031b2c8-c809-4110-8e88-22c80a9c1ec0721aca89-96a1-4346-9b6e-022331d221d1Nec…

【EMNLP 2023】面向Stable Diffusion的自动Prompt工程算法BeautifulPrompt

近日&#xff0c;阿里云人工智能平台PAI与华南理工大学朱金辉教授团队合作在自然语言处理顶级会议EMNLP2023上发表了BeautifulPrompt的深度生成模型&#xff0c;可以从简单的图片描述中生成高质量的提示词&#xff0c;从而使文生图模型能够生成更美观的图像。BeautifulPrompt通…