如何消除Webdriver代码中的xpath?

时间:2013-05-20 10:42:40

标签: xpath selenium 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']"));

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

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

2 个答案:

答案 0 :(得分:11)

你应该投资Page Objects,这是一个非常有用的模式:

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

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

//html/body/center/div/div/center/table/tbody/tr/td/form/table/tbody/tr[4]/td/input

所以这意味着测试会破裂。但是,测试不会因为测试的功能被破坏而破坏,因为测试实现被破坏了。你的测试不应该那么脆弱。如果开发人员希望将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>

我希望得到docSpan作为类名的范围。

我可以:

//div/span/span[1]

哪种方法有效,但如果改为:

<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>

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

所以我可以:

//div/span[@class='uploadDetails']/span[text()='.doc']

这意味着,如果我想要的span成为一个班级uploadDetails {{1}的孩子,那么它只会失败} class完全取消了。

或者我可以:

uploadDetails

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

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

答案 1 :(得分:0)

这里再次Y XPath Y不使用CSS

css = .uploadDetails&gt; .docSpan - .doc

css = .uploadDetails&gt; .excelSpan - .xls

css = .uploadDetails&gt; .txtSpan - .txt

简单