Ui自動化測試上傳文件方法都在這裏了

前言

實施UI自動化測試的時候,經常會遇見上傳文件的操作,那麼對於上傳文件你知道幾種方法呢?今天我們就總結一下幾種常用的上傳文件的方法,並分析一下每個方法的優點和缺點以及哪種方法效率,穩定性更高

被測HTML代碼

<!--upload_file.html-->


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上傳文件</title>
</head>
<body>
    <input id="upload_file" type="file">
</body>
</html>

第一種方法:使用webdriver api 提供的方法send_keys上傳文件

send_keys方法

實例

------------------------------------
@Time : 2019/7/17 19:03
@Auth : linux超
@File : upload_file_send_keys.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
from selenium import webdriver
import time


driver = webdriver.Firefox()
driver.get(r'file:///e:/CnblogCode/upload_file.html')
upload_element = driver.find_element_by_xpath('//*[@id="upload_file"]')
time.sleep(3)  # 爲了看效果
upload_element.send_keys(r'E:\CnblogCode\upload_file.html')

執行過程

可以看到執行過程很順利,且代碼實現簡單,也沒有報錯

但是往往現實是殘酷的,因爲有的網站的上傳文件並不是採用 input標籤來定義的上傳文件按鈕,所以就無法使用send_keys方法上傳,這也是這個方法的限制

AutoIt工具

第二種方法是AutoIT工具,它是一個類似腳本語言的軟件,利用此軟件我們可以方便的實現模擬鍵盤、鼠標、窗口等操作,實現自動化

安裝

官網地址:https://www.autoitscript.com/site/autoit/downloads/

安裝完後可以找到如下一些工具

使用

1. 打開被測試的HTML頁面,並點擊上傳文件,彈出上傳文件窗口,並保持當前窗口

2. 打開AutoIt Window Info(x86/x64)工具

3. 點擊工具中Finder Tool標籤下的按鈕,開始分別定位上傳文件的【輸入框】和【打開】按鈕,並記錄Title,Class,Instance(圖中紅色窗口中的信息)

注意:不同的瀏覽器抓取的Title是不一樣的(Firefox:文件上傳,Chrome:打開,IE:選擇要加載的文件)

4. 打開 SciTE Script Editor工具開始編寫腳本(注意腳本中的Edit1是class 和 instance 拼接的)

;first make sure the number of arguments passed into the scripts is more than 1
If $CmdLine[0]<2 Then Exit EndIf ;if parmas num <2 ,then break
;$CmdLine[0] ;參數的數量
;$CmdLine[1] ;第一個參數 (腳本名稱後面)
;$CmdLine[2] ;第二個參數
;都是從cmd傳入參數
 handleUpload($CmdLine[1],$CmdLine[2])

;定義上傳函數,有兩個參數,第一個是瀏覽器名字,第二參數是文件路徑
 Func handleUpload($browser, $uploadfile)
     Dim $title                          ;定義一個title變量
            ;根據彈窗的title來判斷是什麼瀏覽器
            If $browser="ie" Then                          ; 代表IE瀏覽器
                  $title="選擇要加載的文件"
            ElseIf $browser="chrome" Then               ; 代表谷歌瀏覽器
                 $title="打開"
            ElseIf    $browser="firefox" Then             ; 代表火狐瀏覽器
                  $title="文件上傳"
            EndIf

            if WinWait($title,"",4) Then ;等待彈出出現,最大等待時間是4秒
                   WinActivate($title)                  ;找到彈出窗口之後,激活當前窗口
                   ControlSetText($title,"","Edit1",$uploadfile)   ;把文件路徑放入輸入框,此”Edit1“是用FinderTool獲取到的
                   ControlClick($title,"","Button1")                ;點擊保存或者打開或者上傳按鈕,此“Button1”使用FinderTool獲取到的
            Else
            Return False
            EndIf
 EndFunc

5. 編譯腳本爲exe可執行文件

編寫完腳本之後,保存文件並打開Compile Script to .exe(x64/x86)工具 ,將保存後的腳本.au3文件轉換爲.exe可執行文件

6. 執行轉換後的腳本

在執行腳本之前,先確保上傳文件的窗口已經打開,接下來打開cmd執行exe程序  C:\Users\v-xug\Desktop>upload_file_new.exe firefox E:\CnblogCode\upload_file.html

7. 執行效果

8. 編寫selenium腳本

實例

