WinApp自动化测试之辅助工具介绍

前篇文章中,我们简单介绍了部分WinApp自动化测试脚本常规操作,今天我们来讲剩余的部分。

文件批量上传

文件批量上传和文件单个上传原理是相同的,单个上传直接传入文件路径即可,批量上传需要进入批量上传的文件所在目录,然后观察选中多个文件时【文件路径输入框】读取的批量文件写入规则,如图7-12所示,可以看到规则是:“file_name” “file_name”。

我们只需要根据规则将批量文件组合成字符串输入到【文件路径输入框】中,然后点击【插入】即可完成批量上传。

图片

图 7-12 文件批量写入文件路径输入框

例如打开Word程序,新建一个空白文档,然后依次点击图片>>此设备…,打开插入图片对话框,并在【文件路径输入框】中输入批量上传的文件,最后点击【插入】将多个图片插入到word文档中。代码实现如下:

# upload_files.py
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keysdef upload_files(driver, file_path, files: list):# 定位文件路径输入框file_input = WebDriverWait(driver, 60, 0.5).until(EC.visibility_of_element_located((By.XPATH, "//Edit[@Name='文件名(N):']")))# 输入框输入 Shift,由中文切换到英文file_input.send_keys(Keys.SHIFT)# 先输入批量文件所在的目录,进入该目录下file_input.send_keys(file_path + Keys.ENTER)# 生成多个文件上传时的字符串mult_file_str = ''for file in files:mult_file_str += " \"" + file + "\""# 文件上传file_input.send_keys(mult_file_str)file_insert_btn = WebDriverWait(driver, 60, 0.5).until(EC.visibility_of_element_located((By.NAME, "插入(S)")))file_insert_btn.click()# 添加启动参数
desired_caps = {}
desired_caps['app'] = r"C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE"
# 客户端连接 Server,启动 Session 会话
driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)
driver.set_window_size(1000, 600)
time.sleep(1)
# 新建空白文档
driver.find_element(by=By.NAME, value="空白文档").click()
time.sleep(1)
# 依次点击 插入 >> 图片 >> 此设备...,打开文件上传窗口
driver.find_element(by=By.NAME, value="插入").click()
driver.find_element(by=By.NAME, value="图片").click()
driver.find_element(by=By.NAME, value="此设备...").click()# 文件上传
upload_files(driver, r"D:", ['ty.png', 'ty2.png'])# 关闭程序和会话
driver.close()
driver.find_element(by=By.NAME, value="不保存").click()
driver.quit()

运行上面脚本,可以观察到先启动Word程序,然后点击【空白文档】新建了一个文档,再然后依次点击图片>>此设备…打开了上传文件窗口,上传文件窗口中先是在【文件路径输入框】中输入了"D:“进入到了D盘根目录,接着就在【文件路径输入框】中输入了"ty.png” “ty2.png”,并点击了【插入】按钮,此时可以看到Word文档中已经成功插入了两张图片,如图7-13所示,关闭写字板程序,会话关闭。

图片

图 7-13 文件批量上传

获取通知栏信息

Windows系统屏幕右下角(任务栏最右侧)的区域被称为通知区域,通知区域最后一个图标为通知栏图标,点击可打开通知栏,通知栏中可以查看所有被允许的通知信息。Windows也提供了快捷键迅速开启通知栏,例如Win10系统上快捷键就是Win+a。

通知信息如Windows系统更新、截图、安全通知、备份。例如关闭防火墙后通知栏会出现如图7-14所示的消息。

图片

图 7-14 关闭防火墙通知

自动化脚本实现获取通知栏信息的操作步骤是设置appTopLevelWindow为Root,定位桌面任意元素并发送快捷键打开通知栏,然后定位通知信息元素,获取到通知元素后便可使用text接口得到文本内容。示例代码如下:

# get_notification_message.py
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keysdesired_caps = {}
desired_caps['app'] = "Root"
driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)
time.sleep(1)# 通过快捷键打开 通知栏
driver.find_element(by=By.NAME, value="任务栏").send_keys(Keys.COMMAND + 'a' + Keys.COMMAND)
time.sleep(1)# 定位【来自 Windows 安全中心 的通知】通知元素
notification_element = driver.find_element(by=By.NAME, value="来自 Windows 安全中心 的通知")
# 获取【来自 Windows 安全中心 的通知】下所有 Tag 为 Text 的元素文本,并且打印
text_elements = notification_element.find_elements(by=By.TAG_NAME, value="Text")
texts = [text_element.text for text_element in text_elements]
print(texts)# 通过快捷键关闭 通知栏
driver.find_element(by=By.NAME, value="任务栏").send_keys(Keys.COMMAND + 'a' + Keys.COMMAND)
# 关闭会话
driver.quit()

