Specifiche e ScalaTest sono entrambi buoni strumenti con utenti soddisfatti, ma differiscono in diversi modi. Probabilmente vorrai sceglierne uno come strumento di test principale in Scala, ma non devi rinunciare all'altro perché puoi usare parti di entrambi. Se ti piace la FeatureSpec
sintassi di ScalaTest e la sintassi Mockito delle specifiche, ad esempio, puoi inserire entrambi i file jar nel tuo classpath e usarli entrambi allo stesso tempo. Qui cercherò di catturare le principali differenze di filosofia di progettazione che ho notato tra le specifiche e ScalaTest.
Probabilmente la principale differenza filosofica tra gli strumenti è che le specifiche sono progettate per lo sviluppo guidato dal comportamento (BDD), mentre ScalaTest è più generale. ScalaTest fornisce tratti che puoi mescolare insieme per ottenere il comportamento che preferisci nelle tue classi di test, incluso BDD, e puoi anche definire facilmente il tuo comportamento se vuoi qualcosa di diverso.
ScalaTest supporti BDD attraverso la sua Spec
, FeatureSpec
, WordSpec
, FlatSpec
, e GivenWhenThen
tratti, e ha anche caratteristiche che si possono mescolare per ottenere un bel sintassi matcher. Se ti piace "dovrebbe", mescola ShouldMatchers. Se ti piace il "must", mischia MustMatchers
. Ma se ti piace BDD ma non ti piace la sintassi del matcher, puoi semplicemente usare uno dei tratti Spec di ScalaTest senza mescolare un tratto del matcher. Specs ha una classe Specification che estendi e devi usare la parola "must" nelle espressioni del matcher. Una grande differenza filosofica che è evidente qui è che ScalaTest ti offre molte più scelte. Per rendere questo spazio di scelta più facile da navigare, fornisco un albero decisionale qui:
http://www.scalatest.org/quick_start
Anche la sintassi del matcher è diversa tra ScalaTest e specs. In ScalaTest ho cercato di vedere fino a che punto potevo andare con la notazione degli operatori, e sono finito con espressioni di corrispondenza che si leggono in modo molto simile alle frasi inglesi, con spazi tra le parole. La sintassi di corrispondenza delle specifiche esegue le parole insieme più con il caso del cammello.
Specs ha più matcher di ScalaTest e penso che rifletta una differenza nell'attitudine al design. In realtà ho tagliato probabilmente 2/3 della sintassi del matcher che ho costruito e preso in considerazione per il rilascio. Aggiungerò più abbinamenti nelle versioni future, ma volevo essere sicuro di sapere che gli utenti volevano effettivamente qualcosa prima di aggiungerlo. Tuttavia, i matcher di ScalaTest includono una sintassi del matcher di proprietà dinamico che occupa parte di quel margine di flessibilità. Ad esempio in Specifiche puoi scrivere su java.io.File
:
file must beDirectory
Questo richiamerà il isDirectory
e si assicurerà che sia vero. ScalaTest non ha abbinamenti speciali per il java.io.Files
momento, ma in ScalaTest, potresti semplicemente usare un controllo dinamico come questo:
file must be a ('directory)
Ogni volta che si passa un simbolo dopo be
, utilizzerà la riflessione per cercare (in questo caso) un metodo o un campo denominato directory
o un metodo denominato isDirectory
. C'è anche un modo per renderlo statico, definendo a BePropertyMatcher
(che di solito richiede solo 2 o 3 righe di codice). Quindi fondamentalmente in ScalaTest cerco di fornire più funzionalità con meno API.
Un'altra differenza nell'atteggiamento di progettazione generale tra le specifiche e ScalaTest riguarda le conversioni implicite. Per impostazione predefinita, ottieni una sola conversione implicita quando usi ScalaTest, che è quella che mette l' ===
operatore su tutto. (Se necessario, puoi "disattivare" questa conversione implicita con una riga di codice. L'unico motivo per cui dovresti farlo è se stavi provando a testare qualcosa che ha il suo ===
operatore e ottieni un conflitto. ) ScalaTest definisce molte altre conversioni implicite, ma per usarle è necessario "invitarle" esplicitamente nel codice mescolando un tratto o eseguendo un'importazione. Quando estendi la classeSpecification
nelle specifiche penso che tu ottenga praticamente dozzine di conversioni implicite per impostazione predefinita. Non sono sicuro di quanto sarà importante nella pratica, ma immagino che le persone vorranno testare il codice che utilizza i propri impliciti e talvolta potrebbe esserci un conflitto tra gli impliciti del framework di test e quelli del codice di produzione. Quando ciò accade, penso che potrebbe essere più facile aggirare il problema in ScalaTest rispetto alle specifiche.
Un'altra differenza nell'attitudine al design che ho notato è il comfort con gli operatori. Uno degli obiettivi che avevo era che qualsiasi programmatore che guardasse il codice di test di qualcun altro che usa ScalaTest sarebbe in grado di indovinare quale fosse il significato senza cercare nulla nella documentazione di ScalaTest. Volevo che il codice client ScalaTest fosse ovvio. Un modo in cui l'obiettivo si è manifestato è che ScalaTest è molto conservatore riguardo agli operatori. Definisco solo cinque operatori in ScalaTest:
===
, che significa uguale
>
, che significa maggiore di
<
, meno di
>=
, Maggiore o uguale
<=
, minore o uguale.
Questo è tutto. Quindi queste cose sembrano più o meno quello che significano. Se vedi nel codice di qualcun altro:
result should be <= 7
La mia speranza è che non sia necessario eseguire la documentazione dell'API per indovinare cosa <=
significa. Al contrario, le specifiche sono molto più libere con gli operatori. Non c'è niente di sbagliato in questo, ma è una differenza. Gli operatori possono rendere il codice più conciso, ma il compromesso è che si potrebbe essere necessario eseguire la documentazione quando si trova cose come ->-
, >>
, |
, |>
, !
, o ^^^
(che hanno tutti un significato speciale in Spec) nel codice di prova del vostro collega.
Un'altra differenza filosofica è che cerco di rendere leggermente più semplice in ScalaTest utilizzare uno stile funzionale quando è necessario condividere un dispositivo, mentre Specs per impostazione predefinita continua la tradizione dell'approccio setUp
e tearDown
reso popolare da JUnit, in cui si riassegnano i vars prima di ogni prova. Tuttavia, se vuoi testare in questo modo, è anche molto semplice in ScalaTest. Hai solo bisogno di mescolare il BeforeAndAfter
tratto.
Per ulteriori informazioni su ScalaTest, puoi guardare la presentazione "Get Higher with ScalaTest" che ho tenuto alla conferenza Devoxx del 2009 qui:
http://parleys.com/play/514892260364bc17fc56bde3/chapter0/about