"""
------------------------------------
@Time : 2019/7/18 16:20
@Auth : linux超
@File : base.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
from selenium.webdriver.common.action_chains import ActionChains
import os
from selenium import webdriver
import time


class Base(object):

    @staticmethod
    def upload_file(exe, browser, filename):
        """
        使用autoIt上傳文件
        :param exe: 上傳文件的exe程序所在目錄
        :param browser: 瀏覽器類型: firefox chrome ie
        :param filename: 待上傳文件路徑
        :return: none
        """
        cmd = exe + ' ' + browser + ' ' + filename
        os.system(cmd)


if __name__ == '__main__':
    driver = webdriver.Firefox()
    driver.get(r'file:///e:/CnblogCode/upload_file.html')  # 打開被測html
    upload_element = driver.find_element_by_xpath('//*[@id="upload_file"]')
    action = ActionChains(driver)
    action.move_to_element(upload_element).click().perform()  # 點擊上傳文件彈出上傳文件窗口
    action.release()
    time.sleep(3)  # 爲了看效果
    Base.upload_file(r'E:\CnblogCode\upload_file_new.exe', 'firefox', r'E:\CnblogCode\upload_file.html')  # 上傳文件

執行過程

以上就是使用AutoId工具完成上傳文件的過程,其實還是挺複雜的, 但是配置一次之後,以後就可以重複使用編譯生成的exe文件了,執行效果還是不錯的 沒出什麼錯誤,執行效率也還可以

模擬鍵盤

第三種方法:模擬鍵盤的粘貼與回車操作並結合剪切板的操作來完成上傳文件,基本原理是向剪切板中發送文件(文件路徑字符串),然後再從剪切板中獲取到文件,最後通過模擬鍵盤的ctrl+v與enter鍵來完成文件上傳

這種方法需要第三方庫的支持,安裝pypiwin32庫: pip install pypiwin32

實例

模擬鍵盤操作代碼

"""
------------------------------------
@Time : 2019/7/18 17:14
@Auth : linux超
@File : keyboard.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import win32api
import win32con
import time


class KeyBoard(object):
    """模擬按鍵"""
    # 鍵盤碼
    vk_code = {
        'enter' : 0x0D,
        'ctrl' : 0x11,
        'v' : 0x56
    }

    @staticmethod
    def keyDown(key_name):
        """按下鍵"""
        key_name = key_name.lower()
        try:
            win32api.keybd_event(KeyBoard.vk_code[key_name], 0, 0, 0)
        except Exception as e:
            print('未按下enter鍵')
            raise e

    @staticmethod
    def keyUp(key_name):
        """擡起鍵"""
        key_name = key_name.lower()
        win32api.keybd_event(KeyBoard.vk_code[key_name], 0, win32con.KEYEVENTF_KEYUP, 0)

    @staticmethod
    def oneKey(key):
        """模擬單個按鍵"""
        key = key.lower()
        KeyBoard.keyDown(key)
        time.sleep(2)
        KeyBoard.keyUp(key)

    @staticmethod
    def twoKeys(key1, key2):
        """模擬組合按鍵"""
        key1 = key1.lower()
        key2 = key2.lower()
        KeyBoard.keyDown(key1)
        KeyBoard.keyDown(key2)
        KeyBoard.keyUp(key1)
        KeyBoard.keyUp(key2)


if __name__ == '__main__':
    pass
keyboard.py

剪切板操作代碼

"""
------------------------------------
@Time : 2019/7/18 17:18
@Auth : linux超
@File : clipboard.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import win32con
import win32clipboard as WC


class ClipBoard(object):
    """設置剪切板內容和獲取剪切板內容"""

    @staticmethod
    def getText():
        """獲取剪切板的內容"""
        WC.OpenClipboard()
        value = WC.GetClipboardData(win32con.CF_TEXT)
        WC.CloseClipboard()
        return value

    @staticmethod
    def setText(value):
        """設置剪切板的內容"""
        WC.OpenClipboard()
        WC.EmptyClipboard()
        WC.SetClipboardData(win32con.CF_UNICODETEXT, value)
        WC.CloseClipboard()


if __name__ == '__main__':
    pass
clipboard.py

上傳文件代碼

"""
------------------------------------
@Time : 2019/7/18 17:20
@Auth : linux超
@File : upload_file_board.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
from clipboard import ClipBoard
from keyboard import KeyBoard

from selenium import webdriver
import time
from selenium.webdriver.common.action_chains import ActionChains