运行上面脚本后控制台输出内容如下:

['Windows 安全中心', '防火墙和网络保护', '启用 Windows 防火墙', 'Windows 防火墙已关闭。点击或单击以启用。', '22:17']

运行上面脚本后,可以观察到通知栏先开启然后关闭。

Windows系统上,不止通知栏,许多操作都支持快捷键,例如打开文件资源管理器(Win+e)、打开反馈中心(Win+f)、打开剪贴板(Win+v),我们都可以通过此方法对其操作。

滚动条操作

滚动条是常见的一个控件,当内容超过显示区域时便会出现滚动条,通过滑动滚动条可查看所有的内容。

WinAppDriver本身也实现了scroll(xoffset, yoffset)方法操作滚动条,使用方法为TouchActions(driver).scroll(0, 100).perform()。

除此之外,我们还可以接着键盘键PageUp和PageDown达到滑动滚动条的目的,下面通过发送键盘键滑动滚动条,选择写字板上的字体。打开字体选择下拉列表后,在循环体中重复接下来的操作,首先查找预期的字体元素,如果出现则点击字体元素,如果不出现则定位任意下拉列表框中的元素发送PageUp或PageDown键,如此循环,直到预期字体元素出现。代码实现如下:

# scrollbar_operation.py
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 添加启动参数
desired_caps = {}
desired_caps['app'] = r"C:\Program Files\Windows NT\Accessories\wordpad.exe"
driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)
driver.set_window_size(1000, 600)
time.sleep(1)# 字体选择
combox_btn = WebDriverWait(driver, 30, 1).until(EC.visibility_of_element_located((By.XPATH, "//ComboBox[@Name='字体系列']/Button")))
combox_btn.click()i = 0
while i < 100:try:el = WebDriverWait(driver, 1, 1).until(EC.visibility_of_element_located((By.XPATH, "//ListItem[@Name='幼圆']")))el.click()breakexcept:i += 1temp_element = WebDriverWait(driver, 1, 1).until(EC.visibility_of_element_located((By.XPATH, "//List[@Name='字体系列']")))temp_element.send_keys(Keys.PAGE_DOWN)time.sleep(1)
# 关闭程序和会话
driver.close()
driver.quit()

运行上面脚本,可以观察到打开字体选择下拉列表后,相隔一定的时间滚动条就下滑一定的距离,当查找的幼圆字体后,点击了幼圆字体,下来列表消失。

其他操作

运行在Windows系统上的应用程序,也有下拉框、单选、多选等控件,这些控件的操作与我们开发其它内容自动化脚本的思路是一致的。都是先熟悉手动操作步骤,然后封装成测试方法,使用时调用封装的方法即可。

例如写字板中选择字体下拉框。封装思路为:先定位打开下拉按钮并点击,使下拉列表显示出来,然后在下来列表中根据字体名查找字体元素,然后点击该字体元素。代码实现如下:

# combox_select.py
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECdef combox_select(combox: str, value):combox_btn = WebDriverWait(driver, 30, 1).until(EC.visibility_of_element_located((By.XPATH, f"//ComboBox[@Name='{combox}']/Button")))combox_btn.click()value_item = WebDriverWait(driver, 30, 1).until(EC.visibility_of_element_located((By.XPATH, f"//ListItem[@Name='{value}']")))value_item.click()# 添加启动参数
desired_caps = {}
desired_caps['app'] = r"C:\Program Files\Windows NT\Accessories\wordpad.exe"
driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)
time.sleep(1)# 字体选择
combox_select('字体系列', '黑体')time.sleep(1)
# 关闭程序和会话
driver.close()
driver.quit()

运行上面的脚本,会观察到启动写字板后首先打开了字体选择列表,然后点击黑体字体选择了字体,最后关闭写字板,结束会话。

注意:选择字体时要确保字体在下列列表的可视区域。

对于其他结构相同的下拉框,该方法也同样适用,例如字体大小选择20号字体,使用该方法时就可以写成combox_select(‘字体大小’, 20)。

辅助工具Pywin32

