在ScalaTest中覆盖测试的标记

时间:2017-02-03 15:00:53

标签: tags hook scalatest

我想将DRY原则应用于我的ScalaTest测试定义。具体来说,我想定义一个定义一堆测试的抽象测试类。所有测试都调用一些函数,其中的参数指示要测试的条件。该函数的定义留给扩展类。到目前为止,这是可行的。

接下来,我想标记任何曾经失败的测试并将其修复为"回归"测试,所以如果我这么倾向,我可以运行那些测试。

但测试最初是在抽象类中标记的。我需要在实现类中覆盖标记或添加标记。

这样做有干净的方法吗?文档暗示存在,但到目前为止,我无法找到如何执行此操作的示例。

1 个答案:

答案 0 :(得分:0)

我从来没有找到关于如何做到这一点的文档,但ScalaDocs中有足够的信息让我能够弄明白。为了那些可能想要做这样的事情的人的利益,这是你需要知道的:

首先,您需要定义自己的特征,并将其混合以获得此额外行为。它将覆盖tag()的定义,如下所示:

trait _____ extends SuiteMixin with Informing { this: Suite with Informing =>
  // with Informing, etc. is so that you can call info() 
  // to add comments to tests - not strictly needed for this

  abstract override def tags : Map[String, Set[String]] = {
    // implementation
  }
}

实现必须调用super.tags,然后在返回之前添加需要添加到结果数据结构中的任何内容。结果的键将是测试名称,值将是标记字符串的集合。注意:没有标记的测试将不存在,因此您将无法依赖迭代该对象来查找要操作的测试。您最终必须致电this.testNames并对其进行迭代。

以下是我编写的代码示例,说明了如何解决此问题。

  abstract override def tags : Map[String, Set[String]] = {
    val original = super.tags
    val matching = <list of what to automatically add tags to>
    if ( matching.isEmpty ) original
    else {
      val tests = this.testNames.toList
      def extend( result: Map[String, Set[String]], test_list: List[String] ) : Map[String, Set[String]] = 
        if ( test_list.isEmpty ) result
        else {
          val matches = ( for ( p <- matching if ( <applicable> ) ) yield true ) contains true
          if ( ! matches ) extend( result, test_list.tail )
          else extend( 
            result.updated( 
              test_list.head,
              result.getOrElse( test_list.head, Set[String]() )
                + "<tag-to-be-added>" ),
            test.tail 
          )
        }
      extend( original, tests )
    }
  }

希望这可以帮助除了我以外的人。

欢迎并赞赏有关如何以更优雅或 scala-esque 方式执行此操作的评论。