8

我有一个带有 class 的元素a。所以,在 Selenium 代码中,我得到了这个:

WebElement element = driver.findElement(By.cssSelector(".a"));

之后我点击它element.click();。click 事件a从元素中删除类——这正是我要执行的测试用例。

所以,现在我想问元素是否已经拥有这个类:

element.getAttribute("class").contains("a");

但这不起作用,因为WebElement尝试通过给定的选择器再次找到元素,这对我来说并不清楚。我认为一旦找到 WebElement,就会在整个范围内进行内部复制。但显然,每次在代码中调用它时,它都会调用链接选择器。

那么,我怎样才能更持久地检索元素呢?如何避免WebElement在每次调用时刷新以跟踪已选择元素的更改?

当然,我可以使用 DOM、父母或列表 ID 来解决问题。但是我真的很想避免这种情况,因为我不想在我的测试代码中获得太多关于 DOM 结构的信息。这就是我添加类和 ID 的原因。


编辑:添加日志输出:

WebElement element = driver.findElement(By.cssSelector(".a"));

1564042692783   webdriver::server   DEBUG   -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042692787   Marionette  TRACE   0 -> [0,10,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042692793   Marionette  TRACE   0 <- [1,10,null,[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a","ELEMENT":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]]
1564042692794   webdriver::server   DEBUG   <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]}

如您所见,接收到的元素是517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a.

element.click();

1564042703055   webdriver::server   DEBUG   -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042703058   Marionette  TRACE   0 -> [0,11,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042703065   Marionette  TRACE   0 <- [1,11,null,[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a","ELEMENT":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]]
1564042703066   webdriver::server   DEBUG   <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]}
1564042703142   webdriver::server   DEBUG   -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/element/517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a/click {"id":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}
1564042703145   Marionette  TRACE   0 -> [0,12,"WebDriver:ElementClick",{"id":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]
1564042703380   Marionette  DEBUG   Canceled page load listener because no navigation has been detected
1564042703382   Marionette  TRACE   0 <- [1,12,null,{}]
1564042703384   webdriver::server   DEBUG   <- 200 OK {"value":null}

现在检查:

element.getAttribute("class");

1564042714064   webdriver::server   DEBUG   -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042714067   Marionette  TRACE   0 -> [0,13,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042714070   Marionette  TRACE   0 <- [1,13,null,[]]
1564042714071   webdriver::server   DEBUG   <- 200 OK {"value":[]}

如您所见,现在没有返回任何元素。


编辑:在评估@RahulL 的解决方案之后(这似乎有效;在单击执行时没有记录进一步的WebDriver:FindElements调用 - 与我的日志相反)我相信问题出在包装我的 Selenium 的Aquillian Graphene实现中。该findElement()调用不直接调用 Selenium 类。这就是我添加这些标签的原因。它可能与发现问题有关。

所以,类定义:

import static org.junit.Assert.assertFalse;

import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

@RunWith(Arquillian.class)
@RunAsClient
public class MyTests {

    @Drone
    WebDriver driver;

    @Test
    public void test_removeClassFromElement() {
        driver.navigate().refresh();
        driver.get("my.application");

        WebElement element = driver.findElement(By.className("a"))
        element.click();

        assertFalse(
            element .getAttribute("class").contains("a")
        );
    }
}

arquillian.xml

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/schema/arquillian
        http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

    <extension qualifier="webdriver">
        <property name="browser">firefox</property>
        <property name="firefoxLogLevel">FINEST</property>
    </extension>

</arquillian>
4

1 回答 1

4

在 JAVA binding + Firefox driver 中测试了您的场景。单击从 div 中删除 'mystyle' 并能够获取没有 'mystyle' 的属性类

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.mystyle {
  width: 100%;
  padding: 25px;
  background-color: coral;
  color: white;
  font-size: 25px;
  box-sizing: border-box;
}
</style>
</head>
<body>

<p>Click the "Try it" button to toggle between adding and removing the "mystyle" class name of the DIV element:</p>



<div id="myDIV" onclick="myFunction()" class="mystyle">
This is a DIV element.

</div>

<script>
function myFunction() {
   var element = document.getElementById("myDIV");
   element.classList.remove("mystyle");
}
</script>

</body>
</html>

JAVA代码:

         WebElement element = driver.findElement(By.className("mystyle"));
         element.click();
         System.out.println(element.getAttribute("class"));

启用 FirefoxDriverLogLevel.TRACE 。WebDriver 日志

  1. 查找元素

    WebElement element = driver.findElement(By.className("mystyle"));

    webdriver::server   DEBUG   -> POST /session/81662ee0-1195-4ff3-8687-667f3607ea89/element {
      "value": ".mystyle",
      "using": "css selector"
    }
    
  2. 得到元素

    webdriver::server DEBUG <- 200 OK {"value":{"element-6066-11e4-a52e-4f735466cecf":"c15725f8-89f9-4fec-af08-be1b9487defe"}}

  3. 现在点击元素

    元素.click();

    webdriver::server   DEBUG   -> POST /session/81662ee0-1195-4ff3-8687-667f3607ea89/element/c15725f8-89f9-4fec-af08-be1b9487defe/click {
      "id": "c15725f8-89f9-4fec-af08-be1b9487defe" }
    
  4. 现在发送'getAttribute'

    element.getAttribute("类")

    webdriver::server DEBUG -> POST /session/81662ee0-1195-4ff3-8687-667f3607ea89/execute/sync { "script": "这里 selenium 发送 getAttribute 脚本", "args": [ { "element-6066-11e4 -a52e-4f735466cecf”:“c15725f8-89f9-4fec-af08-be1b9487defe”},“类”]}

5 回应:

webdriver::server   DEBUG   <- 200 OK {"value":""}

将 class 的值设为 "" 。“.mystyle”不存在

从上面的日志中,一旦使用 selenium 找到元素并分配给“元素”,它就不会再次发送 post 请求来查找元素。c15725f8-89f9-4fec-af08-be1b9487defe 在单击和 getAttribute 中保持不变。(Webdriver 协议)

如果您在 JAVA 绑定中使用 @FindBy 注释,那么 Selenium 将尝试在使用代理的每个操作上一次又一次地查找元素。这将在大多数情况下避免 staleelemnt 异常。

为了避免不稳定并更持久地检索元素,您将需要使用不会更改的属性。

于 2019-07-25T05:58:18.103 回答