PythonWin32模块是一个非常受欢迎的模块,它提供了从Python访问许多Windows API的功能。自动化测试中使用它可以更方便地实现某些功能,例如窗口截图。PythonWin32模块作为一个成熟的模块。可以辅助自动化测试项目更好地开展,提高工作效率。

Pywin32简介

Pywin32模块是一个第三方模块库,提供了很多访问Windows系统的API,该项目是一个开源项目,在GitHub上可以看到项目源码(https://github.com/mhammond/pywin32)。

Pywin32的安装和Python的其它第三方库安装方式一样,在命令行工具中输入pip install pywin32即可完成安装。完成后在Python安装路径下~\Lib\site-packages\win32可以看到所有API支撑模块,如图7-15。

图片

图 7-15 pywin32所有API支撑模块

下面对部分模块做以介绍:

win32api:封装Windows Win32 API的模块。

win32console:Windows控制台函数的接口,用于处理字符模式应用程序。

win32event:提供win32事件/等待API接口的模块。

win32file:win32文件API的接口,包括Vista引入的事务性NTFS操作。

win32gui:提供本机win32 GUI API的接口。

win32net:封装Windows Network API的模块。

win32process:提供win32进程和线程API的接口。

win32security:提供win32安全API的接口。

win32service:提供Windows NT Service API的接口。

win32ui:封装Microsoft Foundation类的模块。

其中win32api、win32gui和win32ui是较为重要的三个模块,还有一个消息常量模块win32con。通过这些API,我们可以获取Windows窗口的相关信息,并做简单的操作。

从pywin32所有API支撑模块可以看出,Pywin32库非常强大,提供了丰富的windows系统上的API接口。但是在WinApp自动化中,作为一个辅助工具,我们只用到他的边角料功能就能满足我们的需求。本节将会介绍自动化中使用Pywin32更好地帮助我们完成测试。

常用方法

win32 提供的API非常丰富,下面介绍一些常用的方法:

win32gui.FindWindow(ClassName, Title):获取当前窗口句柄,句柄是窗口的唯一标识。参数ClassName是窗口的类名,Title是窗口标题。

win32gui. FindWindowEx(hld, Child, ClassName, Title):获取父窗口下第一个窗口类为ClassName控件的窗口。参数hld是目标窗口的父窗口,Child是目标窗口的子窗口,ClassName是目标窗口的类名,Title是目标窗口的标题。

win32api.GetCursorPos():获取当前窗口坐标,返回值是tuple类型,例如(721, 550)。

win32gui.GetWindowRect(handle):获取窗口边框矩形的左上角和右下角坐标,返回值是tuple类型,例如(-25600, -25600, -25441, -25573)。

win32gui.FindWindow(None, title):根据窗口名查找 Title窗口,返回值是窗口句柄。

win32gui.GetWindowText(handle):获取窗口标题。

win32gui.GetClassName(handle):获取窗口类名。

win32gui.BringWindowToTop(handle):将窗口放在最前面。

win32gui.SetForegroundWindow(handle):将窗口激活并放在最前面。

win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0):鼠标左键按下。

win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0):鼠标左键释放。

win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0):鼠标右键按下。

win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0):鼠标右键释放。

win32api.mouse_event(win32con.MOUSEEVENTF_WHEEL, 0, 0, -1):滑动界面,-1表示向下移动一个单位。

win32api.keybd_event(val, 0, 0, 0):按下键盘某个键。

win32api.keybd_event(val, 0, win32con.KEYEVENTF_KEYUP, 0):松开键盘的某个键。

获取所有窗口句柄

获取所有窗口句柄我们需要用到win32gui.EnumWindows(callBack,none) 方法,该方法是获取windows所有窗口,无论窗口是否激活。当找到一个窗口就会执行callback一次,传入 当前窗口句柄。将其封装成方法,代码如下:

 def get_all_windows():handle_list = []win32gui.EnumWindows(lambda handle, param: param.append(handle), handle_list)return handle_list# 打印所有窗口 handle
print(get_all_windows())
# 打印窗口 title
print([win32gui.GetWindowText(handle) for handle in get_all_windows()])

键盘按键输入

我们可以通过win32api.keybd_event(bVk, bScan, dwFlags, dwExtraInfo)方法实现键盘事件,因此可以利用它实现键盘按键输入。

keybd_event(bVk, bScan, dwFlags, dwExtraInfo)方法有四个参数,bVk是虚拟键码, bScan是硬件扫描码,一般设置为0即可,dwFlags是函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被释放,dwExtraInfo是定义与击键相关的附加的32位值,一般设置为0即可。封装方法如下:

