Selenium 的 LoadableComponent 作为测试设计模式是一个很好的解决方案吗?

软件测试 自动化测试 测试设计 页面对象
2022-02-05 14:23:23

我需要重构我的 Selenium 测试,并看到他们的LoadableComponent wiki 页面我开始尝试使用它,虽然我无法真正理解它有什么用处。我查看了他们当前的实现(至于 2011-07-26),现在更加困惑。代码基本上是使用错误处理来控制执行流程。让我觉得很奇怪的事情:

@SuppressWarnings("unchecked")
public T get() {
  try {
    isLoaded();
    return (T) this;
  } catch (Error e) {
    load();
  }

  isLoaded();

  return (T) this;
}

也就是说,违背了“只为异常使用而使用异常”的设计原则,这里,异常就是规则,并且isLoaded至少在第一次调用该方法时被期望抛出异常。

此外,这LoadableComponent是一个抽象类,这意味着我不能让子组件继承自父组件。

这一切对我来说似乎都是错误的。我只是为get()每个页面对象实现一个方法,如果需要,它会根据 Selenium 驱动程序的状态加载页面,无需捕获异常。我错了吗?

1个回答

我不知道当你问“我错了吗?”时你指的是哪个“这个”?根据 Wiki 页面,isLoaded 方法应该使用 JUnit 断言来检查页面是否实际加载。JUnit 断言抛出错误,而不是异常,以表明出现问题。

LoadableComponent 可以将 isLoaded 重构为两种方法:一种(称为 isLoadedBoolean)返回一个指示页面是否已加载的布尔值,另一种(称为 assertLoaded)使用 JUnit 断言。当然,如果检查页面是否加载需要评估多个条件,那么 assertLoaded 指示哪个条件失败可能很有价值。懒惰的人可能会这样做:

protected void assertLoaded() {
  assertTrue(condition1,"condition 1 failed");
  assertTrue(condition2,"condition 2 failed");
}

protected boolean isLoadedBoolean() {
  try {
    assertLoaded();
    return true;
  }
  catch (Error e) {
    return false;
  }

其他人会认为设计太奇怪了,而是这样做:

protected void assertLoaded() {
  assertTrue(condition1,"condition 1 failed");
  assertTrue(condition2,"condition 2 failed");
}

protected boolean isLoadedBoolean() {
  return condition1 && condition2;
}

当然,如果检查页面是否加载的标准发生了变化(当然它会发生变化,因为这是对 Web 界面的测试),这两种方法都需要更新。因此,以这种方式编写代码的开发人员将用怪异来换取维护错误。

我想另一种选择是这样的:

public class PageLoadCheckFailure {
   public String reason;
   ... other interesting data ...

   public PageLoadCheckFailure(reason, ... other interesting data ...) {
      this.reason = reason;
      etc.
   }

   public String getReason() {
      return reason;
   }

   ... getters for other interesting data ...
}

protected PageLoadCheckFailure checkWhetherLoaded() {
   if (!condition1) {
      return new PageLoadCheckFailure("condition 1 failed", ... other interesting data...);
   }
   if (!condition2) {
         return new PageLoadCheckFailure("condition 1 failed", ... other interesting data...);
   }
   return nil;
}

protected void assertLoaded() {
  PageLoadCheckFailure result = checkWhetherLoaded();
  if (result != nil) {
     Assert.fail(result.toString());
  }
}

protected boolean isLoadedBoolean() {
  return checkWhetherLoaded() == nil;
}

但与 Selenium 设计相比,这确实看起来需要做很多工作,尤其是因为这毕竟只是测试代码。