在所有Scalatest测试之前或之后做一些事情

时间:2013-03-15 01:45:10

标签: scala scalatest

我有一套scalatest测试,可以测试RESTful API的不同端点。 我真的希望将它们分成不同的文件以便最佳组织。

我的问题是如何在所有测试之前启动某些东西(在我的情况下是一个HTTP服务器,但它并不重要),并在所有测试完成后关闭它。

我知道BeforeAndAfterAll,但这只能在一个测试文件内部/之后完成。我需要这样的东西,但对于所有测试,例如:

- 在测试之前启动http服务器 - 运行所有测试套件
- 关闭http服务器

3 个答案:

答案 0 :(得分:48)

执行此操作的预期方法是使用嵌套套件。 Suite有一个nestedSuites方法,它返回一个IndexedSeq [Suite](在2.0中,在1.9.1中它是一个List [Suite])。 Suite还有一个runNestedSuites方法,负责执行任何嵌套套件。默认情况下,runNestedSuites调用nestedSuites,并且在每个返回的Suite上直接调用run,或者如果传递了Distributor,则将嵌套套件放入分发器中,以便它们可以并行运行。

所以你真正想要做的是将Foo和Bar放入类中,并从EndpointTests的nestedSuites方法返回它们的实例。有一个类可以简单地称为套件。以下是其使用示例:

import org.scalatest._
import matchers.MustMatchers

class Foo extends FunSpec with MustMatchers {
  describe("Message here...") {
    it("Must do something") {  }
    it("Must be ok") {  }
  }
}

class Bar extends FunSpec with MustMatchers {
  describe("Hello you...") {
    it("One more!") {  }
  }
}

class EndpointTests extends Suites(new Foo, new Bar) with BeforeAndAfterAll {

  override def beforeAll(configMap: Map[String, Any]) {
    println("Before!")  // start up your web server or whatever
  }     

  override def afterAll(configMap: Map[String, Any]) {
    println("After!")  // shut down the web server
  }         
}

但是,一个潜在的问题是,如果您使用发现来查找要运行的套件,则将发现所有三个EndpointTests,Foo和Bar。在ScalaTest 2.0中,您可以使用@DoNotDiscover注释Foo和Bar,而ScalaTest的Runner将不会发现它们。但是仍然会。我们目前正在增强sbt,以便它通过使用DoNotDiscover注释的其他可发现的套件,但这将是sbt 0.13,这还没有结束。在此期间,您可以通过向Foo和Bar添加未使用的构造函数参数来让sbt忽略它们。

答案 1 :(得分:10)

或者你可以只使用一个物体。

object TestServer {
  startServer()
}

当您访问该对象时,它将被初始化,启动服务器。 只需在您访问该对象的主体中创建一个共同特征。 然后将这种特性混合到所有测试中。完成。

如果您的服务器以守护进程模式运行(例如,测试模式下的Play!应用程序),它将在所有测试运行后自动关闭。

答案 2 :(得分:8)

好的,找到了办法。似乎(除非有人在这里纠正我)Scalatest没有“主人”套件的设施。但是......你可以建立一个。

你可以从特质组成一个套件。所以使用我的端点示例:

class EndpointTests extends FunSpec with MustMatchers with BeforeAndAfterAll 
      with Foo with Bar {
        override def beforeAll(configMap: Map[String, Any]) {
            println("Before!")  // start up your web server or whatever
        }

        override def afterAll(configMap: Map[String, Any]) {
            println("After!")  // shut down the web server
        }   
}

好的,但测试怎么样?请注意FooBar的合并。我将依赖测试作为特征。 见这里:

trait Foo extends FunSpec with MustMatchers {
    describe("Message here...") {
        it("Must do something") {  }
        it("Must be ok") {  }
    }
}

trait Bar extends FunSpec with MustMatchers { 
    describe("Hello you...") {
        it("One more!") {  }
    }
}