def send_keyboard(*args):for arg in args:win32api.keybd_event(arg, 0, 0, 0)for arg in args:win32api.keybd_event(arg, 0, win32con.KEYEVENTF_KEYUP, 0)

例如 ctrl 键对应的键码是 17,A键对应的键码是65,那么使用封装的方法发送ctrl+A组合键就可写成send_keyboard([17, 65])。

键盘键码请查看附件Ⅰ 键码对照表。

窗口截图

窗口截图的思路是根据窗口句柄获取窗口 DC 和窗口的位置信息及宽和高,然后创建一个新的 DC,再使用新创建的 DC 创建一个兼容设备内容的 DC,最后创建 bitmap,根据 DC 获取图像信息,保存成图片文件。

DC在pywin32中是一个重要概念。windows不允许程序直接访问硬件,所有的操作都需要通过一个设备上下文环境。屏幕上的每个窗口都对应一个DC。DC相当于一个视频缓冲区,对这个缓冲区的操作,会表现在这个缓冲区对应的屏幕窗口上。除了窗口对应的DC外,还可以自己创建DC,然后在创建的DC上面建立数据拷贝到窗口的DC上,就相当于刷新窗口的DC。

示例:打开写字板程序,并对写字板当前窗口截图。根据窗口截图思路可实现截图函数 screenshots_windows。因此实现截图写字板窗口的代码如下:

# win32_screenshots.py
import timeimport win32gui, win32ui, win32con
from appium import webdriverdef screenshots_windows(windows_name):handle = win32gui.FindWindow(None, windows_name)   # 获取窗口句柄win32gui.SetForegroundWindow(handle)                # 将窗口放在前台,激活该窗口hdDC = win32gui.GetWindowDC(handle)                 # 获取窗口 DCnewhdDC = win32ui.CreateDCFromHandle(hdDC)         # 根据句柄创建一个DCsaveDC = newhdDC.CreateCompatibleDC()               # 创建一个兼容设备内存的 DCsaveBitmap = win32ui.CreateBitmap()                 # 创建 bitmap 保存图片# 获取窗口的位置信息left, top, right, bottom = win32gui.GetWindowRect(handle)width = right – leftheight = bottom – top# bitmap 初始化saveBitmap.CreateCompatibleBitmap(newhdDC, width, height)saveDC.SelectObject(saveBitmap)saveDC.BitBlt((0, 0), (width, height), newhdDC, (0, 0), win32con.SRCCOPY)saveBitmap.SaveBitmapFile(saveDC, windows_name + ".png")desired_caps = {}
desired_caps['app'] = r"C:\Program Files\Windows NT\Accessories\wordpad.exe"
driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)
time.sleep(3)
screenshots_windows("文档 - 写字板")
# 关闭会话
driver.quit()

注:此截屏函数screenshots_windows来自网络。

运行上面代码后,在当前目录下多了一个“文档 - 写字板.png”文件,内容如图7-16。

图片

图 7-16 pywin32截图

脚本录制

脚本录制是通过工具记录用户的操作,并将操作生成脚本,已达到回放的目的。WinAppDriver社区也推出了一个开源的工具WinAppDriver UI Recorder,该工具可以让用户轻松地创建自动化的UI测试。下面我们就来学习WinAppDriver UI Recorder的使用。

1.下载WinAppDriver UI Recorder项目,下载地址:https://github.com/Microsoft/WinAppDriver/tree/master/Tools。例如笔者直接下载的是ZIP包,下载并解压后会得到WinAppDriver-master一个文件夹。

2.安装Visual Studio 2017及其以上版本的VS工具,例如笔者安装的是VS 2022。

3.以管理员身份启动VS,并且打开WinAppDriver UI Recorder项目。启动VS后点击【打开项目或解决方案§】,选择~WinAppDriver-master\Tools\UIRecorder\WinAppDriverUIRecorder.sln文件,如图7-17。

图片

图 7-17 VS打开WinAppDriverUIRecorder项目

4.编译项目。在【解决方法资源管理器】下找到WinAppDriverUIRecorder,右键点击后在弹窗的菜单中选择【生成(U)】开始编译项目,如图7-18,如果没有控制台没有报错则编译成功。

如果【解决方法资源管理器】没有显示,可在视图菜单下点击使其显示。

图片

图 7-18 编译WinAppDriverUIRecorder

5.点击VS工具菜单中的【启动】图标:

图片

