如何消除Webdriver代码中的xpath?

mac*_*mac 0 selenium xpath webdriver selenium-webdriver

我致力于自动化网站,我正试图找到一种方法来减少代码中xpath的使用.我的代码看起来像这样

    driver.findElement(By.xpath("//html/body/center/div/div/center/table/tbody/tr/td/form/table/tbody/tr[3]/td/input")).click();
    driver.findElement(By.xpath("//html/body/div/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td")).getText();
    driver.findElement(By.xpath("//html/body/div/table/tbody/tr/td/div[2]/div/div/div[4]/div/div/div")).click();
    driver.findElement(By.xpath("//html/body/div[3]/div/div/div/div[2]/div/span/ul[2]/li[6]/a")).click();
    /*driver.findElement(By.xpath("//html/body/div/div/div/div[3]/div/div[2]/div[2]/table/tbody/tr/td[3]/table/tbody/tr/td[2]/em/button")).click();
    WebElement editUserForm = driver.findElement(By.cssSelector("iframe[src*='editUserForm']"));
Run Code Online (Sandbox Code Playgroud)

有什么办法可以减少这些xpath,这样我的代码看起来不会破旧吗?这里的一位成员建议我"请不要使用绝对xpath".这是什么意思 ?请帮忙.如果有任何链接可以帮助我,请告诉我.

是否可以创建一个将字符串转换为xpath指针的文件,然后我们可以在代码中使用该字符串?

Arr*_*ran 11

你应该投资页面对象,这是一个非常有用的模式:

https://code.google.com/p/selenium/wiki/PageObjects

它将有助于从实施中分离测试.我的意思是,测试应该留下详细说明采取的步骤,实现("页面对象")应该详细说明如何采取这些步骤.

至于XPath本身,是的,它们非常糟糕且不可靠.我会假设您已经通过某些工具(可能是IDE或Firebug)为您自动生成了它们.请把这些扔掉,不要再使用它并阅读一些XPath教程 - 即使XPath规范也是一个很好的学习场所.

首先,丢掉//html/body它,它是不必要的,并使它看起来更糟.没有它它会很好.

其次,是的,拥有绝对XPath(即基于位置的那些)是不好的.在你的第一个XPath中:

//html/body/center/div/div/center/table/tbody/tr/td/form/table/tbody/tr[3]/td/input
Run Code Online (Sandbox Code Playgroud)

看到最后的tr[3]?如果我要tr在那之前粘上另一行()怎么办?这意味着你的XPath现在应该是:

//html/body/center/div/div/center/table/tbody/tr/td/form/table/tbody/tr[4]/td/input
Run Code Online (Sandbox Code Playgroud)

所以这意味着测试将会中断.但是,测试不会因为测试的功能被破坏而破坏,因为测试实现被破坏了.你的测试不应该那么脆弱.如果一个开发人员想要tr超过你想要的那个,那很好,除非它打破你正在测试的实际内容,那么你的测试仍然应该通过.

你应该以不同的方式思考它.想想获得该元素的其他方法.假设我有这个:

<div id="divUpload">
<span class="uploadDetails">We only support the following files:
    <span class="docSpan">.doc</span>
    <span class="txtSpan">.txt</span>
</span>
<button type="submit">Upload the file<submit>
<div>
Run Code Online (Sandbox Code Playgroud)

我想用docSpan它的类名来获得跨度.

我可以:

//div/span/span[1]
Run Code Online (Sandbox Code Playgroud)

哪个会起作用,但如果它改为:

<div id="divUpload">
<span class="uploadDetails">We only support the following files:
    <span class="excelSpan">.xls</span>
    <span class="docSpan">.doc</span>
    <span class="txtSpan">.txt</span>
</span>
<button type="submit">Upload the file<submit>
<div>
Run Code Online (Sandbox Code Playgroud)

这意味着该[1]位不再有效.

所以,我可以:

//div/span[@class='uploadDetails']/span[text()='.doc']
Run Code Online (Sandbox Code Playgroud)

这意味着,它只会如果失败,span我想取出的是跨度的孩子与类uploadDetails uploadDetails类共带下跨度.

或者我可以:

//div/descendant::span[text()='.doc']
Run Code Online (Sandbox Code Playgroud)

这意味着如果跨度完全移动,它只会失败,并且不再是那个'父'div的孩子.

底线是不依赖职位.想想那个元素附近有什么.课上有什么东西吗?里面有文字吗?附近有ID的东西吗?