借助pywinauto实现本地文件上传--转载
https://www.jianshu.com/p/cd85d24a52ef
在自动化测试过程中,有时候需要上传文件,比如类似合同新建等功能必须要求强制上传附件。
附件上传的页面控件有两种情况
第一种,Html原生的input file控件,也就是input标签中type="file";
第二种,通过其他一些方式实现的上传功能,比如swfupload.js。
对于第一种文件上传也就是input控件的方式,
<div>
<span>选择文件</span>
<input type="file" id="upload_pic">
</div>
直接采用send_keys的方式就可以:
driver.find_element_by_id('upload_pic').send_keys('E:\\1.jpg')
注意,这种方式上传时,页面上不会显示图片缩略图或者图片路径;并且只能上传一张图片。
对于第二种上传文件的方式,或者说想传多个文件的时候,就必须要采用按钮点击的方式,这种方式有个最大的问题就是当点击上传按钮后,会弹出文件选择框,这个选择框是脱离于浏览器的,因此无法直接使用selenium来操作。
目前网上关于使用按钮上传文件的教程,基本上都是介绍如何使用AutoIt V3。
AutoIt有很多的缺点,一是需要编译成exe文件,会被杀毒软件删除;二是由于写autoit脚本的时候,只能使用文件窗口的名称,chrome和firefox上传文件的窗口名称都不一致,这就导致了兼容性问题。
*chrome选择文件的窗口名称是“打开”,Firefox选择文件的窗口名称是“文件上传”。
因此我们需要寻求新的方式,偶然的情况了解到python有一个专门用来测试Win32程序的库 pywinauto,尝试之后发现pywinauto可以避免兼容性问题,并且由于pywinauto是python的库,因此可以直接用写代码的方式而不用编译成exe再调用了。
首先,我们先下载pywinauto:
pip install pywinauto
pywinauto操作窗口的方式类似AutoIt,也需要先利用 AutoIt或spy++lite (关于这两种工具的用法,请自行百度)找到选择文件窗口的class_name,文本框和按钮的class_name。
注意,使用pywinauto的时候依然需要通过selenium先点击“上传/下载”按钮,弹出文件选择框,完整的参考脚本如下:
from pywinauto import application
from selenium import webdriver
… # 进入文件上传页面的代码省略
driver.find_element_by_id('upload_pic').click() # 点击上传/浏览按钮
sleep(2) # 需要稍作等待,因为点击上传按钮到文件选择窗口打开会有延迟
app = application.Application() # 实例化Application
# 这里用的class而没有加窗口title,主要为了保证兼容性
app.connect(class_name='#32770') #根据class_name找到弹出窗口
app["Dialog"]["Edit1"].TypeKeys("E:\\1.jpg") # 在输入框中输入值
app["Dialog"]["Button1"].click() # 点击打开/保存按钮
思路与使用AutoIt的思路一样,
通过selenium中的方式点击上传按钮,
注意这里一定要强制等待,等待时长根据机器具体的配置决定,
在打开的文件选择窗口中输入文件的路径,
E:\1.jpg 就是需要上传的文件,
最后确定即可。
以上代码Windows下比较通用,可以直接使用。
Pywinauto操作的方式比AutoIt更简单方便,可以直接写成函数,在脚本中进行调用。另外由于脚本中没有用到窗口的title,因此保证了浏览器兼容性。
这段代码也可以用在文件下载中,其实下载窗口与上传窗口都是一样的,因此下载也可以使用上面的代码。
注意,
如果是64位的python会提示一个警告信息:“UserWarning: 32-bit application should be automated using 32-bit Python (you use 64-bit Python) UserWarning)”,可以忽略。