运行项目,项目启动成功后会打开一个【WAD UIRecorder】窗口,窗口结果如图7-19(图片来源WinAppDriver UI Recorder官方介绍文档https://blogs.windows.com/windowsdeveloper/2018/06/20/introducing-winappdriver-ui-recorder/)。

图片

7-19 WAD UIRecorder窗口

6.点击【Record】激活录制,然后在正文区域输入一个“s”,如图7-20。

图片

7-20 录制脚本

从WAD UIRecorder界面上面的面板中可以看到内容区域的xPath定位语法是:

"/Pane[@ClassName=\"#32769\"][@Name=\"桌面 1\"]/Window[@ClassName=\"WordPadClass\"][@Name=\"文档 - 写字板\"]/Document[@ClassName=\"RICHEDIT50W\"][@Name=\"多信息文本窗口\"]"

从下面的C# Code面板中可以看到操作生成的C#代码,代码如下:

// KeyboardInput VirtualKeys=""s"" CapsLock=False NumLock=True ScrollLock=False
Console.WriteLine("KeyboardInput VirtualKeys=\"\"s\"\" CapsLock=False NumLock=True ScrollLock=False");
System.Threading.Thread.Sleep(100);
winElem_LeftClickDocument多信息文本窗口_24_70.SendKeys("s");

使用WinAppDriver UI Recorder工具,用户可以通过更简单、更直观的方法来为WinAppDriver编写自动化脚本。

虽然生成的代码是C#,但是通过该工具可以帮助我们迅速生成测试脚本,对于一些难以用元素识别工具获得元素属性的元素,也可以快速得到定位语法,这也是UI Recorder初始版本最先支持的两个场景。

 

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

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

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

相关文章

uniapp创建支付密码实现(初始密码,第二次密码)

示例&#xff1a; 插件地址&#xff1a;自定义数字/身份证/密码输入框&#xff0c;键盘密码框可分离使 - DCloud 插件市场 1.下载插件并导入HBuilderX&#xff0c;找到文件夹&#xff0c;copy number-keyboard.vue一份为number-keyboard2.vue&#xff08;number-keyboard.vue是…

C++ STL map容器erase操作避坑

map容器的erase方法有三种重载形式&#xff1a; //1.删除迭代器所指向的元素 //返回值是指向下一个节点的迭代器 iterator erase(iterator it); //2.区间删除 iterator erase(iterator first, iterator last); //3.根据键值删除 //返回值为删除的元素个数 size_type erase(con…

民国漫画杂志《时代漫画》第37期.PDF

时代漫画37.PDF: https://url03.ctfile.com/f/1779803-1248636302-c017ee?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

C++基础编程100题-002 OpenJudge-1.1-04 输出保留3位小数的浮点数

更多资源请关注纽扣编程微信公众号 002 OpenJudge-1.1-04 输出保留3位小数的浮点数 http://noi.openjudge.cn/ch0101/04/ 描述 读入一个单精度浮点数&#xff0c;保留3位小数输出这个浮点数。 输入 只有一行&#xff0c;一个单精度浮点数。 输出 也只有一行&#xff0c;…

07.爬虫---使用session发送请求

07.使用session发送请求 1.目标网站2.代码实现 1.目标网站 我们以这个网站作为目标网站 http://www.360doc.com/ 注册用户 注册后从登录界面获取到这些信息 2.代码实现 import requestssession requests.Session() url http://www.360doc.com/ajax/login/login.ashx u…

深入剖析Java线程池的核心概念与源码解析:从Executors、Executor、execute逐一揭秘

文章目录 文章导图前言Executors、Executor、execute对比剖析Executors生成的线程池&#xff1f;线程池中的 execute 方法execute 方法的作用execute的工作原理拒绝策略 源码分析工作原理基本知识线程的状态线程池的状态线程池状态和线程状态总结线程池的状态信息和线程数量信息…

RedisSearch与Elasticsearch:技术对比与选择指南

码到三十五 &#xff1a; 个人主页 数据时代&#xff0c;全文搜索已经成为许多应用程序中不可或缺的一部分。RedisSearch和Elasticsearch是两个流行的搜索解决方案&#xff0c;它们各自具有独特的特点和优势。本文简单探讨一些RedisSearch和Elasticsearch之间的技术差异。 目录…

9款实用而不为人知的小众软件推荐!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 在电脑软件的浩瀚海洋中&#xff0c;除了那些广为人知的流行软件外&#xff0c;还有许多简单、干净、功能强大且注重实用功能的小众软件等待我们…

[NISACTF 2022]sign_crypto(LATEX)

题目&#xff1a; 我们看出这是LATEX编码&#xff0c;破解之后&#xff1a; 看出每个“\”之后的第一个字母连起来即使&#xff1a;nss....&#xff0c;在大写即可得到flag。

Sui Nami Bags对NFT使用案例进行创新

在四月的Sui Basecamp活动中&#xff0c;与会者体验了一系列Sui技术&#xff0c;这些技术以Nami Bags的形式呈现&#xff0c;这些数字礼包里满是来自Sui生态的NFT和优惠券。通过Enoki&#xff08;Mysten Labs的新客户参与平台&#xff09;提供支持&#xff0c;即使没有加密钱包…

OpenCV学习 基础图像操作(十七):泛洪与分水岭算法

原理 泛洪填充算法和分水岭算法是图像处理中的两种重要算法&#xff0c;主要用于区域分割&#xff0c;但它们的原理和应用场景有所不同&#xff0c;但是他们的基础思想都是基于区域迭代实现的区域之间的划分。 泛洪算法 泛洪填充算法&#xff08;Flood Fill&#xff09;是一…

修改element-ui el-radio颜色

修改element-ui el-radio颜色 需求效果图代码实现 小结 需求 撤销扣分是绿色&#xff0c;驳回是红色 效果图 代码实现 dom <el-table-columnlabel"操作"width"200px"><template v-slot"scope"><el-radio-group v-model"s…

Vue插槽与作用域插槽

title: Vue插槽与作用域插槽 date: 2024/6/1 下午9:07:52 updated: 2024/6/1 下午9:07:52 categories: 前端开发 tags:VueSlotScopeSlot组件通信Vue2/3插槽作用域API动态插槽插槽优化 第1章&#xff1a;插槽的概念与原理 插槽的定义 在Vue.js中&#xff0c;插槽&#xff08;…

c++(七)

c&#xff08;七&#xff09; 内联函数内联函数的特点为什么要有内联函数内联函数是如何工作的呢 类型转换异常处理智能指针单例模式懒汉模式饿汉模式 VS中数据库的相关配置 内联函数 修饰类的成员函数&#xff0c;关键字&#xff1a;inline inline 返回值类型 函数名(参数列…

vue-el-steps 使用2[代码示例]

效果图 代码 element代码 <template> <div class"app-container"> <el-form :model"queryForm" size"small" :inline"true"> <el-form-item label"内容状态"> <el-button-group> <el-bu…

as keyof GlobalStore

解释 as keyof GlobalStore 在 TypeScript 中&#xff0c;as keyof GlobalStore 是一种类型断言语法。它告诉 TypeScript&#xff0c;返回的值是一个特定类型的值&#xff0c;这里是 GlobalStore 类型的键。这在编译时有助于确保类型安全。 关键点&#xff1a; 类型断言&…

构建智慧银行保险系统的先进技术架构

随着科技的不断发展&#xff0c;智慧银行保险系统正日益受到关注。在这个数字化时代&#xff0c;构建一个先进的技术架构对于智慧银行保险系统至关重要。本文将探讨如何构建智慧银行保险系统的先进技术架构&#xff0c;以提升服务效率、降低风险并满足客户需求。 ### 1. 智慧银…

qwen-moe

一、定义 qwen-moe 代码讲解&#xff0c; 代码qwen-moe与Mixtral-moe 一样&#xff0c; 专家模块qwen-moe 开源教程Mixture of Experts (MoE) 模型在Transformer结构中如何实现&#xff0c;Gate的实现一般采用什么函数&#xff1f; Sparse MoE的优势有哪些&#xff1f;MoE是如…

统计信号处理基础 习题解答10-6

题目 在例10.1中&#xff0c;把数据模型修正为&#xff1a; 其中是WGN&#xff0c;如果&#xff0c;那么方差&#xff0c;如果&#xff0c;那么方差。求PDF 。把它与经典情况PDF 进行比较&#xff0c;在经典的情况下A是确定性的&#xff0c;是WGN&#xff0c;它的方差为&#…

5.算法讲解之-二分查找(简单易懂)

1.简介 1.二分查找的思路简单易懂&#xff0c;较难的是如何处理查找过程中的边界条件&#xff0c;当较长时间没写二分查找的时候就容易忘记如何处理边界条件。 2.只有多写代码&#xff0c;多做笔记就不易忘记边界条件 2.算法思路 正常查找都是从头到尾查找一个数字是否在数组中…