if __name__ == '__main__':
    ClipBoard.setText(r'E:\CnblogCode\upload_file.html')  # 待上傳文件設置到剪切板
    driver = webdriver.Firefox()
    driver.get(r'file:///e:/CnblogCode/upload_file.html')
    upload_element = driver.find_element_by_xpath('//*[@id="upload_file"]')
    action = ActionChains(driver)
    action.move_to_element(upload_element).click().perform()
    action.release()
    time.sleep(3)  # 爲了看效果
    KeyBoard.twoKeys('ctrl', 'v')
    KeyBoard.oneKey('enter')
upload_file_board.py

執行過程

失敗

可以看到第二個動畫上傳文件未成功,這也就這個方法的弊端,只要移動了鼠標就有可能就不會成功,畢竟模擬的是enter鍵,這個過程你點擊了別的地方,那麼enter的效果就變了,所以這種方法很不穩定,也不難發現,代碼量也很多,而且需要掌握模擬鍵盤和剪切板的操作,最不推薦使用的就是這種方法

之前我的實戰項目裏面,用到過這種方法, 當時我已經發現了這種方法的弊端, 但是爲了掌握這種模擬鍵盤的方法,所以才使用的,當然模擬鍵盤操作用到一些特殊的情況還是能解決很多實際問題的

WinSpy工具

第四種方法:這個工具其實和AutoIt工具的元素定位方式一樣,但是不需要生成exe文件,其實只是個輔助工具,主要用來獲取windows窗口句柄,進而通過python腳本來控制

WinSpy安裝

https://sourceforge.net/projects/winspyex/

下載完直接解壓打開WinSpy32(64).exe即可使用

使用方法和autoId一樣,請按照下圖的步驟操作,記錄winspy-Tree中紅框信息

編寫代碼之前,同樣需要提前安裝 pypiwin32庫

實例

"""
------------------------------------
@Time : 2019/7/17 19:14
@Auth : linux超
@File : upload_file_winspy.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import win32con
import win32gui
import time


def upload_file(browser: str, file: str):
    browser_type = {
        "firefox": "文件上傳",
        "chrome": "打開",
        "ie": "選擇要加載的文件"
    }
    time.sleep(2)
    dialog = win32gui.FindWindow("#32770", browser_type[browser])  # 火狐瀏覽器爲”文件上傳“,谷歌爲”打開“
    combobox_ex32 = win32gui.FindWindowEx(dialog, 0, "ComboBoxEx32", None)
    combobox = win32gui.FindWindowEx(combobox_ex32, 0, 'ComboBox', None)
    edit = win32gui.FindWindowEx(combobox, 0, 'Edit', None)
    button = win32gui.FindWindowEx(dialog, 0, 'Button', None)
    win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, file)
    win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)


if __name__ == '__main__':
    driver = webdriver.Firefox()
    driver.get(r'file:///e:/CnblogCode/upload_file.html')
    upload_element = driver.find_element_by_xpath('//*[@id="upload_file"]')
    action = ActionChains(driver)
    action.move_to_element(upload_element).click().perform()
    action.release()
    time.sleep(3)  # 爲了看效果
    upload_file('firefox', r'E:\CnblogCode\upload_file.html')
load_file_winspy.py

 

執行過程

此方法也比較穩定,只要通過傳遞不同的瀏覽器參數,即可完成不同瀏覽器中的上傳文件操作,而且相比於AutoId而言,這種方法可以直接使用python編寫代碼且不需要編譯成exe程序,可以隨時對代碼進行修改,易維護

總結

最後總結一下每個方法的優缺點

1. send_keys(): 如果所遇見的上傳文件使用的是input標籤且屬性type=file,均可使用,也最好採用此方法,方便,簡單,執行效率高

2. AutoId: 需編寫VBS代碼並編譯爲exe可執行文件,過程繁瑣,編寫selenium測試用例時無法隨時調試內部代碼,但send_keys()無法使用時,可以採用此方法,執行效率較高,穩定性也算可以

3. 模擬鍵盤和剪切板: 此方法需要掌win32api,win32gui模塊的使用,且代碼編寫繁瑣,上傳文件時如果鼠標點擊其他地方會導致上傳失敗,腳本穩定性差,且效率低,但是如果用到一些特殊地方會起到比較好的效果

4. WinSpay:windows窗口句柄抓取工具,不需要編譯腳本爲exe文件,且上傳文件操作使用的腳本是python第三方庫實現,易維護,執行效率也較高,推薦send_keys()不可使用時,首先考慮此方法

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章