Grails 使用NonEmptyNavigator.metaClass.invokeMethod{…}在字段集之后引入短暂停

Grails 使用NonEmptyNavigator.metaClass.invokeMethod{…}在字段集之后引入短暂停,grails,groovy,spock,geb,Grails,Groovy,Spock,Geb,在我的应用程序中,一些Geb测试有点不稳定,因为我们在每个表单字段更改后都会发出一个ajax验证http请求。如果ajax调用返回的速度不够快,测试就会失败 我想测试一个简单的解决方案,它(正确或错误,让我们不要在这里讨论…)是在每个字段设置后引入一个短的100毫秒左右的暂停,所以我开始研究如何和在哪里实现这一点 看起来我需要在调用NonEmptyNavigator.setInputValue和NonEmptyNavigator.setSelectValue方法之后添加一个线程.sleep。我创

在我的应用程序中,一些Geb测试有点不稳定,因为我们在每个表单字段更改后都会发出一个ajax验证http请求。如果ajax调用返回的速度不够快,测试就会失败

我想测试一个简单的解决方案,它(正确或错误,让我们不要在这里讨论…)是在每个字段设置后引入一个短的100毫秒左右的暂停,所以我开始研究如何和在哪里实现这一点

看起来我需要在调用
NonEmptyNavigator.setInputValue
NonEmptyNavigator.setSelectValue
方法之后添加一个
线程.sleep
。我创建了一个子类
GebSpec
,在其中添加了一个静态初始值设定项块:

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
    }
}

然而,我添加了一些调试日志,我注意到当我执行我的规范时,我从未碰到过这段代码。我做错了什么…?

我知道您要求不要在设置表单元素值时就设置睡眠进行辩论,但我只想向您保证,这确实是您不想做的事情。原因有两个:

  • 这将使您的测试速度大大降低,从长远来看,这将是痛苦的,因为浏览器测试通常都很慢
  • 在某些情况下(比如慢CI),100毫秒是不够的,所以本质上你并没有消除片状,你只是在某种程度上限制了它
如果您真的坚持这样做,那么Geb允许您使用。您的自定义非空
导航器
实现如下所示:

class ValueSettingWaitingNonEmptyNavigator extends NonEmptyNavigator {
    Navigator value(value) {
        super.value(value)
        Thread.sleep(100)
        this
    }
}
这样就不需要使用monkey patch
NonEmptyNavigator
,您将避免可能导致的任何奇怪问题


一个合适的解决方案是有一个自定义的
模块
实现,该实现将覆盖
导航器值(value)
方法,并使用
waitFor()
检查验证是否已完成。最后,您将在页面和模块
content
块中包装此模块中所有已验证的表单元素。这意味着你只在必要的地方等待,并且尽可能少地等待。我不知道你的套件有多大,但随着它的增长,这100毫秒将变成几分钟,你会对你的测试有多慢感到不安。相信我,我已经做到了。

这段代码在groovyConsole中运行良好。也许这是grails的问题?是的,我在想,也许有什么东西覆盖了我的元类更改…谢谢你的全面回答。值得一提的是,我完全同意你关于在测试中添加任意暂停。。。