Selenium进阶——解决web 自动化中上传文件的问题

在做ui自动化测试中,经常会遇到上传文件或者图片的场景,通常的解决方案是自动化工具+autoIT,在这里我介绍一种

通过jdk自带api—— java.awt.Robot 来解决类似问题的方法。java.awt.Robot类主要用于模拟用户点击键盘上的按键,或者模拟用户敲击鼠标等动作。

在做web测试时,弹出窗口如下图所示:

 

Selenium进阶——解决web 自动化中上传文件的问题

Windows上传文件对话框

 

对于打开上传文件框是input形式的控件可以用selenium 的方法:driver.findElement(By.id("")).sendKeys("文件路径")来完成上传操作;

如果不是,我们可以利用Robot类来解决该问题。核心思路:

1.打开弹出窗口后,光标在输入框内,然后使用键盘上的keycode写入上传文件具体信息

2.点击Tab键(光标移动到“所有文件”框中)

3.点击Tab键(光标移动到“打开”按钮上)

4.点击Enter键,完成上传文件操作。

注意:该方法不支持中文,因此文件路径和名称不能包括中文。

点击键盘按键核心代码如下:

robot.keyPress(keyCodes);

robot.keyRelease(keyCodes);

点击Tab键

robot.keyPress(KeyEvent.VK_TAB);

robot.keyRelease(KeyEvent.VK_TAB);

点击Enter键

robot.keyPress(KeyEvent.VK_ENTER);

robot.keyRelease(KeyEvent.VK_ENTER);

输入字符‘a’

robot.keyPress(KeyEvent. VK_A);

robot.keyRelease(KeyEvent. VK_A);

输入字符‘A’,需要Shift键的配合

robot.keyPress(KeyEvent.VK_SHIFT);

robot.keyPress(KeyEvent.VK_A);

robot.keyRelease(KeyEvent.VK_A);

robot.keyRelease(KeyEvent.VK_SHIFT);

更多的按键信息请参考:

https://docs.oracle.com/javase/8/docs/api/java/awt/event/KeyEvent.html

由于每次输入字符都需要调用robot.keyPress和robot.keyRelease方法,当处多字符写入的场景时效率太低,所以我们需要编写方便的API便于调用,核心代码如下:

import java.awt.AWTException;

import java.awt.Robot;

import java.awt.event.KeyEvent;

import static java.awt.event.KeyEvent.*;

public class RobotKeyboard {

   private static RobotKeyboard uniqueInstance = null;

    private Robot robot;

   publicRobotKeyboard()throws AWTException {

        this.robot = new Robot();

   }

 

   public static synchronized  RobotKeyboardgetInstance()throws AWTException {

        if (uniqueInstance == null) {

            uniqueInstance = new RobotKeyboard();

        }

        return uniqueInstance;

    }

   //输入字符串

   public void typeWords(CharSequence characters) {

 

        int length = characters.length();

        for (int i = 0; i < length; i++) {

            char character = characters.charAt(i);

            typeChar(character);

        }

   }

 //输入特殊键盘按键

   public void typeKey(String p_string,int p_times) {

 

       if (p_string.equalsIgnoreCase("Tab"))

       doTypeLoop(KeyEvent.VK_TAB,p_times);

       else if (p_string.equalsIgnoreCase("Enter"))

       doTypeLoop(KeyEvent.VK_ENTER,p_times);

       else if (p_string.equalsIgnoreCase("Up"))

       doTypeLoop(KeyEvent.VK_UP,p_times);

       else if (p_string.equalsIgnoreCase("Down"))

       doTypeLoop(KeyEvent.VK_DOWN,p_times);

       else if (p_string.equalsIgnoreCase("Left"))

       doTypeLoop(KeyEvent.VK_LEFT,p_times);

       else if (p_string.equalsIgnoreCase("Right"))

       doTypeLoop(KeyEvent.VK_RIGHT,p_times);

       else if (p_string.equalsIgnoreCase("Shift"))

       doTypeLoop(KeyEvent.VK_SHIFT,p_times);

       else if (p_string.equalsIgnoreCase("ESC"))

       doTypeLoop(KeyEvent.VK_ESCAPE,p_times);

       else if (p_string.equalsIgnoreCase("Backspace"))

       doTypeLoop(KeyEvent.VK_BACK_SPACE,p_times);

       else doTypeLoop(0,p_times);

   }

 

   //输入常用单个字符

