在上篇中,大致介绍了PageObjects。其实为了对PageObjects更好的支持,webdriver中还有一个PageFactory 的概念。
There is a PageFactory in the support package that provides support for this pattern, and helps to remove some boiler-plate code from your Page Objects at the same time.
来看下,上篇中的百度搜索例子, 用PageFactory该如何实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.ahchoo.automation.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
public class BaiduIndexPage {
private WebDriver driver;
private final String url = "http://www.baidu.com" ;
public BaiduIndexPage (WebDriver driver) {
this .driver = driver;
driver.get(url);
}
@FindBy (how = How.ID, using = "kw" )
private WebElement searchField;
public SearchResultPage searchFor (String text) {
searchField.sendKeys(text);
searchField.submit();
return new SearchResultPage(driver);
}
}
可以看到这里使用了注释@FindBy, 这是一个注释类,我们来看下它的定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public @interface FindBy {
How how () default How.ID ;
String using () default "" ;
String id () default "" ;
String name () default "" ;
String className () default "" ;
String css () default "" ;
String tagName () default "" ;
String linkText () default "" ;
String partialLinkText () default "" ;
String xpath () default "" ;
}
我们可以知道其实FindBy注释就是实现了driver.findElement(By)
,用FindBy可以从无数findElement方法中解脱出来(如果你页面有很多元素的时候)。
然后要用工厂模式生成BaiduIndexPage对象
在SearchTest.java 里1
2
BaiduIndexPage home = PageFactory.initElements(driver, BaiduIndexPage.class);
将WebDriver实例和BaiduIndexPage.class传给initElements方法,该方法会更具反射生成BaiduIndexPage实例,必须注意的是,使用PageFactory,我们的页面对象必须有 一个带有WebDriver类型参数的构造方法。
This method will attempt to instantiate the class given to it, preferably using a constructor which takes a WebDriver instance as its only argument or falling back on a no-arg constructor.
PageFactory基本需要关注的就是:
1. Findby注释
2. PageFactory.initElements
我们继续改造,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.ahchoo.automation.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
public class BaiduIndexPage {
private WebDriver driver;
private final String url = "http://www.baidu.com" ;
public BaiduIndexPage (WebDriver driver) {
this .driver = driver;
driver.get(url);
PageFactory.initElements(driver, this );
}
@FindBy (how = How.ID, using = "kw" )
private WebElement searchField;
@FindBy (how = How.ID, using = "lg" )
private WebElement logo;
@FindBy (how = How.CLASS_NAME, using = "s_btn" )
private WebElement baidYiXiauButton;
public SearchResultPage searchFor (String text) {
searchField.sendKeys(text);
searchField.submit();
return new SearchResultPage(driver);
}
public boolean idLogoDisplay () {
return logo.isDisplayed();
}
public boolean hasBaidYiXiauButton () {
return baidYiXiauButton.isDisplayed();
}
}
我们将PageFactory.initElements(driver, this);
放在页面类的构造函数里,这样就不需要将PageFactory暴露到TestCase中去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.ahchoo.automation.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
public class SearchResultPage {
private WebDriver driver;
@FindBy (how=How.ID, using="ec_im_container" )
private WebElement adDiv;
public SearchResultPage (WebDriver driver) {
this .driver = driver;
PageFactory.initElements(driver, this );
}
public String getTitle () {
return driver.getTitle();
}
public String getContent () {
return driver.getPageSource();
}
public boolean isAdDivDisplayed () {
return adDiv.isDisplayed();
}
}
下面是测试用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.ahchoo.automation;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.PageFactory;
import com.ahchoo.automation.page.BaiduIndexPage;
import com.ahchoo.automation.page.SearchResultPage;
* Unit test for simple App.
*/
public class SearchTest {
private WebDriver driver;
@Before
public void setUp () {
driver = new FirefoxDriver();
}
@After
public void tearDown () {
driver.close();
}
@Test
public void searchTest () {
BaiduIndexPage home = new BaiduIndexPage(driver);
assertTrue(home.hasBaidYiXiauButton());
assertTrue(home.idLogoDisplay());
SearchResultPage searchResult = home.searchFor("pizza" );
assertTrue(searchResult.isAdDivDisplayed());
assertTrue(searchResult.getTitle().contains("pizza" ));
assertTrue(searchResult.getContent().contains("pizza" ));
}
}
改造完毕,我可以保证这个Testcase能运行的很欢。
######总结 可以看到使用PageFactory可以使页面类代码更加清晰,维护也相对简单许多。如果你也使用PageObjects的话, 不妨试试看。如果你想多了解PageFactory的话,请移步PageFactory , 一定能让你受益匪浅。