当前位置: 首页 > 知识库问答 >
问题:

为selenium测试设计页面对象结构。从WebElement继承导致问题

吕霄
2023-03-14

我试图设计一些页面对象,并与整体设计有一些问题。

我知道测试中的一个常见问题是确定元素是否存在,解决方案是使用try/catch或使用findElements(…)如果结果列表的大小为0,则断言。

我想在所有测试中避免这些尝试/陷阱。是否可以使用继承将try/catch放在一个超类中,从而使测试更干净?我希望该方法返回null,如果元素不存在,那么我可以只assertNotNull(…)在测试中。

以下是我当前解决方案中页面对象的一个方法:

public WebElement getRegisterLink(){
    List<WebElement> list = driver.findElements(By.linktext("Register"));
    if(list.size() == 0){
        return null;
    }
        return list.get(0);
}

问题是有很多类似的重复代码。我的getLoginButton()、getSomePageLink()等看起来都一样。

这是我的一个想法。。。

public abstract class MyCompanyElement implements WebElement{

WebElement element;

public MyCompanyElement(WebElement element){
    this.element = element;
}

@Override
public void clear() {
    element.clear();
}

@Override
public void click() {
    element.click();
}

@Override
public MyCompanyElement findElement(By arg0) {      
    try{
        MyCompanyElement e = (MyCompanyElement) element.findElement(arg0);
        return e;
    } catch (NoSuchElementException ex){
        return null;
    }

}

@Override
public List<MyCompanyElement> findElements(By arg0) {       
    List<MyCompanyElement> list = new ArrayList<MyCompanyElement>();
    for(WebElement e : element.findElements(arg0)){
        list.add((MyCompanyElement) e);
    }
    return list;
}

//Rest of the methods here which just call the methods of element
}

然后我有一个BasePage类,所有页面对象都将扩展它。

public abstract class BasePage {

MyCompanyElement element;

public BasePage(WebDriver driver){
    element = (MyCompanyElement) driver.findElement(By.tagName("html"));        
}

//More methods here

}

然后,页面对象有一些方法,如getLoginButton()、getCrysterLink()等,它们返回MyCompanyElement而不是WebElement。(主页包含所有网页上的元素,如页眉和页脚)。

然后,我的测试可能会如下所示:

Homepage homepage = new Homepage(driver);
homepage.getLoginButton().click();

如果我想检查元素是否存在,那么。。。

assertNotNull(homepage.getRegisterLink());

上述解决方案的问题是:

  • 在MyCompanyElement中,findElement()可以返回MyCompanyElement。但是编译器不喜欢我在findElements()中返回MyCompanyElement的列表。有解决办法吗

谢谢

共有1个答案

宣弘新
2023-03-14

我觉得你有点过分了。您不需要创建自己版本的WebElement

您应该做的是,将一个方法放入接受给定By的基类中,例如:

public WebElement getFirstMatchingElement(By by)
{
    List<WebElement> list = driver.findElements(by);
    if(list.size() == 0) {
        return null;
    }
    return list.get(0);
}

那么它就足够通用了,可以这样称呼它。。。。

public WebElement getRegisterLink() {
    return getFirstMatchingElement(By.linktext("Register"));
}

就像。。。

public WebElement getLoginButton() {
    return getFirstMatchingElement(By.id("loginButton"));
}

这通过将代码抽象到另一个方法来解决您的问题,这意味着您的调用者(即您实际找到元素的地方)更干净、更简单,并且不需要“了解”所有“列表内容”。

 类似资料:
  • 第六章 继承和面向对象设计 很多人认为,继承是面向对象程序设计的全部。这个观点是否正确还有待争论,但本书其它章节的条款数量足以证明,在进行高效的C++程序设计时,还有更多的工具听你调遣,而不仅仅是简单地让一个类从另一个类继承。 然而,设计和实现类的层次结构与C语言中的一切都有着根本的不同。只有在继承和面向对象设计领域,你才最有可能从根本上重新思考软件系统构造的方法。另外,C++提供了多种很令人困惑

  • 原型继承 类与实例 类的声明 生成实例 类与继承 如何实现继承 继承的几种方式 类的声明 类声明 构造函数 function Animal1() { this.name = 'animal'; } ES6中class的声明 class Animal2 { constructor() { this.name = 'animal'; } } 1.构造函数方式进行继承 functio

  • JavaScript的继承(实现继承) 原型链 用 原型链 作为实现继承的方法,其基本思想是 利用原型让 一个引用类型 继承 另一个引用类型 的 属性和方法,实现方式就是让  原型对象 等于 另一个类型的实例对象。 回顾构造函数、原型对象和实例之间的关系: 每个构造函数都有个原型属性(prototype),原型属性是一个指针,指向构造函数的原型对象,原型对象默认有个构造属性(constructor

  • 问题内容: 您如何处理在Java中仅具有单一继承的问题?这是我的具体问题: 我有三个(简化的)课程: 这是我认为最基本的实现,但是我想进行其他实现。 可以说我想添加一个新的变量,比如wordLength,但是我想使用继承来添加它。意思是我不想修改那个原始的AbstractWord类。即与此类似: 我知道java不允许我这样做,但是它使我的代码非常难看。现在,每当我添加一个字段时,我都将其添加到Ab

  • 本文向大家介绍JavaScript面向对象程序设计中对象的定义和继承详解,包括了JavaScript面向对象程序设计中对象的定义和继承详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript面向对象程序设计中对象的定义和继承。分享给大家供大家参考,具体如下: 在面向对象的Javascript编程中,希望代码优雅有高效是非常重要的。javascript中不存在类的概念,只有对

  • 面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。 大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class,而是通过“原型对象”(prototype)实现,本章介绍 JavaScript 的原型链继承。 ES6 引入了 class