看selenium的网站的文档,里面的自动化用例设计有一些小点很靠谱。学了很多,可以用作优化自己的代码。

1.测试类型:

Testing Static Content

Testing Links

Function Tests

Testing Dynamic Elements

Ajax Tests

Assert vs. Verify

  assert 和verify的区别:assert如果wrong,就会停止执行后面的内容;verify如果wrong,会记录下来,然后继续执行后面的内容。

Choosing a Location Strategy

  1.id和name是最高效速度最快的;

  2.xpath是万能的

Wrapping Selenium Calls

包装一下selenium的方法,减少代码冗余

---click方法

  原来的代码:  

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-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());
}
}

  

 

‘Safe Operations’ for Element Presence

/**
* 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());
}
}

  

User Interface Mapping

To summarize, a UI Map has two significant advantages

  • Using a centralized location for UI objects instead of having them scattered throughout the script. This makes script maintenance more efficient.
  • Cryptic HTML Identifiers and names can be given more human-readable names improving the readability of test scripts.
  • 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");
    }

      优化为

  • 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");
    }

      和properties

  • admin.username = loginForm:tbUsername
    admin.loginbutton = loginForm:btnLogin
    admin.events.createnewevent = adminHomeForm:_activitynew
    admin.events.cancel = addEditEventForm:_IDcancel
    admin.events.viewoldevents = adminHomeForm:_activityold

      ↑ 这种方法,一般在java中的实现,我看到的,都是用class,不是用prop.properties

Page Object Design Pattern

The Page Object Design Pattern provides the following advantages

1. 分离测试代码和页面代码,比如定位和布局;

2. 把页面的服务或者操作存在一个简单的仓库里面,而不是散乱的在测试用例中;

We encourage the reader who wishes to know more to search the internet for blogs on this subject.

之前其实在一些讨论里面看到过page object设计模式,不过具体实现的话,以前曾经做过登录页面的一点点,没有全部页面应用。感觉可以优化一下现有代码。

优化前的实现:

/***
* Tests login feature
*/
public class Login { public void testLogin() {
selenium.type("inputBox", "testUser");
selenium.type("password", "my supersecret password");
selenium.click("sign-in");
selenium.waitForPageToLoad("PageWaitPeriod");
Assert.assertTrue(selenium.isElementPresent("compose button"),
"Login was unsuccessful");
}
}

  

There are two problems with this approach.

  1. There is no separation between the test method and the AUT’s locators (IDs in this example); both are intertwined in a single method. If the AUT’s UI changes its identifiers, layout, or how a login is input and processed, the test itself must change.
  2. The ID-locators would be spread in multiple tests, in all tests that had to use this login page.

e.g

优化后的代码:将page变成对象,操作是属于该page的

/**
* Page Object encapsulates the Sign-in page.
*/
public class SignInPage { private Selenium selenium; public SignInPage(Selenium selenium) {
this.selenium = selenium;
if(!selenium.getTitle().equals("Sign in page")) {
throw new IllegalStateException("This is not sign in page, current page is: "
+selenium.getLocation());
}
} /**
* Login as valid user
*
* @param userName
* @param password
* @return HomePage object
*/
public HomePage loginValidUser(String userName, String password) {
selenium.type("usernamefield", userName);
selenium.type("passwordfield", password);
selenium.click("sign-in");
selenium.waitForPageToLoad("waitPeriod"); return new HomePage(selenium);
}
}

  

/**
* Page Object encapsulates the Home Page
*/
public class HomePage { private Selenium selenium; public HomePage(Selenium selenium) {
if (!selenium.getTitle().equals("Home Page of logged in user")) {
throw new IllegalStateException("This is not Home Page of logged in user, current page" +
"is: " +selenium.getLocation());
}
} public HomePage manageProfile() {
// Page encapsulation to manage profile functionality
return new HomePage(selenium);
} /*More methods offering the services represented by Home Page
of Logged User. These methods in turn might return more Page Objects
for example click on Compose mail button could return ComposeMail class object*/ }

  用例:

