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


73

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

我的问题是如何在所有测试之前启动某个东西(就我而言,这是一个HTTP服务器,但并不重要),并在所有测试完成后将其关闭。

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

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


看到这个问题/答案(不是很重复)-> stackoverflow.com/questions/8486869/…–
罗恩·达尔格伦

请检查以下问题:stackoverflow.com/questions/27272811/…我想保留初始化步骤作为测试本身,相关测试确保初始化首先运行,并取消初始化失败
akauppi,2014年

Answers:


57

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

因此,您实际上可能要做的是将Foo和Bar变成类,然后从EndpointTests的nestedSuites方法返回它们的实例。有一个简单的类叫做Suites。这是其用法的示例:

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仍然会。我们目前正在增强sbt,以便它可以通过用DoNotDiscover注释的其他可发现的套件传递,但是它将在sbt 0.13中,但尚未发布。同时,您可以通过向Foo和Bar添加未使用的构造函数参数来使sbt忽略它们。


玩这个...尝试未使用的构造函数参数的想法。它从无发现的角度工作,但是会引发某种错误:java.lang.IllegalArgumentException:类不是可访问的org.scalatest.Suite:com.br.awe.service.test.Api10tests。在org.scalatest.tools.ScalaTestFramework $ ScalaTestRunner.run(ScalaTestFramework.scala:300)在org.scalatools.testing.Runner2.run(Runner2.java:16)在sbt.TestRunner.delegateRun(TestFramework.scala:57)处。 ..我的主测试套件如下所示:MasterTestSuite类扩展套件(新Api10tests(1),新Api20tests(1))
Greg

2
有没有办法显示内部测试的结果?目前,如果它失败了,那就只能说EndpointTests失败了。很高兴看到套件中哪些测试失败。
Nacht 2013年

ScalaTest <2.0.M8中有一个错误会导致此方法陷入僵局,因此请确保升级。请在此处查看M8的发行说明:scalatest.org/release_notes/2.0
David van Geest

1
在scalatest 2.2.5中,您不需要将配置传递给beforeAll方法:`@deprecated(“请改用特征BeforeAndAfterAllConfigMap的beforeAll(ConfigMap)方法。”)protected def beforeAll(configMap:ConfigMap){beforeAll()} `
r90t

4
请注意,使用这种方法会失去运行单个套件的能力。
伊万·巴拉索夫

11

或者,您可以只使用一个对象。

object TestServer {
  startServer()
}

当您访问对象时,它将被初始化,启动服务器。只需在访问对象的主体中创建一个公共特征即可。然后将这个特征混入所有测试中。做完了

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


与“ BeforeAndAfterAll”相比,在许多情况下,我认为这种方法对我来说更好。例如,现在我正在使用etcd后端进行测试,并且使用对象使我可以在多个测试中运行相同的实例。
akauppi

对象TestServer {startServer(); 覆盖def finalize():单位= {super.finalize(); stopServer()}}
brendon

11

好的,找到了办法。似乎(除非有人可以纠正我),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
        }   
}

好吧,那测试呢?注意Foowith Bar。我把依赖测试作为特征。看这里:

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!") {  }
    }
}

1
Bill的上述答案遭受了测试失败细节的吞没-如果您确实想知道出了什么问题,这是没有用的。不幸的是,这种方法具有副作用,BeforeAndAfterAll即使在单个测试中也适用于整个套件。另外,您不再可以单独运行测试,并且将其输出全部写入控制台。我真的希望ScalaTest有比这更好的答案。
Martin Gladdish
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.