除非使用@Stepwise,否则类无法将模块解析为内容

时间:2017-09-26 20:22:21

标签: testing automation spock geb

我有一个Spock类,当作为测试套件运行时,抛出Unable to resolve iconRow as content for geb.Page, or as a property on its Navigator context. Is iconRow a class you forgot to import?,除非我用@Stepwise注释我的类。但是,我确实不希望测试执行在第一次失败时停止,这是@Stepwise所做的。

我已尝试使用this帖子撰写(复制和粘贴)我自己的扩展程序,但我仍然遇到这些错误。它正在使用我的扩展,因为我添加了一些打印到控制台的日志语句。

这是我的一个模块:

class IconRow extends Module {
    static content = {
        iconRow (required: false) {$("div.report-toolbar")}
    }
}

使用它的页面:

class Report extends SomeOtherPage {
    static at = {$("div.grid-container").displayed}

    static content = {
        iconRow { module IconRow }
    }
}

还有一个失败的测试片段:

class MyFailingTest extends GebReportingSpec {

    def setupSpec() {
        via Dashboard
        SomeClass.login("SourMonk", "myPassword")
        assert page instanceof Dashboard

        nav.goToReport("Some report name")
        assert page instanceof Report
    }

    @Unroll
    def "I work"() {
        given:
        at Report

        expect:
        this == that

        where:
        this << ["some list", "of values"]
        that << anotherModule.someContent*.@id
    }

    @Unroll
    def "I don't work"() {
        given:
        at Report

        expect:
        this == that

        where:
        this << ["some other", "list", "of values"]
        that << iconRow.columnHeaders*.attr("innerText")*.toUpperCase()
    }
}

作为套件I work传递时,I don't work失败,因为它无法识别&#34; iconRow&#34;作为页面的内容。如果我切换测试用例的顺序,I don't work将通过,I work将失败。或者,如果我单独执行每个测试,它们都会通过。

我尝试过:

  • 从模块中的内容添加/删除required: true属性
  • 使用类添加模块名称,例如IconRow.iconRow
  • 将我的模块定义为静态@Shared属性
  • 初始化setupSpec()
  • 内外的模块
  • 在每个模块的类中返回简单的getter方法,返回模块,并引用IconRow.getIconRow().columnHeaders*.attr("innerText")*.toUpperCase()
  • 等内容
  • setupSpec()的内容移至setup()
  • autoClearCookies = false添加到我的GebConfig.groovy
  • 制作@Shared Report report变量并为所有模块添加前缀report.iconRow

关于最后一个要点的非常特别的注意事项 - 它神奇地解决了具有前缀的模块 - 所以它不会解决report.IconRow但是将只解决iconRow - 绝对奇怪,因为如果我删除该变量,之前突然工作的模块将无法再次解决。我甚至尝试声明这个变量,然后没有添加任何前缀,这也不起作用。

我一直把头撞到墙上的另一个问题是,我也不确定 问题所在。它引发的错误让我相信它是一个项目设置问题,但单独运行每个功能都可以正常工作,所以它似乎正好解决了这些类。

另一方面,也许这是会话和/或Cookie的问题?虽然我还没有看到关于此的任何官方文档,但似乎是普遍的共识(来自我已阅读过的其他帖子和文章)仅使用@Stepwise将维持您在功能方法之间的会话。如果是这种情况,为什么我的扩展无法正常工作?它几乎是@Stepwise没有skipFeaturesAfterFirstFailingFeature方法的复制和粘贴(如果需要,我可以发布),除非在幕后使用@Stepwise进行其他操作

为文本墙道歉,但我现在已经试图解决这个问题大约6个小时了,所以我的脑子很油腻。

1 个答案:

答案 0 :(得分:3)

Geb特别支持@Stepwise,如果规范用它注释,它在每次测试后都不会调用resetBrowser(),而是在规范完成后调用它。请参阅github

上的代码

所以基本上你需要将你的setupSpec更改为setup,以便在每次测试之前执行它。

关于您的观察,如果您只是运行一个重点测试,则会为该测试执行setupSpec,因此它会通过。问题出现了,之后调用清理并重置浏览器,打破后续测试。

修改

我忽略了你对where块的使用,where块需要静态地(@Shared)可用,因此使用实例级构造将不起作用。重置浏览器也将杀死每个引用,所以只有在它不能工作之前获取它。基本上,不要在where块中使用Geb对象!

查看您的代码,但我认为没有任何理由在此处使用数据驱动测试。

  1. 这可以通过正常测试中的一个断言轻松完成
  2. 单元测试只是测试一件事是一种好习惯。然而,Geb不是单元测试,而是接受/前端测试。这里的问题是它们比单元测试慢,将合理的断言合并到一个测试中是有意义的。
  3. 
    class MyFailingTest extends GebReportingSpec {    
        def setup() {
            via Dashboard
            SomeClass.login("SourMonk", "myPassword")
            assert page instanceof Dashboard
    
            nav.goToReport("Some report name")
            assert page instanceof Report
        }
    
        def "I work"() {
            given:
            at Report
    
            expect:
            ["some list", "of values"] == anotherModule.someContent*.@id
        }
    
        def "I don't work"() {
            given:
            at Report
    
            expect:
            ["some other", "list", "of values"] == iconRow.columnHeaders*.attr("innerText")*.toUpperCase()
        }
    }