他们是否可以通过单独传递对象定位器来找到对象定位器类型。
例如我需要点击登录按钮,其中id=login
,classname=loginbutton
或xpath=//input[@name='login']
。我需要构建方法,我将只传递objectlocator(id或name)作为输入,并且它的类型(id或name)应该在方法中决定,如果它包含//
那么type应该是of xpath等。
我需要传递objectLocator(),它返回findElement()
WebElement element = driver.findElement(objectLocator());
答案 0 :(得分:2)
我认为它不是现成的,你必须实现自己的逻辑。
唯一的问题是,假设你想通过linktext进行搜索。根据您的用例,您可以在对象仓库中指定“这是我的链接文本” 现在你怎么知道它是一个id,一个名字或一个linktext?
对于xpath,您可以检查它是否以/开头,然后是xpath。如果它唯一的id或名称,那么你可以使用ByIdorName,但我认为使用css和linktext会变得棘手。
我能想到的一件事是你可以建立某种约定,比如它是在你的lcoator定义之前的linktext与linktext = blah blah然后你拆分并使用它。
答案 1 :(得分:1)
执行此操作的现代方法是使用PageFactory和PageObjects
以下是一个快速而又脏的方法,它将使selenium定位器字符串适应WebDriver定位器。
public enum LocatorType {
CLASSNAME, CSS, ID, LINK, NAME, TAGNAME, XPATH ;
}
public WebElement objectLocator(LocatorType type, String ref) {
switch(type) {
case ID:
return this.webDriver.findElement(By.id(ref));
case CLASSNAME:
return this.webDriver.findElement(By.className(ref));
case XPATH:
return this.webDriver.findElement(By.xpath(ref));
case CSS:
return this.webDriver.findElement(By.cssSelector(ref));
case LINK:
return this.webDriver.findElement(By.linkText(ref));
case NAME:
return this.webDriver.findElement(By.name(ref));
case TAGNAME:
return this.webDriver.findElement(By.tagName(ref));
}
return null;
}
public WebElement objectLocator(String identifier) {
String typeString = identifier.substring(0, identifier.indexOf('='));
String ref = identifier.substring(identifier.indexOf('=')+1, identifier.length());
if (typeString.toLowerCase().contains("classname")) {
return objectLocator(LocatorType.CLASSNAME, ref);
} else if (typeString.toLowerCase().contains("css")) {
return objectLocator(LocatorType.CSS, ref);
} else if (typeString.toLowerCase().contains("id")) {
return objectLocator(LocatorType.ID, ref);
} else if (typeString.toLowerCase().contains("link")) {
return objectLocator(LocatorType.LINK, ref);
} else if (typeString.toLowerCase().contains("name")) {
return objectLocator(LocatorType.NAME, ref);
} else if (typeString.toLowerCase().contains("tagname")) {
return objectLocator(LocatorType.TAGNAME, ref);
} else if (typeString.toLowerCase().contains("xpath")) {
return objectLocator(LocatorType.XPATH, ref);
} else {
return null;
}
}
答案 2 :(得分:1)
我发现将所有定位器存储为By对象非常有用,可以直接使用By,也可以根据需要将By传递给方法。例如:
By passwordField= By.id("login");
By userNameField = By.name("username");
By submitButton = By.xpath("\\myxpath\div[2]");
public void clickLogin() {
driver.findElement(submitButton).click();
}
我也使用其他类的静态Bys:
public void clickLogin() {
driver.findElement(LoginPage.SUBMIT_BUTTON).click();
}
答案 3 :(得分:0)
看起来您正在寻找此解决方案,因为您在某些属性文件或xml中的代码之外的某个位置维护了对象存储库。
Using gui maps has lot of disadvantages like,
- maintain an external file with a list of locators
- parse locator files to read keys (you can abstract this but still an overhead)
- when writing PageObjects you need to switch back and forth from Page to gui map
- possibility of multiple duplicate locators in gui maps
- object repo grows over time and becomes impossible to maintain
- debugging is far more difficult
您正在寻找的是增加一层复杂性,这在我看来并不是必需的。自动化浏览器本身就是一项挑战,编写可维护的测试自动化代码至关重要。
在页面对象中使用PageFactory。
- Natural place for your locators are Page Objects themselves.
- Locators easily accessible in page objects for review or correction
- No need for explicit driver.findElement, with @FindBy you get that for free
- modern Java and awesome annotations make page objects look beautiful & readable
我之前使用过gui地图并且经常苦苦挣扎。切换到页面工厂让我意识到使用对象存储库是一个糟糕的主意!
答案 4 :(得分:0)
这应该用于定位元素。我已经举了三层深的例子。
public WebElement findElement(String locator){
WebElement w = null;
try{
return (driver.findElement(By.id(locator)));
}catch(Exception e1){
try{
return ( driver.findElement(By.name(locator)));
}catch(Exception e2){
try{
return (driver.findElement(By.xpath(locator)));
}catch(Exception e3){
System.out.println("Cound not find a locator");
e3.printStackTrace();
}
}
}
return(w);
}
public void type(String locator, String value){
try{
WebElement w= findElement(locator);
w.sendKeys(""+value);
Thread.sleep(sleepTime);
}catch(Exception e){
e.printStackTrace();
}
}
-Vinay