Specs et ScalaTest sont tous deux de bons outils avec des utilisateurs satisfaits, mais ils diffèrent de plusieurs manières. Vous voudrez probablement en choisir un comme principal outil de test dans Scala, mais vous ne devez pas abandonner l'autre car vous pouvez utiliser des morceaux des deux. Si vous aimez la FeatureSpec
syntaxe de ScalaTest et la syntaxe Mockito de specs, par exemple, vous pouvez placer les deux fichiers jar dans votre chemin de classe et utiliser les deux en même temps. Ici, je vais essayer de capturer les principales différences de philosophie de conception que j'ai remarquées entre les spécifications et ScalaTest.
La principale différence philosophique entre les outils est probablement que les spécifications sont conçues pour le développement axé sur le comportement (BDD), tandis que ScalaTest est plus général. ScalaTest fournit des caractéristiques que vous pouvez mélanger pour obtenir le comportement que vous préférez dans vos classes de test, y compris BDD, et vous pouvez également définir facilement votre propre comportement si vous voulez quelque chose de différent.
ScalaTest supports BDD par son Spec
, FeatureSpec
, WordSpec
, FlatSpec
et GivenWhenThen
traits, et a aussi des traits que vous pouvez mélanger pour obtenir une belle syntaxe matcher. Si vous aimez "devrait", vous mélangez dans ShouldMatchers. Si vous aimez "must", vous mélangez MustMatchers
. Mais si vous aimez BDD mais que vous n'aimez pas la syntaxe matcher, vous pouvez simplement utiliser l'un des traits Spec de ScalaTest sans mélanger dans un trait matchers. Specs a une classe de spécification que vous étendez et vous devez utiliser le mot «must» dans vos expressions matcher. Une grande différence philosophique qui est évidente ici est que ScalaTest vous donne beaucoup plus de choix. Pour faciliter la navigation dans cet espace de choix, je propose ici un arbre de décision:
http://www.scalatest.org/quick_start
La syntaxe du matcher est également différente entre ScalaTest et specs. Dans ScalaTest, j'ai essayé de voir jusqu'où je pouvais aller avec la notation d'opérateur, et je me suis retrouvé avec des expressions de correspondance qui se lisent beaucoup comme des phrases anglaises, avec des espaces entre les mots. La syntaxe du matcher de spécifications exécute davantage les mots avec la casse camel.
Specs a plus de matchers que ScalaTest, et je pense que cela reflète une différence d'attitude de conception. En fait, j'ai coupé probablement 2/3 de la syntaxe du matcher que j'ai construite et envisagée pour la publication. J'ajouterai plus de matchers dans les prochaines versions, mais je voulais être sûr de savoir que les utilisateurs voulaient réellement quelque chose avant de l'ajouter. Cependant, les correspondants de ScalaTest incluent une syntaxe de correspondance de propriété dynamique qui prend une partie de cette marge. Par exemple, dans Specs, vous pouvez écrire sur un java.io.File
:
file must beDirectory
Cela invoquera le isDirectory
et s'assurera qu'il est vrai. ScalaTest n'a pas de correspondance spéciale pour le moment java.io.Files
, mais dans ScalaTest, vous pouvez simplement utiliser une vérification dynamique comme celle-ci:
file must be a ('directory)
Chaque fois que vous passez un symbole après be
, il utilisera la réflexion pour rechercher (dans ce cas) une méthode ou un champ nommé directory
ou une méthode nommée isDirectory
. Il existe également un moyen de rendre cela statique, en définissant a BePropertyMatcher
(qui ne nécessite généralement que 2 ou 3 lignes de code). Donc, fondamentalement, dans ScalaTest, j'essaie de fournir plus de fonctionnalités avec moins d'API.
Une autre différence d'attitude de conception générale entre les spécifications et ScalaTest implique des conversions implicites. Par défaut, vous n'obtenez qu'une seule conversion implicite lorsque vous utilisez ScalaTest, qui est celle qui place l' ===
opérateur sur tout. (Si vous en avez besoin, vous pouvez "désactiver" cette conversion implicite avec une seule ligne de code. La seule raison pour laquelle vous auriez besoin de le faire est que vous essayiez de tester quelque chose qui a son propre ===
opérateur et que vous obtenez un conflit. ) ScalaTest définit de nombreuses autres conversions implicites, mais pour les utiliser, vous devez les «inviter» explicitement dans votre code en les mélangeant dans un trait ou en faisant une importation. Lorsque vous prolongez la classeSpecification
dans les spécifications, je pense que vous obtenez à peu près des dizaines de conversions implicites par défaut. Je ne sais pas à quel point cela importera dans la pratique, mais je pense que les gens voudront tester du code qui utilise leurs propres implicits, et parfois il peut y avoir un conflit entre les implicits du framework de test et ceux du code de production. Lorsque cela se produit, je pense qu'il peut être plus facile de contourner le problème dans ScalaTest que les spécifications.
Une autre différence d'attitude de conception que j'ai remarquée est le confort avec les opérateurs. Un objectif que j'avais était que tout programmeur regardant le code de test de quelqu'un d'autre qui utilise ScalaTest soit capable de deviner quelle était la signification sans rien chercher dans la documentation de ScalaTest. Je voulais que le code client ScalaTest soit totalement évident. Une façon dont cet objectif s'est manifesté est que ScalaTest est très prudent sur les opérateurs. Je ne définis que cinq opérateurs dans ScalaTest:
===
, ce qui signifie égal
>
, ce qui signifie supérieur à
<
, moins que
>=
, Meilleur que ou égal
<=
, inférieur ou égal.
C'est tout. Donc, ces choses ressemblent à peu près à ce que cela signifie. Si vous voyez dans le code de quelqu'un d'autre:
result should be <= 7
J'espère que vous n'aurez pas besoin de consulter la documentation de l'API pour deviner ce que cela <=
signifie. En revanche, les spécifications sont beaucoup plus libres avec les opérateurs. Rien de mal à cela, mais c'est une différence. Les opérateurs peuvent rendre le code plus concis, mais le compromis est que vous pourriez avoir à courir à la documentation lorsque vous trouvez des choses comme ->-
, >>
, |
, |>
, !
ou ^^^
(qui ont tous une signification particulière dans les specs) dans le code de test de votre collègue.
Une autre différence philosophique est que j'essaie de rendre un peu plus facile dans ScalaTest d'utiliser un style fonctionnel lorsque vous devez partager un appareil, alors que Specs par défaut continue la tradition de l' approche setUp
et tearDown
popularisée par JUnit, dans laquelle vous réaffectez les vars avant chaque test. Cependant, si vous voulez tester de cette façon, c'est aussi très facile dans ScalaTest. Vous avez juste besoin de mélanger le BeforeAndAfter
trait.
Pour plus d'informations sur ScalaTest, vous pouvez regarder la présentation "Get Higher with ScalaTest" que j'ai donnée à la conférence Devoxx 2009 ici:
http://parleys.com/play/514892260364bc17fc56bde3/chapter0/about