2013-11-27 6 views
8

Lauftests, wie beschrieben hereschnelle Testausführung in einem playframework gefälschte Anwendung

"Spec" should { 
    "example" in new WithApplication { 
    ... 
    } 
} 

ist unannehmbar langsam für mich. Dies liegt daran, dass die neue WithApplication das Framework bei jedem Beispiel startet und beendet. Versteht mich nicht falsch, ein Framework selbst lädt sehr schnell, aber wenn die Datenbank konfiguriert ist (Überraschung!), Wird die Situation schrecklich.

Hier sind einige measurments:

"The database layer" should { 

    "test1" in { 
    1 must be equalTo(1) 
    } 
    ... 
    "test20" in { 
    1 must be equalTo(1) 
    } 
} 

Ausführungszeit: 2 Sekunden. Gleiche Test mit WithApplication bei jedem Beispiel verbraucht 9 Sekunden

konnte ich dank viel bessere Ergebnisse zu this answer

import play.api.Play 
import play.api.test.FakeApplication 
import org.specs2.mutable.Specification 
import scalikejdbc._ 

class MySpec extends Specification { 

var fake: FakeApplication = _ 

step {fake = FakeApplication(...)} 
step {Play.start(fake)} 

"The database layer" should { 

    "some db test" in { 
    DB localTx { implicit session => 
     ... 
    } 
    } 

    "another db test" in { 
    DB localTx { implicit session => 
     ... 
    } 
    } 

    step {Play.stop()} 
} 

}

Pros achive: Leistungssteigerung

Nachteile:

  • müssen Code kopieren-Paste-Setup und tear-down, weil nicht wissen, wie es zu Wiederverwendung (durch Wiederverwendung meine ich so etwas wie "Klasse MySpec erweitert Spezifikation mit NoWasteOfTime"

  • neue WithApplication() Anrufe Helpers.running, die nicht vollständig emulieren Helpers.running wie dieses ich kann

synchronized { 
    try { 
    Play.start(fakeApp) 
    block 
    } finally { 
    Play.stop() 
    play.api.libs.ws.WS.resetClient() 
    } 
} 

so aussieht Verhalten (ResetClient ist für meinen Code nicht sichtbar) ohne Reflektion.

Bitte schlagen Sie vor, wie man Nachteile oder anderen Ansatz bricht, wie mein Problem erreicht.

+0

Möchten Sie einmal für eine Spezifikation Setup/Teardown, oder wollen Sie es für jeden Test darin tun? –

+0

Es ist schade, dass es 18 Monate später ist und Play dieses Verhalten noch nicht verändert hat. Starten der App für jeden Test ist lächerlich. Play 3 wird DI haben, das hoffentlich die Notwendigkeit für eine laufende App vollständig beseitigen wird. – andyczerwonka

Antwort

9

Ich weiß nicht, ob es die beste Lösung ist, aber in diesem Thread: Execute code before and after specification

Sie können eine Lösung für wiederverwendbaren Code lesen. Ich habe es mit kleinen Änderungen implementiert. Bei mir lief der beforeAll-Schritt nicht und fügte den Modifikator sequential hinzu.

import org.specs2.mutable._ 
import org.specs2.specification._ 

class PlayAppSpec extends Specification with BeforeAllAfterAll{ 
    sequential 
    lazy val app : FakeApplication = { 
     FakeApplication() 
    } 

    def beforeAll(){ 
     Play.start(app) 
    } 

    def afterAll(){ 
     Play.stop() 
    } 
} 
import org.specs2.specification.Step 

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


    def beforeAll() 
    def afterAll() 
} 

Ich denke, die map mit Step(...)^fragments^Step(...) besser wäre, aber es die beforeAll für mich nicht laufen. Das Benutzerhandbuch (http://bit.ly/11I9kFM) bei "Global setup/teardown" besagt, dass ein Lazy Val verwendet werden soll.

Insgesamt war es ein Schmerz, dies einzurichten.Mein Problem war Exception in thread "Thread-145" java.net.SocketException: Connection reset Oder

Configuration error[Cannot connect to database [default]] (Configuration.scala:559)

Wenn die gleiche FakeApplication Wiederverwendung: SQLException: Attempting to obtain a connection from a pool that has already been shutdown.

Ich denke, es ist viel logischer diese Art und Weise als immer eine neue Anwendung für jeden „in“ Block erstellen oder Hinzufügen aller Tests in einen Block.

+0

Ich bevorzuge definitiv Ihren Ansatz, funktioniert wie ein Charme. – Jeriho

Verwandte Themen