Vor oder nach allen Scalatest-Tests etwas tun

72

Ich habe eine Reihe von skalierten Tests, die verschiedene Endpunkte einer RESTful-API testen. Ich möchte wirklich, dass sie für eine optimale Organisation in verschiedene Dateien unterteilt werden.

Mein Problem ist, wie man vor allen Tests etwas startet (in meinem Fall einen HTTP-Server, aber es spielt keine Rolle, was es ist) und es nach Abschluss aller Tests herunterfährt.

Ich kenne BeforeAndAfterAll, aber das funktioniert nur vor / nach einer Testdatei. Ich brauche so etwas, aber für alle Tests zum Beispiel:

- Starten Sie den http-Server vor den Tests.
- Führen Sie alle Testsuiten aus.
- Fahren Sie den http-Server herunter

Greg
quelle
Siehe diese Frage / Antwort (nicht ganz ein Duplikat) -> stackoverflow.com/questions/8486869/…
Ron Dahlgren
Überprüfen Sie dieses Q / A: stackoverflow.com/questions/27272811/… Ich wollte den Initialisierungsschritt als Test selbst beibehalten , wobei abhängige Tests sicherstellen, dass die Initialisierung zuerst ausgeführt wurde, und abbrechen, wenn sie fehlgeschlagen war
akauppi

Antworten:

56

Der beabsichtigte Weg, dies zu tun, besteht darin, verschachtelte Suiten zu verwenden. Suite verfügt über eine nestedSuites-Methode, die eine IndexedSeq [Suite] zurückgibt (in 2.0 war es in 1.9.1 eine List [Suite]). Suite verfügt außerdem über eine runNestedSuites-Methode, die für die Ausführung verschachtelter Suites verantwortlich ist. Standardmäßig ruft runNestedSuites nestedSuites auf und ruft bei jeder zurückgegebenen Suite entweder direkt run auf, oder wenn ein Distributor übergeben wird, werden die verschachtelten Suites im Distributor abgelegt, damit sie parallel ausgeführt werden können.

Was Sie also wirklich wahrscheinlich tun möchten, ist, Foo und Bar zu Klassen zu machen und Instanzen davon von der nestedSuites-Methode von EndpointTests zurückzugeben. Es gibt eine Klasse namens Suites, die das so einfach macht. Hier ist ein Beispiel für seine Verwendung:

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
  }         
}

Ein potenzielles Problem besteht jedoch darin, dass alle drei EndpointTests, Foo und Bar erkannt werden, wenn Sie mithilfe der Ermittlung Suites zum Ausführen finden. In ScalaTest 2.0 können Sie Foo und Bar mit @DoNotDiscover mit Anmerkungen versehen, und ScalaTests Runner erkennt sie nicht. Aber sbt wird es immer noch. Wir verbessern derzeit sbt so, dass es ansonsten erkennbare Suiten übergibt, die mit DoNotDiscover kommentiert sind. Dies wird jedoch in sbt 0.13 sein, was noch nicht veröffentlicht wurde. In der Zwischenzeit können Sie sbt dazu bringen, sie zu ignorieren, indem Sie Foo und Bar einen nicht verwendeten Konstruktorparameter hinzufügen.

Bill Venners
quelle
Ein bisschen damit spielen ... Die unbenutzte Konstruktorparameter-Idee ausprobieren. Es funktioniert vom Standpunkt der Nichtentdeckung aus, löst jedoch einen Fehler aus: java.lang.IllegalArgumentException: Klasse ist keine zugängliche org.scalatest.Suite: com.br.awe.service.test.Api10tests. at org.scalatest.tools.ScalaTestFramework $ ScalaTestRunner.run (ScalaTestFramework.scala: 300) at org.scalatools.testing.Runner2.run (Runner2.java:16) at sbt.TestRunner.delegateRun (TestFramework.scala: 57). .. Meine Master-Testsuite beginnt wie folgt: Klasse MasterTestSuite erweitert Suites (neue Api10tests (1), neue Api20tests (1))
Greg
2
Gibt es eine Möglichkeit, die Ergebnisse für die inneren Tests anzuzeigen? Im Moment, wenn es fehlschlägt, ist es einfach so, dass die EndpointTests fehlgeschlagen sind. Es wäre schön zu sehen, welche Tests innerhalb der Suite fehlgeschlagen sind.
Nacht
Es gibt einen Fehler, der einen Deadlock für diesen Ansatz in ScalaTest <2.0.M8 verursacht. Stellen Sie daher sicher, dass Sie ein Upgrade durchführen. Siehe Versionshinweise
David van Geest
1
In der Skalierung 2.2.5 müssen Sie die Konfiguration nicht an die beforeAll-Methode übergeben: `@deprecated (" Verwenden Sie stattdessen die beforeAll (ConfigMap) -Methode BeforeAndAfterAllConfigMap. ") Protected def beforeAll (configMap: ConfigMap) {beforeAll ()} `
r90t
4
Mit diesem Ansatz verlieren wir die Fähigkeit, einzelne Suiten zu betreiben.
Ivan
11

Alternativ können Sie auch nur ein Objekt verwenden.

object TestServer {
  startServer()
}

Wenn Sie auf das Objekt zugreifen, wird es initialisiert und der Server gestartet. Erstellen Sie einfach ein gemeinsames Merkmal, in dessen Körper Sie auf das Objekt zugreifen. Mischen Sie dann dieses Merkmal in alle Ihre Tests ein. Erledigt.

Wenn Ihr Server im Daemon-Modus ausgeführt wird (z. B. eine Play! -Anwendung im Testmodus), wird er automatisch heruntergefahren, nachdem alle Tests ausgeführt wurden.

Machisuji
quelle
Ich kann sehen, dass dies in vielen Fällen besser für mich funktioniert als 'BeforeAndAfterAll'. Beispiel: Jetzt teste ich mit einem etcd-Backend. Wenn ich ein Objekt verwende, kann ich dieselbe Instanz für mehrere Tests ausführen.
Akauppi
11

Ok, habe einen Weg gefunden. Es scheint (es sei denn, jemand hier kann mich korrigieren), dass Scalatest nicht über die Möglichkeit einer "Master" -Suite verfügt. Aber ... du kannst irgendwie einen bauen.

Sie können eine Suite aus Merkmalen zusammenstellen. Verwenden Sie also mein Endpunktbeispiel:

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
        }   
}

Ok, aber was ist mit den Tests? Beachten Sie das mit Foomit Bar. Ich bringe die abhängigen Tests als Merkmale ein. Siehe hier:

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!") {  }
    }
}
Greg
quelle
1
Bills obige Antwort leidet unter dem Verschlucken von Testfehlerdetails - was nutzlos ist, wenn Sie tatsächlich wissen möchten, was schief gelaufen ist. Leider hat dieser Ansatz den Nebeneffekt, dass BeforeAndAfterAllauch innerhalb einzelner Tests für die gesamte Suite gilt. Außerdem können Sie Tests nicht mehr einzeln ausführen und ihre Ausgabe wird auf einmal in die Konsole geschrieben. Ich wünschte wirklich, ScalaTest hätte eine bessere Antwort als diese.
Martin Gladdish