   public void typeChar(char character) {

        switch (character) {

        case 'a': doType(VK_A); break;

        case 'b': doType(VK_B); break;

        case 'c': doType(VK_C); break;

        case 'd': doType(VK_D); break;

        case 'e': doType(VK_E); break;

        case 'f': doType(VK_F); break;

        case 'g': doType(VK_G); break;

        case 'h': doType(VK_H); break;

        case 'i': doType(VK_I); break;

        case 'j': doType(VK_J); break;

        case 'k': doType(VK_K); break;

        case 'l': doType(VK_L); break;

        case 'm': doType(VK_M); break;

        case 'n': doType(VK_N); break;

        case 'o': doType(VK_O); break;

        case 'p': doType(VK_P); break;

        case 'q': doType(VK_Q); break;

        case 'r': doType(VK_R); break;

        case 's': doType(VK_S); break;

        case 't': doType(VK_T); break;

        case 'u': doType(VK_U); break;

        case 'v': doType(VK_V); break;

        case 'w': doType(VK_W); break;

        case 'x': doType(VK_X); break;

        case 'y': doType(VK_Y); break;

        case 'z': doType(VK_Z); break;

        case 'A': doType(VK_SHIFT, VK_A); break;

        case 'B': doType(VK_SHIFT, VK_B); break;

        case 'C': doType(VK_SHIFT, VK_C); break;

        case 'D': doType(VK_SHIFT, VK_D); break;

        case 'E': doType(VK_SHIFT, VK_E); break;

        case 'F': doType(VK_SHIFT, VK_F); break;

        case 'G': doType(VK_SHIFT, VK_G); break;

        case 'H': doType(VK_SHIFT, VK_H); break;

        case 'I': doType(VK_SHIFT, VK_I); break;

        case 'J': doType(VK_SHIFT, VK_J); break;

        case 'K': doType(VK_SHIFT, VK_K); break;

        case 'L': doType(VK_SHIFT, VK_L); break;

        case 'M': doType(VK_SHIFT, VK_M); break;

        case 'N': doType(VK_SHIFT, VK_N); break;

        case 'O': doType(VK_SHIFT, VK_O); break;

        case 'P': doType(VK_SHIFT, VK_P); break;

        case 'Q': doType(VK_SHIFT, VK_Q); break;

        case 'R': doType(VK_SHIFT, VK_R); break;

        case 'S': doType(VK_SHIFT, VK_S); break;

        case 'T': doType(VK_SHIFT, VK_T); break;

        case 'U': doType(VK_SHIFT, VK_U); break;

        case 'V': doType(VK_SHIFT, VK_V); break;

        case 'W': doType(VK_SHIFT, VK_W); break;

        case 'X': doType(VK_SHIFT, VK_X); break;

        case 'Y': doType(VK_SHIFT, VK_Y); break;

        case 'Z': doType(VK_SHIFT, VK_Z); break;

        case '`': doType(VK_BACK_QUOTE); break;

        case '0': doType(VK_0); break;

        case '1': doType(VK_1); break;

        case '2': doType(VK_2); break;

        case '3': doType(VK_3); break;

        case '4': doType(VK_4); break;

        case '5': doType(VK_5); break;

        case '6': doType(VK_6); break;

        case '7': doType(VK_7); break;

        case '8': doType(VK_8); break;

        case '9': doType(VK_9); break;

        case '-': doType(VK_MINUS); break;

        case '=': doType(VK_EQUALS); break;

        case '~': doType(VK_SHIFT, VK_BACK_QUOTE); break;

        case '!': doType(VK_EXCLAMATION_MARK); break;

        case '@': doType(VK_AT); break;

        case '#': doType(VK_NUMBER_SIGN); break;

        case '$': doType(VK_DOLLAR); break;

        case '%': doType(VK_SHIFT, VK_5); break;

        case '^': doType(VK_CIRCUMFLEX); break;

        case '&': doType(VK_AMPERSAND); break;

        case '*': doType(VK_ASTERISK); break;

        case '(': doType(VK_LEFT_PARENTHESIS); break;

        case ')': doType(VK_RIGHT_PARENTHESIS); break;

        case '_': doType(VK_UNDERSCORE); break;

        case '+': doType(VK_PLUS); break;

        case '\t': doType(VK_TAB); break;

        case '\n': doType(VK_ENTER); break;

        case '[': doType(VK_OPEN_BRACKET); break;

        case ']': doType(VK_CLOSE_BRACKET); break;

        case '\\': doType(VK_BACK_SLASH); break;

        case '{': doType(VK_SHIFT, VK_OPEN_BRACKET); break;

        case '}': doType(VK_SHIFT, VK_CLOSE_BRACKET); break;

        case '|': doType(VK_SHIFT, VK_BACK_SLASH); break;

        case ';': doType(VK_SEMICOLON); break;

        case ':': doType(VK_SHIFT, VK_SEMICOLON); break;

        case '\'': doType(VK_QUOTE); break;

        case '"': doType(VK_QUOTEDBL); break;

        case ',': doType(VK_COMMA); break;

        case '<': doType(VK_LESS); break;

        case '.': doType(VK_PERIOD); break;

        case '>': doType(VK_GREATER); break;

        case '/': doType(VK_SLASH); break;

        case '?': doType(VK_SHIFT, VK_SLASH); break;

        case ' ': doType(VK_SPACE); break;

        default:

            throw new IllegalArgumentException("Cannot type character " + character);

        }

   }

 

   //无需shift键配合的单字符输入的核心API

   private void doType(int keyCodes) {

    if(keyCodes==0)

    {

        return;

    }

    robot.keyPress(keyCodes);

    robot.keyRelease(keyCodes);

 }

 

   //循环输入键值

   private void doTypeLoop(int keyCodes,int times){

    if(keyCodes==0)

    {

        return;

    }

    for(int i=0;i<times;i++){

        robot.keyPress(keyCodes);

         robot.keyRelease(keyCodes);

    }

 

 }

   //需要shift键配合的单字符输入的核心API

   private void doType(int keyShit,int keyCodes) {

    if(keyCodes==0)

    {

        return;

    }

    robot.keyPress(keyShit);

    robot.keyPress(keyCodes);

    robot.keyRelease(keyCodes);

    robot.keyRelease(keyShit);

    }

}

 

使用代码如下:

public static void main(String[] args) throws AWTException {

    RobotKeyboard.getInstance().type("D:\\test\\test.png"); //输入要上传的文件

    RobotKeyboard.getInstance().typeKey("Tab", 2); //点击两次Tab键

    RobotKeyboard.getInstance().typeKey("Enter", 1);//点击一次Tab键

 

}

这里只提供了基础代码,大家可以根据项目实际需求进行改写!