【问题标题】:Find the outcome/status of a test in Specification.cleanup()在 Specification.cleanup() 中查找测试的结果/状态
【发布时间】:2018-06-03 12:00:18
【问题描述】:

这似乎是一件合理的事情……例如当测试失败时记录一些东西,如果没有,则不记录。

我找到了this,例如,从 2013 年开始……当时没有既简单又有效的答案。现在呢?

我希望可以在 org.spockframework.runtime.SpecificationContext ... 或者 org.spockframework.runtime.model.SpecInfo ... 中找到合适的属性/方法,但我什么都看不到。

稍后

回答我可能想做的事情的问题:事实上我的Specifications “劫持”System.out(使用PrintStream)所以我可以捕获输出到System.out 然后分析它。注意记录,我知道 Spock 纯粹主义者可能不赞成对终端输出感兴趣的测试,但我不是这样的纯粹主义者,特别是在谈论单元测试以外的测试时。

以某种方式获得此输出,这意味着它不会在任何地方输出,因此没有理由系统地记录它并弄乱日志文件......但如果测试失败,我想这样做。 System.err 可能同上...

【问题讨论】:

    标签: testing spock


    【解决方案1】:

    首先,记录失败的测试是您的测试框架(JUnit、Spock)的工作。因此,测试本身的状态不容易从测试本身中获得也就不足为奇了。无论如何,如果您想要 Spock 中更高级的东西,那么另一个线程中的 accepted answerPeter's answer 仍然有效。没有更简单的方法可以通过 cleanup() 方法找出测试是否失败。

    无论如何,它并不像看起来那么复杂,因为您只需设置一次,然后它就可以工作了。由于您没有提到您想要登录cleanup() 的确切内容,我将进行一些推测。出于演示目的,我只是记录了从规范上下文中检索到的功能方法名称,以及发生的错误的类(以免两次打印整个花哨的 Spock 错误消息),从注册的运行侦听器中检索到我将在这里介绍全局扩展。

    全球 Spock 扩展:

    该扩展注册了一个运行监听器,它在发生测试错误时记录错误信息。在每个功能或迭代开始时(对于具有 where: 块的功能),最后记录的错误被清除,以免渗入下一个功能/迭代。

    package de.scrum_master.testing.extension
    
    import org.spockframework.runtime.AbstractRunListener
    import org.spockframework.runtime.extension.AbstractGlobalExtension
    import org.spockframework.runtime.model.ErrorInfo
    import org.spockframework.runtime.model.IterationInfo
    import org.spockframework.runtime.model.SpecInfo
    
    class TestResultExtension extends AbstractGlobalExtension {
      @Override
      void visitSpec(SpecInfo spec) {
        spec.addListener(new ErrorListener())
      }
    
      static class ErrorListener extends AbstractRunListener {
        ErrorInfo errorInfo
    
        @Override
        void beforeIteration(IterationInfo iteration) {
          errorInfo = null
        }
    
        @Override
        void error(ErrorInfo error) {
          errorInfo = error
        }
      }
    }
    

    如何注册 Spock 扩展:

    您还需要将文件META-INF/services/org.spockframework.runtime.extension.IGlobalExtension 添加到您的测试资源中才能注册扩展。该文件仅包含以下内容:

    de.scrum_master.testing.extension.TestResultExtension
    

    顺便说一句,这不是 Spock 或 Groovy 的东西,而是称为 service providers 的标准 Java SE 功能。

    使用扩展的示例测试:

    这个测试非常愚蠢,但它展示了它如何适用于普通方法和带有where: 块的方法,无论有没有@Unroll

    package de.scrum_master.testing.extension
    
    import spock.lang.Specification
    import spock.lang.Unroll
    
    class TestFailureReportingTest extends Specification {
      def "failing normal feature"() {
        expect:
        0 == 1
      }
    
      def "passing normal feature"() {
        expect:
        0 == 0
      }
    
      def "parametrised feature"() {
        expect:
        a == b
    
        where:
        a << [2, 4, 6]
        b << [3, 5, 6]
      }
    
      @Unroll
      def "unrolled feature with #a/#b"() {
        expect:
        a == b
    
        where:
        a << [6, 8, 0]
        b << [7, 9, 0]
      }
    
      def cleanup() {
        specificationContext.currentSpec.listeners
          .findAll { it instanceof TestResultExtension.ErrorListener }
          .each {
            def errorInfo = (it as TestResultExtension.ErrorListener).errorInfo
            if (errorInfo)
              println "Test failure in feature '${specificationContext.currentIteration.name}', " +
                "exception class ${errorInfo.exception.class.simpleName}"
            else
              println "Test passed in feature '${specificationContext.currentIteration.name}'"
          }
      }
    }
    

    控制台日志(省略实际错误)将是:

    Test failure in feature 'failing normal feature', exception class ConditionNotSatisfiedError
    
    Test passed in feature 'passing normal feature'
    
    Test failure in feature 'parametrised feature', exception class ConditionNotSatisfiedError
    Test failure in feature 'parametrised feature', exception class ConditionNotSatisfiedError
    Test passed in feature 'parametrised feature'
    
    Test failure in feature 'unrolled feature with 6/7', exception class ConditionNotSatisfiedError
    Test failure in feature 'unrolled feature with 8/9', exception class ConditionNotSatisfiedError
    Test passed in feature 'unrolled feature with 0/0'
    

    P.S.:错误信息在功能方法内的cleanup: 块中可用,因为扩展仅在包括该块在内的整个功能/迭代完成运行后才会启动。因此,您确实必须使用 cleanup() 方法,但无论如何您都希望这样做,它可以避免代码重复。

    P.P.S.:当然,您也可以只在方法拦截器中进行通用日志记录,然后跳过整个 cleanup() 方法。但是,您不再可以使您的日志输出特定于测试,并且它将用于所有您的测试,而不仅仅是您选择的测试 - 当然除非您对包或规范名称过滤器进行硬编码直接进入拦截器或确保Spock启动时拦截器读取相应的配置文件。

    【讨论】:

    • “它并不像看起来那么复杂”……呃,也许吧!我只能说,这可能需要我一天的时间来锻炼。还有,维伦丹克!
    • 我在另一个上下文中再次发现了这个并更新了示例代码:测试现在打印展开的方法(迭代)名称,以防您使用带有参数名称占位符的@Unroll。我还从拦截器中删除了多余的方法beforeFeature
    • 请提出一个新问题并显示代码来解释您想要做什么以及您尝试了什么。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    相关资源
    最近更新 更多