在Specification.cleanup()

时间:2018-06-03 12:00:19

标签: testing spock

想做的事似乎是合理的......例如测试失败时记录某些内容,如果没有则记录。

例如,我从2013年开始发现this ...当时没有简单有效的答案。那现在呢?

我希望在org.spockframework.runtime.SpecificationContext ......或者org.spockframework.runtime.model.SpecInfo中找到合适的属性/方法......但我看不到任何内容。

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

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

1 个答案:

答案 0 :(得分:1)

首先,记录失败的测试是您的测试框架(JUnit,Spock)工作。因此,测试本身的状态在该测试本身内不易获得并不令人惊讶。无论如何,如果你想在Spock中找到更好的东西,那么另一个帖子中的accepted answerPeter's answer仍然有效。没有更简单的方法可以从cleanup()方法中找出测试是否失败。

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

Global Spock扩展程序:

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

package de.scrum_master.stackoverflow

import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractGlobalExtension
import org.spockframework.runtime.model.ErrorInfo
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.IterationInfo
import org.spockframework.runtime.model.SpecInfo

class MyGlobalExtension extends AbstractGlobalExtension {
  @Override
  void visitSpec(SpecInfo spec) {
    spec.addListener(new ErrorListener())
  }

  static class ErrorListener extends AbstractRunListener {
    ErrorInfo errorInfo

    @Override
    void beforeFeature(FeatureInfo feature) {
      errorInfo = null
    }

    @Override
    void beforeIteration(IterationInfo iteration) {
      errorInfo = null
    }

    @Override
    void error(ErrorInfo error) {
      errorInfo = error
    }
  }
}

如何注册Spock扩展程序:

您还需要将文件META-INF/services/org.spockframework.runtime.extension.IGlobalExtension添加到您的teast资源以注册扩展程序。该文件只包含以下内容:

de.scrum_master.stackoverflow.MyGlobalExtension

BTW,这不是Spock或Groovy,而是标准的Java SE功能service providers

使用扩展程序进行样本测试:

此测试非常愚蠢,但展示了如何使用带有where:的{​​{1}}阻止@Unroll块的常规方法和方法。

package de.scrum_master.stackoverflow

import spock.lang.Specification
import spock.lang.Unroll

class TestFailureReportingTest extends Specification {

  def cleanup() {
    specificationContext.currentSpec.listeners
      .findAll { it instanceof MyGlobalExtension.ErrorListener }
      .each {
        def errorInfo = (it as MyGlobalExtension.ErrorListener).errorInfo
        if (errorInfo)
          println "Test failure in feature '${specificationContext.currentFeature.name}', " +
            "exception class ${errorInfo.exception.class.simpleName}"
        else
          println "Test passed in feature '${specificationContext.currentFeature.name}'"
      }
  }

  def normalFeature() {
    expect:
    0 == 1
  }

  def parametrisedFeature() {
    expect:
    a == b

    where:
    a | b
    2 | 3
    4 | 5
    6 | 6
  }

  @Unroll
  def unrolledParametrisedFeature() {
    expect:
    a == b

    where:
    a | b
    6 | 7
    8 | 9
    0 | 0
  }
}

P.S。:在功能方法内的cleanup:块中,错误信息可用,因为扩展仅在整个功能/迭代(包括该块已完成运行)之后启动。所以你真的必须使用cleanup()方法,但无论如何你想要它,它避免了代码重复。

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

相关问题