jjzjj

java - 重新查找 WebElement 哪个类在单击事件中被删除

coder 2024-03-13 原文

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

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

然后我用 element.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>

最佳答案

在 JAVA 绑定(bind) + Firefox 驱动程序中测试了您的方案。点击remove the 'mystyle' from div 可以得到没有'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="">

  3. 现在点击元素

    元素.点击();

    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 脚本", “参数”:[ { “element-6066-11e4-a52e-4f735466cecf”:“c15725f8-89f9-4fec-af08-be1b9487defe” }, “类(class)” ]

5 响应:

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

得到类的值为 ""。 “.mystyle”不存在

从上面的日志中,一旦使用 Selenium 找到元素并将其分配给“元素”,它就不会再次发送发布请求来查找元素。 c15725f8-89f9-4fec-af08-be1b9487defe 在点击和 getAttribute 中保持不变。 (网络驱动程序协议(protocol))

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

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

关于java - 重新查找 WebElement 哪个类在单击事件中被删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57147306/

有关java - 重新查找 WebElement 哪个类在单击事件中被删除的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  5. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  6. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  7. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  8. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  9. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