尝试个人翻译selenium官方的测试设计模式篇,由于本人个人能力有限,翻译内容没有进行校对,还有很多晦涩难懂的地方,部分地方翻译出来强加了个人理解,所以本文仅供个人学习参考,文末有对应文档的官网链接可供参考。
- 封装selenium接口
与任何编程一样,您需要使用工具函数来处理在测试代码中重复的代码。防止这种情况的一种方法是将经常使用的selenium方法调用与自己设计的函数或类方法进行封装。例如,测试时会频繁地点击页面上的元素并等待页面加载。
selenium.click(elementLocator);
selenium.waitForPageToLoad(waitPeriod);
为不重复上述代码,你可以编写方法封装这两个功能。
/**
* Clicks and Waits for page to load.
*
* param elementLocator
* param waitPeriod
*/
public void clickAndWait(String elementLocator, String waitPeriod) {
selenium.click(elementLocator);
selenium.waitForPageToLoad(waitPeriod);
}
- 判断元素是否存在的“安全操作”
封装Selenium方法的另一个常见做法是在执行某些操作之前检查页面上是否存在元素。这有时被称为“安全操作”。例如,下面的方法可用于实现一个依赖期望元素存在的安全操作
/**
* Selenum-RC -- Clicks on an element only if it is available on a page.
*
* param elementLocator
*/
public void safeClick(String elementLocator) {
if(selenium.isElementPresent(elementLocator)) {
selenium.click(elementLocator);
} else {
// Using the TestNG API for logging
Reporter.log("Element: " + elementLocator + ", is not available on a page - "
+selenium.getLocation());
}
}
这个例子使用Selenium 1 API,但Selenium 2也支持这个。
/**
* Selenium-WebDriver -- Clicks on an element only if it is available on a page.
*
* param elementLocator
*/
public void safeClick(String elementLocator) {
WebElement webElement = getDriver().findElement(By.XXXX(elementLocator));
if(webElement != null) {
selenium.click(webElement);
} else {
// Using the TestNG API for logging
Reporter.log("Element: " + elementLocator + ", is not available on a page - "
+ getDriver().getUrl());
}
}
在这第二个例子中,'XXXX'只是定位方法之一的占位符,
如它可以代表ID,name等。
是否使用安全操作取决于测试开发人员的决定。因此,即使在页面上缺少元素的情况下,要继续执行测试,可以使用安全操作,并将消息发布到关于缺少元素的日志中。这基本上是通过报告机制实现“验证”,而不是异常声明。但是,如果一个元素必须在页面上出现才能执行进一步的操作(例如,门户主页上的登录按钮),
则应该直接报错终止而不是继续执行。
- 用户界面映射
用户界面(UI)映射是一种机制,它将测试套件的所有定位器存储在一个地方,以便在被测试应用程序(AUT)中UI元素的标识符或路径发生更改时能轻松进行修改。测试脚本使用UI 映射方式来定位被测试元素。基本上,UI映射是封装了被测应用的UI元素的对象库。
UI映射有什么用?它的主要目的是使测试脚本管理更容易。当需要编辑定位器时,有一个集中的文件可以轻松找到该对象,而不必搜索测试脚本代码。此外,它能在该文件统一更改标识符,而不必在测试脚本中的多个地方或在多个测试脚本中进行更改。
总而言之,UI图有两个显着的优点
- 将UI对象放在集中的位置,而不是将它们分散在整个脚本中。提高测试脚本可维护性。
- 用自定义别名的方式替代HTML标识符和专业名称,提高测试脚本可读性。
思考下面让人理解困难的例子( Java中)。
public void testNew() throws Exception {
selenium.open("http://www.test.com");
selenium.type("loginForm:tbUsername", "xxxxxxxx");
selenium.click("loginForm:btnLogin");
selenium.click("adminHomeForm:_activitynew");
selenium.waitForPageToLoad("30000");
selenium.click("addEditEventForm:_IDcancel");
selenium.waitForPageToLoad("30000");
selenium.click("adminHomeForm:_activityold");
selenium.waitForPageToLoad("30000");
}
对于那些不熟悉AUT页面源代码的人来说,这个脚本很难理解。即使应用程序的常规用户可能也难以理解该脚本的功能。更好的脚本可以是:
public void testNew() throws Exception {
selenium.open("http://www.test.com");
selenium.type(admin.username, "xxxxxxxx");
selenium.click(admin.loginbutton);
selenium.click(admin.events.createnewevent);
selenium.waitForPageToLoad("30000");
selenium.click(admin.events.cancel);
selenium.waitForPageToLoad("30000");
selenium.click(admin.events.viewoldevents);
selenium.waitForPageToLoad("30000");
}
现在,使用一些注释和空白以及UI Map标识符可以创建一个非常易读的脚本。
public void testNew() throws Exception {
// Open app url.
selenium.open("http://www.test.com");
// Provide admin username.
selenium.type(admin.username, "xxxxxxxx");
// Click on Login button.
selenium.click(admin.loginbutton);
// Click on Create New Event button.
selenium.click(admin.events.createnewevent);
selenium.waitForPageToLoad("30000");
// Click on Cancel button.
selenium.click(admin.events.cancel);
selenium.waitForPageToLoad("30000");
// Click on View Old Events button.
selenium.click(admin.events.viewoldevents);
selenium.waitForPageToLoad("30000");
}
UI Map有多种实现方式。人们可以创建一个类或结构,它只存放每个定位符(如ID、name)的公共字符串变量。或者,可以使用存储键值对的文本文件。在Java中,包含键/值对的属性文件可能是最好的方法。
考虑一个属性文件prop.properties,它为前面例子中的UI元素赋予“别名”是标识符便于读者理解。
admin.username = loginForm:tbUsername
admin.loginbutton = loginForm:btnLogin
admin.events.createnewevent = adminHomeForm:_activitynew
admin.events.cancel = addEditEventForm:_IDcancel
admin.events.viewoldevents = adminHomeForm:_activityold
定位器仍将引用HTML对象,但我们在测试脚本和UI元素之间引入了抽象层。从文件参数读取值并在测试类中使用以实现UI映射。有关Java属性文件的更多信息,请参阅以下
链接。
原文地址:测试设计注意事项
上一节:
下一节: