Ci sono 2 parti alla tua domanda: utilizzando Vars per la memorizzazione di stato intermedio, e l'arresto esempi quando uno sta fallendo.
1 - Utilizzo Vars
Ci
sono alcune alternative all'utilizzo Vars quando si utilizza una specifica mutevole.
È possibile utilizzare lazy vals
che rappresenta le fasi del processo:
object DatabaseSpec extends mutable.Specification {
sequential
"The Data Access Object" should {
lazy val id1 = database.save(Entity(1))
lazy val loaded = database.load(id1)
lazy val list = database.list
"save an object" >> { id1 === 1 }
"load one object" >> { loaded.id === id1 }
"list all objects" >> { list === Seq(Entity(id1)) }
}
object database {
def save(e: Entity) = e.id
def load(id: Int) = Entity(id)
def list = Seq(Entity(1))
}
case class Entity(id: Int)
}
Tali valori sono pigri, perché saranno chiamati solo quando vengono eseguiti gli esempi.
Se si è pronti a cambiare la struttura della vostra specifica corrente è anche possibile utilizzare l'ultima 1.12.3-SNAPSHOT e di gruppo tutte quelle piccole aspettative in un esempio:
"The Data Access Object provides a save/load/list api to the database" >> {
lazy val id1 = database.save(Entity(1))
lazy val loaded = database.load(id1)
lazy val list = database.list
"an object can be saved" ==> { id1 === 1 }
"an object can be loaded" ==> { loaded.id === id1 }
"the list of all objects can be retrieved" ==> {
list === Seq(Entity(id1))
}
}
Se uno qualsiasi di tali aspettative fallisce, allora non verrà eseguito il resto e si otterrà un messaggio di errore del tipo:
x The Data Access Object provides a save/load/list api to the database
an object can not be saved because '1' is not equal to '2' (DatabaseSpec.scala:16)
Un'altra possibilità, che richiederebbe 2 piccoli miglioramenti, sarebbe quella di utilizzare il modo Given/When/Then delle specifiche di scrittura ma utilizzando expectati "gettato" passaggi all'interno dei passi Given
e When
. Come si può vedere nella Guida per l'utente, i Given/When/Then
passi estrarre i dati da stringhe e passano le informazioni digitate al successivo Given/When/Then
:
import org.specs2._
import specification._
import matcher.ThrownExpectations
class DatabaseSpec extends Specification with ThrownExpectations { def is =
"The Data Access Object should"^
"save an object" ^save^
"load one object" ^load^
"list all objects" ^list^
end
val save: Given[Int] = groupAs(".*") and { (s: String) =>
database.save(Entity(1)) === 1
1
}
val load: When[Int, Int] = groupAs(".*") and { (id: Int) => (s: String) =>
val e = database.load(id)
e.id === 1
e.id
}
val list: Then[Int] = groupAs(".*") then { (id: Int) => (s: String) =>
val es = database.list
es must have size(1)
es.head.id === id
}
}
I miglioramenti, che ho intenzione di fare, sono:
- rilevare le eccezioni di errore per segnalarle come errori e non errori
- rimuovere la necessità di utilizzare
groupAs(".*") and
quando non c'è nulla da estrarre dalla descrizione della stringa.
In tal caso dovrebbe essere sufficiente scrivere:
val save: Given[Int] = groupAs(".*") and { (s: String) =>
database.save(Entity(1)) === 1
1
}
Un'altra possibilità sarebbe quella di permettere di scrivere direttamente:
val save: Given[Int] = groupAs(".*") and { (s: String) =>
database.save(Entity(1)) === 1
}
in cui un oggetto Given[T]
può essere creato da un String => MatchResult[T]
perché l'oggetto MatchResult[T]
contiene già un valore di tipo T
, che diventerebbe un "Dato".
2 - Fermare l'esecuzione dopo un esempio di mancanza di
Uso del implicita WhenFail
Around
contesto è certamente il modo migliore per fare ciò che si vuole (a meno che non si va con le aspettative descrizioni come indicato sopra la G/W/T esempio).
Note sulla step(stepOnFail = true)
I step(stepOnFail = true)
opere interrompendo i seguenti esempi se un esempio nel blocco precedente di esempi simultanee fallito. Tuttavia, quando si utilizza sequential
, quel blocco precedente è limitato a un solo esempio. Quindi cosa stai vedendo. In realtà penso che questo sia un bug e che tutti gli esempi rimanenti non debbano essere eseguiti, sia che tu stia usando sequenziale o meno. Quindi rimanete sintonizzati per una soluzione in arrivo questo fine settimana.
specifiche BTW 2.x è stato progettato per risolvere questo problema esatto, in cui è possibile creare test arbitrari basandosi sui risultati dei test precedenti. Vedi qui: https://etorreborre.github.io/specs2/guide/SPECS2-3.1.1/org.specs2.guide.CreateOnlineSpecifications.html – Eric