/***
* Tests login feature
*/
public class TestLogin { public void testLogin() {
SignInPage signInPage = new SignInPage(selenium);
HomePage homePage = signInPage.loginValidUser("userName", "password");
Assert.assertTrue(selenium.isElementPresent("compose button"),
"Login was unsuccessful");
}
}

  

上面的代码应该是seleniumRC?不是最新的selenium3.0的实现。

a few basic rules:

  1.Page objects themselves should never make verifications or assertions.

  页面对象不做校验和断言。校验和断言属于测试用例,必须在测试代码中实现,而不是在页面对象中。页面对象只包含页面表达, 和服务于页面的方法,和要测试的代码无关。

  2.There is one, single, verification which can, and should, be within the page object and that is to verify that the page, and possibly critical elements on the page, were loaded correctly.

  有唯一的能被正确定位的页面元素,在页面对象中,可以用来验证这个页面。

这里介绍的方法其实不是很懂,需要多看下其他的介绍。

Data Driven Testing

  数据驱动,用相同的用例,不同的数据来跑多条数据;

  e.g 原来的代码

     @Test( priority=2)
public void testGameCard(){
Verify.verifyCard("我的游戏","更多游戏","积分游戏");
} @Test( priority=3)
public void testLoginCard(){
Verify.verifyCard("登录轨迹","查看更多","用户登录轨迹");
}
@Test( priority=4)
public void testLotteryCard(){
Verify.verifyCard("我的彩票","积分换彩票","玩游戏赢好礼");
}

  优化为(代码细节有变更,所以和上面的test方法体有差别)

@DataProvider(name="serviceLogin")
public Object[][] service2Detail(){
return new Object[][]{
{"我的游戏","积分游戏"},
{"登录轨迹","用户登录轨迹"},
{"我的彩票","玩游戏赢好礼"},
{"万里通积分","积分团购"},
{"预约挂号", "平安好医生"},
{"生活缴费","生活缴费"},
{"我的资产","一账通账户资产查询"},
{"问律师","闪电律师"},
{"手机维修","极客修"},
{"家电服务","十分到家"},
};
}
@Test(dataProvider="serviceLogin")
public void testService2(String serviceName,String clickName,String resultTitle){
if(!isLogin){
list.login("test1998","qwr1234");
isLogin=list.isLogin();
}
check(serviceName,resultTitle);
}

  

最新文章

  1. JQuery的ajax
  2. php fastcgi_finish_request让你的程序由等待时间,瞬间完成,提高用户体验
  3. Q promise的使用
  4. BZOJ4000 [TJOI2015]棋盘
  5. Java 8怎么了:局部套用vs闭包
  6. jquery radio 取值 取消选中 赋值
  7. 百度劫持js代码
  8. IOS开发环境更换后重新制作Provisioning Profile证书详解
  9. TP-Link WR842N VPN错误619 不能建立到远程计算机的连接
  10. Angular - - ngIf、ngSwitch、ngHide/ngShow
  11. websocket多线程问题
  12. FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换
  13. @Cacheable的实现原理
  14. puppet一些常用的参数
  15. redis在centos7下安装
  16. android 多模块项目构建一
  17. luasocket 安装记录 (FS1.4)
  18. 总结Java虚拟机内存区域模型
  19. C语言递归函数讲解
  20. 枚举类型---java基础代码

热门文章

  1. WEB测试重点--(转载)
  2. Eclipse报错:An internal error has occurred. Widget is disposed
  3. Python——进程通信之间数据共享
  4. python之旅4[第四篇]
  5. springMVC整理01--搭建普通的工程
  6. CetenOS 6.9 搭建hubot运维机器人
  7. 【BZOJ4033】【HAOI2015】树上染色 树形DP
  8. scrapy 发送post请求
  9. QML 用QSortFilterProxyModel实现搜索功能
  10. 自写juqery插件实现左右循环滚动效果图