2013-11-26 5 views
7

Ich habe die Scala-Testbeispiele mit Specs2 aus der offiziellen Play-Dokumentation verfolgt. Ich bemerke, dass sie WithApplication verwenden, um eine gefälschte Anwendung zu testen gegen, mit clode wie folgt aus zu starten:Play Famework 2 - Scala - Starten Sie eine Anwendung für Testsuite

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

Das ist in Ordnung und alles, aber das Problem, dass ich habe, ist, dass ich die Kosten entstehen Meine Anwendung startet jedes Mal, wenn dies geschieht. Dies ist nicht unbedingt "schnell" oder zumindest nicht schnell genug, wenn Ihre Testsuite auf eine vernünftige Größe angewachsen ist. Ich habe versucht, Dinge zu tun wie:

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

und

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

Die erste scheint für den ersten Test zu arbeiten und dann beschwert sich über db-Verbindungsprobleme zu den späteren Tests. Ich nehme an, hier wird etwas heruntergefahren oder etwas (nicht sicher was).

Die zweite funktioniert überhaupt nicht, weil sie sich darüber beschwert, dass es keine laufende Anwendung gibt, von der ich mir auch nicht sicher bin.

Jede Hilfe wird sehr geschätzt. Vielen Dank!

Antwort

4

Nun, es hängt davon ab, was Sie testen möchten. Wenn Sie nur Unit-Test-Code verwenden, der keine externen Abhängigkeiten oder Abhängigkeiten aufweist, die Sie nachahmen oder ausstellen können (und es wäre eine gute Idee, Ihren Code so zu strukturieren, dass dies möglich ist), müssen Sie dies nicht tun Verwenden Sie WithApplication. Dies ist wahrscheinlich der beste Ansatz.

Die erste von Ihnen bereitgestellte Lösung funktioniert nicht, da Anwendungen nur einmal verwendet werden können. Es ist WithApplication, die Ihre Anwendung startet und stoppt, also selbst wenn das funktionieren würde, würden Sie keinen Leistungsvorteil erhalten.

Die zweite Lösung, die Sie zur Verfügung gestellt haben, funktioniert nicht, denn wenn der Codeblock Helpers.running(app) { } ausgeführt wird, werden nur die Spezifikationen deklariert. Specs fügt all diese Daten in eine Liste ein, und dann verlässt du den laufenden Block und es schaltet die App aus. Dann, zu einem späteren Zeitpunkt, führt Specs die Tests durch und es gibt natürlich keine Anwendung.

Also, wenn Sie Ihren Code nicht isoliert von dem Rest Ihrer App testen können, dann brauchen Sie eine laufende App, es gibt nichts, was Sie dagegen tun können, es ist die Realität des Integrationstests. Und Sie möchten wahrscheinlich, dass es zwischen den einzelnen Tests gestartet und heruntergefahren wird, andernfalls laufen Ihre Tests nicht isoliert voneinander ab.

3

Es ist veraltet, aber ich werde meine Antwort geben. Da ich demselben Problem gegenüberstand und ähnliche Vorstellungen hatte. Es gibt afterall & BeforeAll Züge in spec2, vielleicht ist es zum Zeitpunkt der Post nicht da war, so meine Lösung im Grunde ist:

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 ([email protected]) 
*/ 
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 
    } 
    } 

} 

Im Grunde habe ich WithApplication Implementierung und machte es global.