文件上传是做UI自动化测试时候的一个大问题,尝试了一下网上各种上传文件的方式,以下试验按照使用频率来排名。(多个方法多个思路,你要不想学“茴”字的四种写法,看第一个就够了)
在动手之前,我们要区分出上传按钮的种类,大体上可以分为两种
- 一种是input框
- 另外一种就比较复杂,通过js、flash等实现,标签非input
我们分别对这两种进行分析:
1.input标签
众所周知,input标签是可以直接send_keys的,这种情况下就简单粗暴,来看代码示例:
1 from selenium import webdriver 2 import time 3 4 driver = webdriver.Firefox() 5 driver.get('url') 6 driver.find_element_by_name('myfile').send_keys('d:\\test.png') #输入的是文件的绝对路径。
2.非input型上传
那么对于那些不是input框实现的上传怎么办,这种上传千奇百怪,有用a标签的,有用div的,有用button的,有用object的,我们没有办法通过直接在网页上处理掉这些上传,唯一的办法就是打开windows的系统弹框,去处理弹框。
问题又来了,Selenium2.0还不能解决掉windows系统弹框的问题,怎么办?很简单,用OS层面的操作去处理呗(谁家的孩子谁家领回家的思维方式在哪里都好用)
大体上有以下四种解决方案:
- Python pywin32库,识别对话框句柄,进而操作
- pywinauto库
- pyautogui库
- autoIT,借助外力,我们去调用其生成的au3或exe文件。
1 首先安装pywin32库(命令:pip install pywin32)
2 代码示例
from selenium import webdriver import win32gui import win32con dr = webdriver.Firefox() dr.get('http://localhost/test/fileupload.html') dr.find_element_by_id('file').click()# win32gui dialog = win32gui.FindWindow('#32770', '文件上传') # 对话框 ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None) ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None) Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None) # 上面三句依次寻找对象,直到找到输入框Edit对象的句柄 button = win32gui.FindWindowEx(dialog, 0, 'Button', None) # 确定按钮Button win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, 'd:\\all_money.wmv') # 往输入框输入绝对地址 win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) # 按button
这个地方大家其实对识别对话框的句柄有问题,这个在使用autoIt的时候可以解决掉,或者使用Spy++这个小工具。其它的也就是win32gui里面的api调用方式。
NO 2:AutoIt
1 pip install pywinauto
代码如下:
1 from selenium import webdriver 2 from pywinauto import Desktop 3 import time 4 dr=webdriver.Chrome() 5 6 dr.get('url') 7 dr.maximize_window() 8 time.sleep(1) 9 10 # 操作系统的指令 11 wd = Desktop() 12 open = wd['打开'] #根据名字找到弹出窗口 13 open["Edit"].type_keys("D:\demo.txt") # 在输入框中输入值 14 open["Button"].click()
NO 3:pyautogui库
from selenium import webdriver import pyautogui import time dr=webdriver.Chrome() dr.get('url') dr.maximize_window() dr.find_element_by_name('myfile').click() time.sleep(1) pyautogui.write(r'd:\demo.txt') time.sleep(1) pyautogui.press('enter')#回车按键
但是路径内有中文的话这种方法是不支持的,解决方法如下:
from selenium import webdriver import pyautogui import pyperclip import time dr=webdriver.Chrome() dr.get('url') dr.maximize_window() dr.find_element_by_name('myfile').click() pyperclip.copy(r'd:\测试.txt') time.sleep(1) pyautogui.hotkey('ctrl','v') time.sleep(1) pyautogui.press('enter') time.sleep(2)
D:\ uploadfile.exe param1 "This is an int parameter" 102
在脚本中,可用以下变量获取命令行参数:
$CmdLine[0] ; = 3 $CmdLine[1] ; = param1 $CmdLine[2] ; = "This is an int parameter" $CmdLine[3] ; = 102 $CmdLineRaw ; = 'param1 "This is a string parameter" 99'
$CmdLine[0] 获取的是命令行参数的总数,在上例中参数有3个。
$CmdLine[1]~$CmdLine[63] 获取的是命令行参数第1到第63位,这个方式最多只能获取63个参数,不过正常情况下是足够用的
$CmdLineRaw 获取的是未拆分的所有参数,是一个长字符串,这种情况下不局限与63个参数
通过autoit的获取对象并编辑脚本:
ControlFocus("文件上传", "", "Edit1") WinWait("[CLASS:#32770]", "", 10) ControlSetText("文件上传" ,"", "Edit1", $CmdLine[1]) Sleep(2000) ControlClick("文件上传", "","Button1");
通过Aut2Exe工具将脚本转成exe文件(uploadfile.exe)
接着就可以使用Python中的os模块来运行这个exe执行程序了。
# -*- coding: utf-8 -*- from selenium import webdriver import os import time driver = webdriver.Firefox() driver.get('http://localhost/test/fileupload.html') driver.find_element_by_id('file').click() time.sleep(1) os.system('D:\\Python\\Demo\\uploadfile.exe "d:\\all_money.wmv" ') # 这里可以对传参进行参数化,我们可以通过py脚本来控制所要上传的文件了 time.sleep(3) driver.quit()
在处理弹框的方法中根据浏览器类型的不同而进行选择,或者每次去获取所有类型弹框,再或者通过参数传入该弹框的名称。
进阶版:
刚才的几种方法都是上传单个的文件的操作,如果我想上传多个文件怎么办呢?
答案很简单:
“D:\allmoney.txt” “D:\allgirls.txt”
注意点为:所有文件最好放于同一路径下,才能这样用,否则是会失败的。(这个还没找到合适的网站测试,稍后添加)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?