到此,一个 Junit4 test case 就在 Eclipse 中建成 , 如代码清单 1.
清单 1. 将脚本导入 Eclipse
package com.example.casePackage; import static org.junit.Assert.fail ; import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; import com.example.util.TVTUtility; public class TestCase{ private WebDriver driver; private String baseUrl; /* * This is the directory to save the screen captures, if you have finished a * language executing, please change the directory to save another * languages screen captures */ public static final String DIRECTORY = "c:\\ScreenCapture\\jp\\"; // the pictures's format public static final String FORMAT = ".gif"; private StringBuffer verificationErrors = new StringBuffer(); @Before public void setUp() throws Exception { driver = TVTUtility.openPreferenceFirefox ("en"); baseUrl = "https://9.115.46.97:16311"; driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS ); driver.manage().window().maximize(); } @Test public void testCase_01010010() throws Exception { System.out .println("case1 start"); driver.get(baseUrl + "/ibm/console/logon.jsp"); driver.findElement(By.id ("j_username")).clear(); driver.findElement(By.id ("j_username")).sendKeys("admin"); driver.findElement(By.id ("j_password")).clear(); driver.findElement(By.id ("j_password")).sendKeys("password"); driver.findElement(By.id ("other")).click(); /* * judge whether the user has login in the system or not, if the user * has already login in, then click OK button to log-out * the pre-user, * if there were no user has login the system, just ignore this step */ if (isElementPresent(By.name ("submit"))) { driver.findElement(By.name ("submit")).click(); } driver.switchTo().frame("ISCNavigation"); driver.findElement(By.id ("2-nav-tree-expandable-item")).click(); driver.findElement(By.id ("3-nav-tree-expandable-item")).click(); driver.findElement(By.id (" nav-tree-item-com.ibm.license.mgmt.ui.reports.ManageReports.node"\ )).click(); Thread.sleep (1000); driver.switchTo().defaultContent(); driver.switchTo().frame("ISCWork"); driver.findElement(By.className ("btnm1")).click(); driver.findElement(By.className ("pop5")).click(); Thread.sleep (1000); driver.findElement(By.xpath("html/body/div[1]/table/tbody/tr/td/div/ table/tbody/tr/td/table/tbody/tr[3]/td/table/tbody/tr/td/form/span/ table/tbody/tr[3]/td/table[2]/tbody/tr/td/table/tbody/tr[3]/td/table/ tbody/tr[3]/td[1]/table/tbody/tr/td/table/tbody/tr/td/table/tbody/ tr/td[4]/a/img")).click(); Select m1= new Select(driver.findElement(By.id(TVTUtility.byDom( driver,"document.getElementsByTagName('select')[0].id")))); m1.selectByIndex(9); // select the day Select y1= new Select(driver.findElement(By.id(TVTUtility.byDom( driver,"document.getElementsByTagName('select')[1].id")))); y1.selectByValue("2013"); driver.findElement(By.linkText("9")).click(); driver.findElement( By.xpath("html/body/div[3]/div/table/tbody/tr[3]/td/input[1]"\ )).click(); driver.findElement(By.xpath("html/body/div[1]/table/tbody/tr/td/\ div/table/tbody/tr/td/table/tbody/tr[3]/td/table/tbody/tr/td/form/\ span/table/tbody/tr[3]/td/table[2]/tbody/tr/td/table/tbody/tr[3]/\ td/table/tbody/tr[5]/td/table/ tbody/tr/td[1]/input")).click(); Thread.sleep(1000); TVTUtility.captureScreen(driver, DIRECTORY,\ TVTUtility.getMethodName(),FORMAT); System.out.println("case1 finished"); } @After public void tearDown() throws Exception { driver.quit(); String verificationErrorString = verificationErrors.toString(); if (!"".equals(verificationErrorString)) { fail(verificationErrorString); } }}
[size=1em]清单 1 是一个完整的 Case 脚本,每个脚本从 Selenium IDE 中导出来都会由三个方法组成,setup(),tearDown() 和 testXxx()。setup() 在 testXxx() 前执行,tearDown() 在 testXxx() 之后执行。setup() 主要是用来初始化一些通用参数,比如 WebDriver 的构建和某些参数的初始化工作,或者系统的登陆。tearDown() 主要是来关闭浏览器等后续动作 ,Case 的主体在 testXxx() 中完成。
[size=1em]由于每个 Case 的主要步骤都是在 testXxx() 方法中完成,而 setup() 和 tearDown() 方法是一些通用的步骤,所以在写脚本的时候,不用为每一个导出的脚本都新建一个 Java 类,只需要将脚本中的 testXxx() 方法拷贝到已经建好的类中,并重用 setup() 和 tearDown() 方法。这样就可以在一个类中添加多个 testXxx() 方法,每个方法对应一个 Case 脚本。
[size=1em]其中 testXxx() 方法命名最好是有规律和规范的,比如 testCase_01010010(), testCase_01010020()..., 这样在保存截图的时候就可以使用方法名或者方法名的一部分作为图片名,处理起来也比较简单。
[size=1em]在 testXxx() 方法中,有很多如 driver.findElement(By.id ("2-nav-tree-expandable-item")).click(); driver.findElement(By.xpath ("xxxxxxxxxxxxxxxxxxxxxxx")).click(); 的语句,这些语句就是用来查找页面元素的,在用 Selenium WebDriver 的时候,主要挑战就是查找元素,所以了解更多的 WebDriver API 才能更顺利的去实现 Case 的编写。前面已经讨论过,在 TVT 中,重复工作在于截图,所以接下来就要解决截图问题。Selenium WebDriver 已经提供了截图方法,我们只需在需要截图的代码位置,嵌入截图语句。以下方法是将截图功能封装在一个 TVTUtility 的工具类中,如代码清单 2.
清单 2. 截图方法
public static void captureScreen(WebDriver dr, String directory,String captureName, String format) File screenShotFile = ((TakesScreenshot) dr).getScreenshotAs(OutputType.FILE ); try { FileUtils.copyFile (screenShotFile, new File(directory+ captureName + \ format)); } catch (IOException e) { e.printStackTrace(); } }
[size=1em]在需要截图的位置,嵌入 TVTUtility.captureScreen(driver, DIRECTORY, TVTUtility.getMethodName(),FORMAT) 语句,就能完成截图并保存到指定的位置。这里需要注意语句的执行速度一般比 Firefox 的响应速度快,所以有必要在截图之前显示等待一段时间以便页面的完全加载,如 Thread.sleep(1000), 具体的时间要看实际情况而定。
[size=1em]captureScreen() 方法中参数 driver 是一个 Selenium WebDriver 对象,DIRECTORY 是保存图片的位置,TVTUtility.getMethodName() 参数的作用是获取当前的方法名,前面我们讨论过,这个方法的命名最好是有规律和规范的,这样就可以截取其一部分来作为图片保存的名称,比如截取成 01010010,01010020...,FORMAT 参数为图片的格式,如 jpg,gif 等。