@FindBy(xpath="//button[@class='submitButton']")
WebElement submit;
我已经在使用POM的测试框架中使用了这类代码。
我想将此Xpath存储在属性文件中,并且只想为其分配密钥。
例如:
@FindBy(xpath=config.getsubmit())
WebElement submit;
有什么方法可以存储WebElement或建立WebElement存储库吗?
答案 0 :(得分:1)
您不能使用PageObjects和PageFactory的普通香草味来做到这一点。
您需要进行一些自定义,之后才能完成此操作。
要完成此操作,您基本上需要以下内容
org.openqa.selenium.support.pagefactory.ElementLocator
的自定义实现,以便您可以使用提供的findElement
实例来兑现对findElements
和WebDriver
的调用。默认实现只是从注释中查询。org.openqa.selenium.support.pagefactory.ElementLocatorFactory
的自定义实现,以便它可以生成自定义的ElementLocator
实例,而不是默认实例。WebElement
来解析已添加到org.openqa.selenium.support.pagefactory.AbstractAnnotations
对象的自定义注释有了这些,您可以执行以下操作
By
对象ElementLocator
,使其使用自定义注释解析器查找元素。ElementLocatorFactory
,以使其生成自定义ElementLocator
的实例。我有时把整个概念写成博客。请看看here
要全面了解PageFactory的工作原理,请查看我创建的this博客。
有人以我的博客文章为起点,并建立了一个图书馆,可以为您完成所有这些工作。您可以从这里https://github.com/shchukax/search-with
消费它为了完整起见,我包括了博客中的所有代码段
json看起来像这样
[
{
"pageName": "HomePage",
"name": "abTesting",
"locateUsing": "xpath",
"locator": "//a[contains(@href,'abtest')]"
},
{
"pageName": "HomePage",
"name": "checkBox",
"locateUsing": "xpath",
"locator": "//a[contains(@href,'checkboxes')]"
},
{
"pageName": "CheckboxPage",
"name": "checkBox1",
"locateUsing": "xpath",
"locator": "//input[@type='checkbox'][1]"
},
{
"pageName": "CheckboxPage",
"name": "checkBox2",
"locateUsing": "xpath",
"locator": "//input[@type='checkbox'][2]"
}
]
自定义注释看起来像这样
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.FIELD)
public @interface SearchWith {
String inPage() default "";
String locatorsFile() default "";
String name() default "";
}
自定义ElementLocator
实现
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.pagefactory.AbstractAnnotations;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import java.util.List;
public class FileBasedElementLocator implements ElementLocator {
private final SearchContext searchContext;
private final boolean shouldCache;
private final By by;
private WebElement cachedElement;
private List<WebElement> cachedElementList;
public FileBasedElementLocator(SearchContext searchContext, AbstractAnnotations annotations) {
this.searchContext = searchContext;
this.shouldCache = annotations.isLookupCached();
this.by = annotations.buildBy();
}
@Override
public WebElement findElement() {
if (cachedElement != null && shouldCache) {
return cachedElement;
}
WebElement element = searchContext.findElement(by);
if (shouldCache) {
cachedElement = element;
}
return element;
}
@Override
public List<WebElement> findElements() {
if (cachedElementList != null && shouldCache) {
return cachedElementList;
}
List<WebElement> elements = searchContext.findElements(by);
if (shouldCache) {
cachedElementList = elements;
}
return elements;
}
}
自定义元素定位器工厂如下所示
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import java.lang.reflect.Field;
public class FileBasedElementLocatorFactory implements ElementLocatorFactory {
private final SearchContext searchContext;
public FileBasedElementLocatorFactory(SearchContext searchContext) {
this.searchContext = searchContext;
}
@Override
public ElementLocator createLocator(Field field) {
return new FileBasedElementLocator(searchContext, new CustomAnnotations(field));
}
}
AbstractAnnotations
的自定义实现
import com.google.common.base.Preconditions;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.openqa.selenium.By;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.pagefactory.AbstractAnnotations;
import organized.chaos.annotations.SearchWith;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.util.Iterator;
class CustomAnnotations extends AbstractAnnotations {
private final Field field;
CustomAnnotations(Field field) {
this.field = field;
}
@Override
public By buildBy() {
SearchWith search = field.getAnnotation(SearchWith.class);
Preconditions.checkArgument(search != null, "Failed to locate the annotation @SearchWith");
String elementName = search.name();
String pageName = search.inPage();
String locatorsFile = search.locatorsFile();
Preconditions
.checkArgument(isNotNullAndEmpty(elementName), "Element name is not found.");
Preconditions.checkArgument(isNotNullAndEmpty(pageName), "Page name is missing.");
Preconditions.checkArgument(isNotNullAndEmpty(locatorsFile), "Locators File name not provided");
File file = new File(locatorsFile);
Preconditions.checkArgument(file.exists(), "Unable to locate " + locatorsFile);
try {
JsonArray array = new JsonParser().parse(new FileReader(file)).getAsJsonArray();
Iterator&lt;JsonElement&gt; iterator = array.iterator();
JsonObject foundObject = null;
while (iterator.hasNext()) {
JsonObject object = iterator.next().getAsJsonObject();
if (pageName.equalsIgnoreCase(object.get("pageName").getAsString()) &&
elementName.equalsIgnoreCase(object.get("name").getAsString())) {
foundObject = object;
break;
}
}
Preconditions.checkState(foundObject != null, "No entry found for the page [" + pageName + "] in the "
+ "locators file [" + locatorsFile + "]");
String locateUsing = foundObject.get("locateUsing").getAsString();
if (! ("xpath".equalsIgnoreCase(locateUsing))) {
throw new UnsupportedOperationException("Currently " + locateUsing + " is NOT supported. Only xPaths "
+ "are supported");
}
String locator = foundObject.get("locator").getAsString();
Preconditions.checkArgument(isNotNullAndEmpty(locator), "Locator cannot be null (or) empty.");
return new By.ByXPath(locator);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isLookupCached() {
return (field.getAnnotation(CacheLookup.class) != null);
}
private boolean isNotNullAndEmpty(String arg) {
return ((arg != null) && (! arg.trim().isEmpty()));
}
}
这是页面对象类的外观
import org.openqa.selenium.WebElement;
import organized.chaos.annotations.SearchWith;
public class HomePage {
public static final String PAGE = "HomePage";
@SearchWith (inPage = HomePage.PAGE, locatorsFile = "src/main/resources/locators.json", name = "abTesting")
private WebElement abTestingLink = null;
@SearchWith (inPage = HomePage.PAGE, locatorsFile = "src/main/resources/locators.json", name = "checkBox")
private WebElement checkBoxLink = null;
public HomePage() {
}
public CheckBoxPage navigateToCheckBoxPage() {
checkBoxLink.click();
return new CheckBoxPage();
}
}
另一个页面类
import org.openqa.selenium.WebElement;
import organized.chaos.annotations.SearchWith;
public class CheckBoxPage {
private static final String PAGE = "CheckBoxPage";
@SearchWith (inPage = CheckBoxPage.PAGE, locatorsFile = "src/main/resources/locators.json", name = "checkBox1")
private WebElement checkBoxOne;
@SearchWith (inPage = CheckBoxPage.PAGE, locatorsFile = "src/main/resources/locators.json", name = "checkBox2")
private WebElement checkBoxTwo;
public void unCheckCheckBoxTwo() {
if (checkBoxTwo.isSelected()) {
checkBoxTwo.click();
}
}
public boolean isCheckBoxTwoUnchecked() {
return (! checkBoxTwo.isSelected());
}
}
这是一个使用这个的测试类
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import organized.chaos.pages.CheckBoxPage;
import organized.chaos.pages.HomePage;
import organized.chaos.support.FileBasedElementLocatorFactory;
public class AlteredPageFactoryDemo {
private RemoteWebDriver driver;
@BeforeClass
public void setup() {
driver = new ChromeDriver();
}
@AfterClass
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
@Test
public void testMethod() {
driver.get("https://the-internet.herokuapp.com/");
HomePage homePage = new HomePage();
ElementLocatorFactory factory = new FileBasedElementLocatorFactory(driver);
PageFactory.initElements(factory, homePage);
CheckBoxPage checkboxPage = homePage.navigateToCheckBoxPage();
PageFactory.initElements(factory, checkboxPage);
checkboxPage.unCheckCheckBoxTwo();
Assert.assertTrue(checkboxPage.isCheckBoxTwoUnchecked());
}
}
答案 1 :(得分:0)
您不能将值传递给在运行时确定的注释,仅允许使用诸如final字段或类型之类的常量。有关详情,请参见the spec。这是因为注释是在编译时评估的。它们的值可能保留在类文件中。
尽管您可以find elements programmatically:
WebElement element = driver.findElement(By.xpath(config.getsubmit()));
但是,这需要您引用WebDriver实例。
答案 2 :(得分:0)
Vicky,
您可以通过使用POJO模型创建来创建WebElement存储库。
Public class WebElementRepo
{
static WebElement01 = null;
// then create getter setter for all these webelements
public static void setWebElement01(WebElement WE)
{
WebElement01 = WE;
}
public static WebElement getWebElement01(WebElement WE)
{
return WebElement01;
}
}
当您需要将Web元素保存到资源库时,只需将webelement传递给WebElementRepo.setWebElement()并使用WebElementRepo.getWebElement()即可检索该webelement。
答案 3 :(得分:-1)
@FindBy
接受final
字符串
static final String xpath;
xpath=config.getsubmit();
@FindBy(xpath)
WebElement submit;