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

时间:2014-10-13 16:38:44

标签: grails groovy spock geb

在我的应用程序中,一些Geb测试有点不稳定,因为我们在每个表单字段更改后触发了ajax验证http请求。如果ajax调用没有足够快地返回,测试就会爆炸。

我想为此测试一个简单的解决方案,(正确或错误,让我们不在这里讨论...)是在每个字段设置后引入短暂的100ms左右暂停,所以我开始关注怎么&我可以在哪里实现这一目标。

看起来我需要在调用Thread.sleepNonEmptyNavigator.setInputValue方法后添加NonEmptyNavigator.setSelectValue。我创建了一个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
    }
}

但是我添加了一些调试日志记录,我注意到当我执行我的规范时,我从来没有点过这段代码。我在这做错了什么......?

1 个答案:

答案 0 :(得分:3)

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

  • 它会使你的测试明显变慢,从长远来看这将是痛苦的,因为浏览器测试通常很慢
  • 会出现这种情况(例如缓慢的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块中。这意味着你只能在必要的地方等待,尽可能少。我不知道你的套房有多大,但随着它的增长,这100毫秒会变成几分钟,你会对你的测试速度感到不安。相信我,我去过那里。