发现个极品开发在上载的时候毫无由头的不去用公司通用的标准控件,居然用一个flash控件,一查发现叫SWFUpload。上google查了好一会,貌似目前WebDriver还是不支持对这玩意的处理的。
思考了一会,对网页上的组件做自动化无非就是考虑js或者浏览器接口,既然这二者都行不通,那么也许改考虑一下GUI工具,最不济的就是鼠标键盘动作的模拟。所以又查了一会autoit对flash的处理,没有找到对这个页面上这个组件的好的处理方式,因为用暴力的坐标定位的方法可能不具备可移植性。没办法只好用键盘模拟了,试了一下,在flash控件的前一个div单击或者双击之后用一次TAB键,就可以聚焦到flash控件(图中的上载)上,然后再给一个ENTER/RETURN应该可以。反复试了几次,发现TAB可以,而ENTER/RETURN是不行的,幸好我还有点QTP基础,对vbs烂熟,索性调用vbs的键盘模拟试试……结果发现是可以的。
package com.star.autotest.demo;
import com.star.frame.basecase.WebDriverBaseCase;
import org.openqa.selenium.interactions.Actions;
import com.star.support.externs.Win32GuiByVbs;
import org.testng.annotations.Test;
import org.openqa.selenium.Keys;
import org.openqa.selenium.By;
import java.io.File;
public class UploadTest extends WebDriverBaseCase {
protected static Actions action = new Actions(driver);
@Test(alwaysRun = true)
public void testUpload() {
Win32GuiByVbs gui32 = new Win32GuiByVbs();
final String vbs = "Set WshShell = CreateObject(\"Wscript.shell\") \n"
+ "WshShell.sendKeys \"{ENTER}\" \n" + "Set WshShell = Nothing";
final String vbsfileName = gui32.getEnvironment("TEMP") + "\\test.vbs";
startWebDriver();
get("http://XXXXXX.com.cn/YYYY/ZZZZ.do");
maximizeWindow();
selectWindow(">>邮件附件上传");
waitForElementVisible(By.id("closeUpload"), 30);
doubleClick(findElement(By.id("fsUploadProgress")));
action.sendKeys(Keys.TAB);
action.perform();
pause(500);
gui32.createVbsFile(vbs, vbsfileName);
gui32.executeVbsFile(vbsfileName);
new File(vbsfileName).delete();
AU3.fileUpload("选择要上载的文件,通过: XXXXXX.com.cn", "D:\\ABCDEFG.doc", 10);
}
}
其他的相关引用方法:
/**
* execute a vbs file.
*
* @param vbsfileName whole name whitch vbs file to be executed
* @throws RuntimeException
**/
public void executeVbsFile(String vbsfileName){
try {
String[] vbsCmd = new String[]{"wscript", vbsfileName};
Process process = Runtime.getRuntime().exec(vbsCmd);
process.waitFor();
} catch (Exception e) {
LOG.error(e);
throw new RuntimeException("execute extern file failed:" + e.getMessage());
}
}
/**
* create a temp vbs file to be executed.
*
* @param vbs string content to be written into file
* @param vbsfileName whole name whitch vbs file to be saved
* @throws RuntimeException
**/
public void createVbsFile(String vbs, String vbsfileName){
File file = new File(vbsfileName);
BufferedWriter writer = null;
try{
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
writer.write(vbs);
writer.flush();
writer.close();
}catch(Exception e){
LOG.error(e);
throw new RuntimeException("execute extern file failed:" + e.getMessage());
}
}
/**
* get system environment values.
*
* @param virName viriable name to get, such as "classpath", "JAVA_HOME"
* @return the viriable value
* @throws RuntimeException
**/
public String getEnvironment(String virName) {
byte[] env = new byte[1000];
try {
Process process = Runtime.getRuntime().exec("cmd /c echo %" + virName + "% ");
process.waitFor();
InputStream iStream = process.getInputStream();
iStream.read(env);
} catch (Exception e) {
LOG.error(e);
throw new RuntimeException("execute extern file failed:" + e.getMessage());
}
return new String(env).trim();
}
至于AUTOIT的代码,也没有新意,实用即可:
If $CmdLine[0] < 3 Then
Exit
EndIf
fileUpload($CmdLine[1], $CmdLine[2], $CmdLine[3])
Func fileUpload($uploadtitle, $uploadfile, $timeout)
WinWait($uploadtitle,"",$timeout)
If WinExists($uploadtitle) Then
WinActive($uploadtitle)
Sleep (500)
ControlSetText($uploadtitle,"","Edit1",$uploadfile)
ControlClick($uploadtitle, "", "打开(&O)")
Else
Return False
EndIf
EndFunc