简体   繁体   English

玩Famework 2 - Scala - 启动一个测试套件应用程序

[英]Play Famework 2 - Scala - Start one application for test-suite

I've been following the Scala testing examples using Specs2 from the official Play documentation. 我一直在使用官方Play文档中的Specs2来跟踪Scala测试示例。 I notice that they use WithApplication to start up a fake application to test against, with clode like the following: 我注意到他们使用WithApplication来启动一个虚假的应用程序进行测试,如下所示:

"something" should {
    "do X" in new WithApplication { /* ... */ }
    "do Y" in new WithApplication { /* ... */ }
    "do Z" in new WithApplication { /* ... */ }
}

This is fine and all, but the problem that I'm having is that I incur the cost of my application starting up each time this happens. 这很好,但是我遇到的问题是,每次发生这种情况时,我都要承担启动应用程序的成本。 This isn't necessarily "fast" or at least not fast enough once your test-suite grows to a reasonable size. 一旦您的测试套件增长到合理的大小,这不一定是“快”或至少不够快。 I've tried doing things like: 我尝试过这样的事情:

val app = FakeApplication()
"something" should {
    "do X" in new WithApplication(app) { /* ... */ }
    "do Y" in new WithApplication(app) { /* ... */ }
    "do Z" in new WithApplication(app) { /* ... */ }
}

and

"something" should {
    val app = FakeApplication()
    Helpers.running(app) {
        "do X" in { /* ... */ }
        "do Y" in { /* ... */ }
        "do Z" in { /* ... */ }
    }
}

The first seems to work for the first test and then complains about db connection issues on the later tests. 第一个似乎适用于第一个测试,然后在后面的测试中抱怨数据库连接问题。 I'm guessing something is getting shutdown here or something (not sure what). 我猜这里有什么东西要关机或什么东西(不确定是什么)。

The second doesn't work at all because it complains about there being no running application, which I'm not sure about either. 第二个根本不起作用,因为它抱怨没有正在运行的应用程序,我也不确定。

Any help is greatly appreciated. 任何帮助是极大的赞赏。 Thanks! 谢谢!

Well, it depends on what you want to test. 嗯,这取决于你想测试什么。 If you're just unit testing code that has no external dependencies or dependencies that you can mock or stub out (and it would be a good idea to structure your code in such a way that allows this), then you don't need to use WithApplication . 如果您只是单元测试没有外部依赖关系或依赖关系的代码,您可以模拟或存根(并且以允许这种方式构建代码是一个好主意),那么您不需要使用WithApplication This is probably the best approach. 这可能是最好的方法。

The first solution you provided doesn't work because applications can only be used once. 您提供的第一个解决方案不起作用,因为应用程序只能使用一次。 It's WithApplication that starts and stops your application, so even if that did work, you wouldn't get any performance benefit. 它是启动和停止应用程序的WithApplication ,因此即使它确实有效,也不会获得任何性能优势。

The second solution you provided doesn't work because when the Helpers.running(app) { } code block runs, this is only declaring the specs. 您提供的第二个解决方案不起作用,因为当Helpers.running(app) { }代码块运行时,这只是声明规范。 Specs puts all these in a list, and then you exit the running block and it shuts down the app. 规范将所有这些放在一个列表中,然后退出正在运行的块并关闭应用程序。 Then at some point later, specs runs the tests, and there's no application of course then. 然后在某些时候,规范运行测试,当然没有应用程序。

So, if you can't test your code in isolation of the rest of your app, then you need to have a running app, there's nothing you can do about that, it's the reality of integration testing. 因此,如果您无法独立于应用程序的其余部分测试代码,那么您需要有一个正在运行的应用程序,您无需做任何事情,这是集成测试的现实。 And you probably want it started and shutdown between each test, otherwise your tests aren't running in isolation of each other. 并且您可能希望它在每次测试之间启动和关闭,否则您的测试不会彼此孤立地运行。

It's outdated, but I'll give my answer. 它已经过时了,但我会给出答案。 Since I faced same problem, and had similar idea. 既然我遇到同样的问题,也有类似的想法。 There is AfterAll & BeforeAll traits in spec2, maybe it was not there at the time of post, so my solution is basically: 在spec2中有AfterAll&Before所有特征,也许它在发布时不存在,所以我的解决方案基本上是:

package com.equipx.spec.util

import org.specs2.specification.{AfterAll, BeforeAll}
import play.Application
import play.api.Play
import play.test.{Helpers, FakeApplication}

/**
 * @author Anton Oparin (antono@clemble.com)
 */
trait WithGlobalApplication extends BeforeAll with AfterAll {

  protected var app: Application = null

  /**
   * Override this method to setup the application to use.
   *
   * By default this will call the old {@link #provideFakeApplication() provideFakeApplication} method.
   *
   * @return The application to use
   */
  protected def provideApplication: Application = {
    return provideFakeApplication
  }

  /**
   * Old method - use the new {@link #provideApplication() provideApplication} method instead.
   *
   * Override this method to setup the fake application to use.
   *
   * @return The fake application to use
   */
  protected def provideFakeApplication: FakeApplication = {
    return Helpers.fakeApplication
  }

  override def beforeAll {
    app = provideApplication
    Helpers.start(app)
    Play.current
  }

  override def afterAll {
    if (app != null) {
      Helpers.stop(app)
      app = null
    }
  }

}

Basically I took WithApplication implementation, and made it global. 基本上我采用了WithApplication实现,并使其成为全局的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM