1. 程式人生 > >【開源自動化測試疑難FAQ】【WebDriver】WebDriver對SWFUpload的無奈之舉

【開源自動化測試疑難FAQ】【WebDriver】WebDriver對SWFUpload的無奈之舉

       發現個極品開發在上載的時候毫無由頭的不去用公司通用的標準控制元件,居然用一個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