在我的应用程序中,一些 Geb 测试有点不稳定,因为我们在每个表单字段更改后都会发出 ajax 验证 http 请求。如果 ajax 调用返回的速度不够快,测试就会失败。
我想为此测试一个简单的解决方案,该解决方案(正确或错误,我们不在这里讨论这个争论......)是在设置每个字段后引入一个短暂的 100 毫秒左右的暂停,所以我开始考虑我如何以及在哪里可以实现这一点。
看起来我需要在调用 NonEmptyNavigator.setInputValue
和 NonEmptyNavigator.setSelectValue
方法之后添加 Thread.sleep
。我创建了 GebSpec
的子类,并在其中添加了静态初始化 block :
static {
NonEmptyNavigator.metaClass.invokeMethod = { String name, args ->
def m = delegate.metaClass.getMetaMethod(name, *args)
def result = (m ? m.invoke(delegate, *args) : delegate.metaClass.invokeMissingMethod(delegate, name, args))
if ("setInputValue".equals(name) || "setSelectValue".equals(name)) {
Thread.sleep(100)
}
return result
}
}
但是,我添加了一些调试日志记录,并且我注意到,当我执行规范时,我从未遇到过此代码。我在这里做错了什么......?
最佳答案
我知道您要求不要在设置表单元素值时陷入有关放置 sleep 的争论,但我只是想向您保证,这确实是您不想做的事情。原因有二:
- 这会使您的测试速度明显变慢,从长远来看,这将是痛苦的,因为浏览器测试通常很慢
- 在某些情况下(例如慢速 CI),100 毫秒是不够的,因此本质上您并没有消除不稳定,只是以某种方式限制了它
如果你真的坚持这样做,那么 Geb 允许你使用 custom Navigator
implementations 。您的自定义非空 Navigator
实现如下所示:
class ValueSettingWaitingNonEmptyNavigator extends NonEmptyNavigator {
Navigator value(value) {
super.value(value)
Thread.sleep(100)
this
}
}
这样就不需要对 NonEmptyNavigator
进行猴子修补,并且您将避免可能导致的任何奇怪问题。
一个正确的解决方案是拥有一个自定义的Module
实现,它将覆盖Navigator value(value)
方法并使用waitFor()
来检查验证是否已完成。最后,您可以将此模块中所有经过验证的表单元素包装在页面和模块 content
block 中。这意味着您只在必要时等待并且尽可能少地等待。我不知道你的套件有多大,但随着它的增长,这 100 毫秒将变成几分钟,你会对你的测试有多慢感到不安。相信我,我去过那里。
关于grails - 使用 NonEmptyNavigator.metaClass.invokeMethod { ... } 在字段设置后引入短暂的暂停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26344830/