对于一些页面非常重要的互联网产品,尤其是工作流(workflow)主要体现在页面的操作和跳转上,这种产品的质量保证和持续集成,可以通过展示层(网页)的自动化测试来完成。当前有较为成熟的基于网页的测试框架:selenium+webdriver+testng+java,当然后面的testng+java,可以由其他各种语言替代,也都有相应的测试框架。
好处有:
1.直观,测试的执行完全是基于页面的,能够直观的验证页面和逻辑。
2.编写难度小,有较为成熟的框架
3.能够迅速检测出产品改动和缺陷
但是,这也带来了相应的副作用,包括:
1.产品的微小改动可能就引起大量的脚本运行失败(如调整了css)
2.每次新上页面,需要做大量新的持续集成工作,增加了测试工作量
3.基于页面的测试代码维护成本较高,代码会写的很难看
好的编程习惯和思想,能够减少上面所述的弊端,即POM,面向页面的编程,尤其适用于测试场景下。
先看脚本一:
public void testBaiduSearch() {
System.setProperty("webdriver.chrome.driver",
"E:/webdriver/chromedriver_win32/chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
driver.get("http://www.baidu.com");
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebElement searchText = driver.findElementById("kw");
searchText.sendKeys("abcd");
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebElement searchBtn = driver.findElementById("su");
searchBtn.click();
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebElement verifyElement = driver
.findElementByXPath("//*[@id='1']/h3/a");
String text = verifyElement.getText();
if (text == null) {
Assert.fail("Get output null.");
}
Assert.assertTrue(text.equals("abcd_百度百科"));
driver.close();
}
这是一个简单的测试百度搜索页面的功能,其中把动作和动作执行的对象,以及执行的逻辑混杂在一起,脚本的维护性很差。
POM,简单来说,是把具体的页面和测试该页面的逻辑进行分离,而页面上的操作,见仁见智,可以放在页面上封装一层,也可在测试代码中定义。
对于另一个相对复杂点的页面,即转换字符的,输入,点击转换,得出结果。
首先定义页面:
public class EncodePage {
static ChromeDriver driver;
public static String URL = "http://tool.oschina.net/encode";
static WebElement nativeText;
static WebElement unicodeBtn;
static WebElement nativeBtn;
static WebElement unicodeText;
static {
System.setProperty("webdriver.chrome.driver",
"E:/webdriver/chromedriver_win32/chromedriver.exe");
driver = new ChromeDriver();
driver.get(URL);
nativeText = driver.findElementById("a_source");
unicodeBtn = driver
.findElementByXPath("//*[@id='mainContent']/div[2]/div[4]/div/button[1]");
nativeBtn = driver
.findElementByXPath("//*[@id='mainContent']/div[2]/div[4]/div/button[2]");
unicodeText = driver.findElementById("a_source");
}
public void clearUnicode() {
unicodeText.clear();
}
public void clearNative() {
nativeText.clear();
}
public void typeIntoNative(String input) {
nativeText.sendKeys(input);
}
public void clickUnicode() {
unicodeBtn.click();
}
public void clickNative() {
nativeBtn.click();
}
public String getUnicodeText() {
return unicodeText.getText();
}
public String getNativeText() {
return nativeText.getText();
}
public static ChromeDriver getDriver() {
return driver;
}
public static void setDriver(ChromeDriver driver) {
EncodePage.driver = driver;
}
}
该类定义一个URL对应的页面上所有在测试中可以用到的元素和相应的操作,当然这个类中对方法定义的粒度较细,对于复杂页面,可以定义更粗粒度的操作,如“翻译一个值”,包含“输入”,“点击”,“获得输出”等多个操作和多个元素。
下面是测试类:
public class OschinaNormalTest {
@Test
public void testNaviteToUnicode() {
EncodePage page = new EncodePage();
page.clearNative();
page.typeIntoNative("aaa");
page.clickUnicode();
String output = page.getUnicodeText();
Assert.assertEquals(output, "aaa");
page.getDriver().close();
}
@Test
public void testUnicodeToNavite() {
EncodePage page = new EncodePage();
page.clearUnicode();
page.typeIntoNative("aa");
page.clickNative();
String result = page.getNativeText();
Assert.assertEquals(result, "aa");
page.getDriver().close();
}
}
测试类中关注测试逻辑,调用页面的方法进行测试,后续用例的可扩展空间较大且灵活;一旦发生页面变更,只要工作流不变,只需调整page类,用例还可以照常回归。