在规范之前和之后执行代码

15

我有一个简单的规范,其中包含几个案例:

class MySpec extends Specification {

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

现在我需要启动应用程序,运行所有测试用例,然后关闭应用程序。启动/停止应用程序非常耗时,我不希望它在每个测试用例周围发生。

我该如何在测试用例开始之前和所有测试用例完成后运行代码?


请向下滚动此文档页面,直到“Before/After”段落。 - om-nom-nom
@om-nom-nom 它只是解释了如何在每个情况下执行代码。 - lambdas
糟糕,我的意思是“模板”或“全局设置/拆卸”段落(其中包含数据库设置/清理):-) - om-nom-nom
@om-nom-nom 我已经做了。它只是解释了如何在规范之前执行代码。 - lambdas
我曾经遇到过相同的情况,并且没有发现任何缺省的前/后功能能够满足我的需求。如果你能等大约一个小时(因为我在路上去上班),我会发布我的解决方案。 - cmbaxter
@om-nom-nom,链接失效了 :( - Paul Draper
4个回答

33
我基于cmbaxter的答案提出了以下解决方案。
import org.specs2.specification.Step

trait BeforeAllAfterAll extends Specification {
  // see http://bit.ly/11I9kFM (specs2 User Guide)
  override def map(fragments: =>Fragments) = 
    Step(beforeAll) ^ fragments ^ Step(afterAll)

  protected def beforeAll()
  protected def afterAll()
}

然后在Specification中混合BeforeAllAfterAll,并实现beforeAllafterAll方法:

class MySpec extends Specification with BeforeAllAfterAll {

  def beforeAll() {
    println("Doing setup work...")
  }

  def afterAll() {
    println("Doing shutdown work...")
  }

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

最后,将初始化内容提取出来以在不同的规格说明之间共享:
trait InApplication extends BeforeAllAfterAll {
  def beforeAll() {
    println("Doing setup work...")
  }

  def afterAll() {
    println("Doing shutdown work...")
  }
}

class MySpec extends Specification with InApplication {

  "Something" should {

    "case 1" in {
      ...
    }

    "case 2" in {
      ...
    }
  }
}

1
这真的很有帮助,谢谢。现在如果我想为所有规范创建一个全局设置怎么办? - Sebastien Lorber

8

好的,正如我在评论中提到的那样,我曾经遇到过这个问题。我需要测试未过滤的端点,而对于每个规范来说,最好的方法是启动一个仅有一个端点的未过滤服务器,运行规范,然后关闭服务器。为了实现这一目标,我首先定义了一个类似于以下代码的基本规范:

import org.specs2.mutable.Specification

abstract class SpecificationBase extends Specification{
  //Do setup work here
  step{
    println("Doing setup work...")
    success
  }

  //Include the real spec from the derived class
  include(spec)

  //Do shutdown work here
  step{
    println("Doing shutdown work...")
    success
  }  

  /**
   * To be implemented in the derived class.  Returns the real specification
   * @return Specification
   */
  def spec:Specification
}

基本上,该基类将完整的规范装配为设置步骤和拆卸步骤,并用中间的真实规范(在具体规范类中定义)夹在中间。因此,使用此基类的测试将如下所示:

class MySpec extends SpecificationBase{ def spec = 
  new Specification{
    "A request to do something" should{
      "be successful in case 1" in {
        println("Testing case 1")
        success
      }
      "be successful in case 2" in {
        println("Testing case 2")
        success
      }      
    }
  }
}

当你运行此代码时,你会看到:
Doing setup work...
Testing case 1
Testing case 2
Doing shutdown work...

虽然不是完美的,但它起作用了。有没有另一种(可能更简洁/更好)的方法来做到这一点?可能有,但这是一个解决方案,你可以考虑使用。


谢谢!我基于你的方案开发了更简洁的解决方案,并将其发布为答案。 - lambdas

2
现有的答案很好,但现在在specs2中有一个简单的BeforeAfterAll trait。覆盖它将提供所需的功能。例如,测试代码:
class ASpec extends Specification with BeforeAfterAll {

  "The 'Hello world' string" should {
    "contain 11 characters" in {
      println("test 1")
      "Hello world" must have size (11)
    }
    "start with 'Hello'" in {
      println("test 2")
      "Hello world" must startWith("Hello")
    }
    "end with 'world'" in {
      println("test 3")
      "Hello world" must endWith("world")
    }
  }

  def beforeAll(): Unit = {
    println("beforeAll")
  }

  def afterAll(): Unit = {
    println("afterAll")
  }
}

将输出:

beforeAll
test 3
test 2
test 1
afterAll

-1

好的,这是一个老问题,但它可能会帮助到某些人。

我正在使用Play框架。在我的测试中,我使用了org.scalatest.BeforeAndAfterAll

示例:

import org.scalatest.BeforeAndAfterAll

class MySpec extends PlaySpec with BeforeAndAfterAll {

  "Some test" must {
    "print a text" in {

      println("Some test")
      2 mustBe 2
    }
  }

  override def beforeAll(): Unit = {
    println("Before")
  }

  override def afterAll(): Unit = {
    println("After")
  }
}

2
据我所知,问题是关于specs2的,而这个答案是关于scalatest的。 - user2770362

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接