[英]Get sub-item's XPath using Selenium - Java
我在第三步中嘗試從菜單中單擊子項時遇到問題..
我登錄
進入一個項目
僅刪除創建的卡我認為問題即將獲得正確的 xpath PAGE
包裝頁面對象;
導入 org.openqa.selenium.By; 導入 org.openqa.selenium.Keys; 導入 org.openqa.selenium.WebDriver; 導入 org.openqa.selenium.WebElement; 導入 org.openqa.selenium.interactions.Actions;
public class Page { protected final WebDriver webDriver;
public Page( final WebDriver driver ) { this.webDriver =driver; } protected WebElement element(By by ) { return webDriver.findElement( by ); } public void pressEnter(){ Actions builder = new Actions(webDriver); builder.sendKeys(Keys.RETURN).perform(); }
}
頁面對象:卡片頁面
package Helpers;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
public class public class CardPage extends PageObject.Page{
By close = By.xpath("//*[@id='ngdialog5']/div[2]/div/div[2]");
By menuCard = By.xpath("html/body/div[1]/div/div/div/div/ui-view/project/div[1]/board/div/div/div/backlog-list/div[2]/div/ul/li/ul/div[1]/card/li/div/div[1]/a[3]");
By container1stCard = By.xpath("html/body/div[1]/div/div/div/div/ui-view/project/div[1]/board/div/div/div/backlog-list/div[2]/div/ul/li/ul/div/card/li/div");
By delete3 = By.xpath("//*[contains(text(), 'delete')]");
By accceptWarning = By.xpath("html/body/div[4]/div/div[10]/button[1]");
By openCard = By.xpath("//*[@id=\"scrollable\"]/div/backlog-list/div[2]/div/ul/li/ul/div/card/li/div");
private Services services;
public CardPage(WebDriver driver) {
super(driver);
}
//SERVICES CARDS
private void closeCard() {
element(close).click();
}
public void delete1stCard(){
WebElement Wcontainer1stCard = element(container1stCard);//Menu
Actions builder = new Actions(super.webDriver);
Actions hoverOverContainer = builder.moveToElement(Wcontainer1stCard);
hoverOverContainer.perform();
Services.waitMilisegundos(1000);
element(menuCard).click();
Services.waitMilisegundos(500);
WebElement deleteBtn = element(delete3);
deleteBtn.click();//Menu Item
Services.waitMilisegundos(1000);
}
public void openCard(){
element(openCard).click();
}
}
頁面對象服務
package Helpers;
import PageObject.*;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class Services {
WebDriver webDriver;
private LandingPage landingPage;
private MainPage mainPage;
private LoginPage loginPage;
private ProjectPage projectPage;
private CardPage cardPage;
String url;
////
public Services(TmpEnvironment environment) {
webDriver = new StartDriver( environment.url ).getWebDriver();
}
public Services() {
webDriver = new StartDriver(TmpEnvironment.STAGING).getWebDriver();
}
///LOGIN SERVICES
public Services login(String email, String passw){
getLandingPage().goToLoginPage();
getLoginPage().writeUserName(email)
.writePassword(passw)
.clickOnLogin();
return this;
}
public Services enterToProject() {
getMainPage().enterToProject();
return this;
}
//PAGES GETTERS
public WebDriver getWebDriver() {
return webDriver;
}
public MainPage getMainPage() {
if (mainPage == null)
mainPage = new MainPage(webDriver);
return mainPage;
}
public LoginPage getLoginPage() {
if (loginPage == null)
loginPage = new LoginPage(webDriver);
return loginPage;
}
public ProjectPage getProjectPage(){
if (projectPage == null)
projectPage = new ProjectPage(webDriver);
return projectPage;
}
public LandingPage getLandingPage() {
if (landingPage == null)
landingPage = new LandingPage(webDriver);
return landingPage;
}
public CardPage getCardPage() {
if (cardPage == null)
cardPage = new CardPage(webDriver);
return cardPage;
}
//CARDS SERVICES
public Services delete1stCard() {
getCardPage().delete1stCard();
return this;
}
public static void waitMilisegundos(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pressEnter(){
Actions builder = new Actions(webDriver);
builder.sendKeys(Keys.RETURN).perform();
}
public void pressEsc(){
Actions builder = new Actions(webDriver);
builder.sendKeys(Keys.ESCAPE).perform();
}
//
public Services goToLoginPage() {
getLandingPage().goToLoginPage();
return this;
}
public enum TmpEnvironment {
DEVELOPMENT( "http://tmp-landing-dev.theamalgama.com/index" ),
STAGING( "https://tmpapp.theamalgama.com" ),
PRODUCTION( "https://tmpapp.com" );
public final String url;
TmpEnvironment( final String url ) {
this.url = url;
}
public String getUrl(){
return url;
}
}
}
測試班
package z_Test;
import Helpers.Services;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import static Helpers.Services.waitMilisegundos;
public class CardTest {
static String email, password;
Services services;
public CardTest(){
services = new Services();
}
@BeforeClass
public static void setData(){
email = "test01@testing.com";
password = "password";
}
@After
public void CloseDriver(){
services.getWebDriver().close();
}
/////////////////////////////////////////////////////////////
@Test
public void cardTest(){
services.login(email,password);
services.enterToProject()
.delete1stCard();
waitMilisegundos();
}
}
接下來是嘗試刪除卡時的錯誤消息。
[org.openqa.selenium.ElementNotVisibleException: 元素不可見
(Session info: chrome=58.0.3029.110) (Driver info: chromedriver=2.30.477691 (6ee44a7247c639c0703f291d320bdf05c1531b57),platform=Linux 4.4.0-786N-generic stack 未提供任何命令或命令棧的持續時間:(6ee44a7247c639c0703f291d320bdf05c1531b57)超時:96 毫秒構建信息:版本:'未知',修訂:'未知',時間:'未知'系統信息:主機:'julieta',ip:'127.0.1.1',os.name:'Linux',os .arch: 'amd64', os.version: '4.4.0-79-generic', java.version: '1.8.0_131' 驅動程序信息:org.openqa.selenium.chrome.ChromeDriver Capabilities [{applicationCacheEnabled=false, rotatable =false, mobileEmulationEnabled=false, networkConnectionEnabled=false, chrome={chromedriverVersion=2.30.477691 (6ee44a7247c639c0703f291d320bdf05c1531b57), userDataDir=/tmp/.org.chromium.LoadStrategy.r handlesAlerts=true,hasTouchScreen=false,version=58.0.3029.110,platform=LINUX,browserConnectionEnabled=false,nativeEvents=true,接受 SslCerts=true、locationContextEnabled=true、webStorageEnabled=true、browserName=chrome、takesScreenshot=true、javascriptEnabled=true、cssSelectorsEnabled=true、unexpectedAlertBehaviour=}] 會話 ID:a33c710a9bae046f731a66bb56b344b8 at sun.newstructorNampleInstance(sun.reflectorN)。 .reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:4openqa.org) selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:215) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:167) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java: 671) 在 org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:272) 在 org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:82) 在 PageObject.Ca rdPage.delete1stCard(CardPage.java:92) at Helpers.Services.delete1stCard(Services.java:201) at z_Test.CardTest.cardTest(CardTest.java:69) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun .reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit。 runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod) .java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 在 org. junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java: 71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner) .java:268) 在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.junit.runner。 JUnitCore.run(JUnitCore.java:137) 在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 在 com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)]
我也嘗試使用不同的 xpath,所以當我運行它時,我得到了另一種例外: org.openqa.selenium.NoSuchElementException: Unable to locate element:
我認為您有許多需要改進的問題。
您使用的是絕對 XPath,這總是不好的做法。 它們極其脆弱。 您應該花一些時間閱讀一些有關手工制作 XPath 的教程。 它們會更短、更容易閱讀,但也不會那么脆弱。
與其使用delete1stCard()
方法, delete1stCard()
創建一個使用deleteCard(int index)
的方法deleteCard(int index)
,以便您可以刪除所需的任何卡片。 您可能需要另一種方法deleteCard(String cardName)
接收卡片名稱並將其刪除。 我認為這可能比按索引刪除更有用,但我不知道您的測試用例是什么樣的。 (或者更好的是,實現一個卡片組件類,正如我在下面建議的那樣,它解決了這個問題。)
您的名為Services
課程似乎是一個包羅萬象的東西。 做一個適當的頁面對象模型並添加一個登錄頁面來處理來自登錄頁面的登錄,一個處理該頁面的項目頁面,等等。 我不知道一旦您將所有內容重新組織為適當的頁面對象后, Services
應該包含哪些內容……我認為您可能不需要它。
我還建議您創建組件頁面對象,例如卡片、某些工具欄。 “頁面對象”不必是整個頁面。 它可以是任何可重用的組件。 您可以使用Services
類中的一些可用功能,並將它們移動到TimerMenu
、 ProjectBar
等TimerMenu
,以表示頁面頂部的不同工具欄及其功能。
你會有一個CardsPage
頁面對象來代表卡片頁面,例如https://tmpapp.theamalgama.com/#/projects/681/cards ,但你也會有一個CardComponent
代表頁面上的實際卡片,這些東西包含在<card>
標簽中。 CardComponent
將包含單個卡片的功能...名稱、該卡片的播放按鈕、該卡片的完成圖標、該卡片的刪除/編輯/等選項等等。
現在到實際答案。 我寫了一個CardComponent
類,正如我建議你寫的那樣。 你傳入卡片的名字,它就會得到它的句柄。 從那里,您只需調用card.delete()
或card.whatever()
在您指定的卡片上完成該操作。 它使處理單個卡片、項目等變得更加容易。 對卡片功能的更新很容易……在CardComponent
頁面對象等中進行更改。
public class CardComponent
{
private WebDriver driver;
private WebElement card;
private By deleteCardLocator = By.xpath(".//p[@class='option-list-option'][.='Delete']");
private By acceptDeleteButtonLocator = By.xpath("//button[.='Accept']");
public CardComponent(WebDriver webDriver, String cardName)
{
driver = webDriver;
card = new WebDriverWait(webDriver, 10)
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//card[contains(., '" + cardName + "')]")));
}
public void delete()
{
openMenu();
card.findElement(deleteCardLocator).click();
driver.findElement(acceptDeleteButtonLocator).click();
}
private void openMenu()
{
new Actions(driver).moveToElement(card).perform();
card.findElement(By.id("dots")).click();
}
}
要使用此代碼,請導航到卡片頁面並調用
CardComponent card = new CardComponent(driver, "card to delete");
card.delete();
我創建了幾張新卡並測試了這段代碼,它可以工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.