web-dev-qa-db-fra.com

Quelle est la différence entre ScalaTest et Scala Specs unit test frameworks?

Les deux sont des cadres de tests unitaires compatibles BDD (Behavior Driven Development) pour Scala écrit en Scala. Et Spécifications est construit sur peut également impliquer le framework ScalaTest . Mais qu'est-ce que Specs offre ScalaTest ne fait pas? Quelles sont les différences?

119
Alex

Les spécifications et ScalaTest sont tous deux de bons outils pour les utilisateurs satisfaits, mais ils diffèrent de plusieurs manières. Vous voudrez probablement en choisir un comme votre principal outil de test dans Scala, mais ne devez pas abandonner l'autre car vous pouvez utiliser des morceaux des deux. Si vous aimez la syntaxe FeatureSpec de ScalaTest et la syntaxe Mockito de specs, par exemple, vous pouvez placer les deux fichiers jar dans votre chemin de classe et les utiliser 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 basé sur le comportement (BDD), tandis que ScalaTest est plus général. ScalaTest fournit des traits 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 prend en charge BDD par le biais de ses traits Spec, FeatureSpec, WordSpec, FlatSpec et GivenWhenThen, ainsi que des traits que vous pouvez mélanger pour obtenir une syntaxe Nice Matcher. Si vous aimez "devrait", vous mélangez dans ShouldMatchers. Si vous aimez "must", vous mélangez dans MustMatchers. Mais si vous aimez BDD mais que vous n'aimez pas la syntaxe de matcher, vous pouvez simplement utiliser l'un des traits de spécification de ScalaTest sans mélanger un trait de matchers. Specs possède une classe Specification que vous étendez et vous devez utiliser le mot "must" dans vos expressions de correspondance. 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 fournis ici un arbre de décision:

http://www.scalatest.org/quick_start

La syntaxe du matcher est également différente entre ScalaTest et les spécifications. 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 ressemblaient beaucoup à des phrases anglaises, avec des espaces entre les mots. La syntaxe de la correspondance des spécifications exécute davantage les mots avec le boîtier camel.

Specs a plus d'apparieurs que ScalaTest, et cela reflète une différence d'attitude de conception. J'ai en fait coupé probablement 2/3 de la syntaxe de matcher que j'ai construite et envisagée pour la sortie. J'ajouterai plus d'apparieurs 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 matchers de ScalaTest incluent une syntaxe de correspondance de propriété dynamique qui prend une partie de ce mou. Par exemple, dans les spécifications, 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 d'apparieurs spéciaux pour Java.io.Files actuellement, 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 un 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 le === 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 si vous essayiez de tester quelque chose qui a son propre ===, et 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 mélangeant un trait ou en effectuant une importation. Lorsque vous étendez la classe Specification dans les spécifications, je pense que vous obtenez à peu près des dizaines de conversions implicites par défaut. Je ne sais pas combien cela importera dans la pratique, mais je pense que les gens voudront tester du code qui utilise leurs propres implications, et parfois il peut y avoir un conflit entre les implications du framework de test et celles 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 des opérateurs. L'un de mes objectifs était que tout programmeur qui regarde le code de test de quelqu'un d'autre qui utilise ScalaTest puisse deviner ce que signifiait sans chercher quoi que ce soit dans la documentation ScalaTest. Je voulais que le code client ScalaTest soit parfaitement évident. Une façon dont cet objectif s'est manifesté est que ScalaTest est très conservateur à propos des 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 ça. 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 d'exécuter la documentation de l'API pour deviner ce que cela <= veux dire. 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 devrez peut-être exécuter la documentation lorsque vous trouverez des choses comme ->-, >>, |, |>, !, ou ^^^ (qui ont tous une signification particulière dans les spécifications) 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 l'utilisation d'un style fonctionnel lorsque vous devez partager un appareil, tandis que les spécifications par défaut poursuivent la tradition des setUp et tearDown approche popularisée par JUnit, dans laquelle vous réaffectez des 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 trait BeforeAndAfter.

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

170
Bill Venners

Les principales différences sont (principalement du point de vue des spécifications :-)):

  • ScalaTest fournit plus de "styles de test" que de spécifications (vous pouvez visiter chaque puce sur la page démarrage rapide pour obtenir une vue détaillée de chaque style)

  • ScalaTest et les spécifications ont un ensemble différent d'apparieurs. Vous pouvez les comparer ici pour ScalaTest et ici pour les spécifications. De ce côté des choses, les spécifications ont beaucoup de petites fonctionnalités que vous pouvez aimer lors de la rédaction de votre spécification: égaliseurs xml, composition des égaliseurs (un moyen facile de réutiliser les égaliseurs en les transformant), échecs précis, différences détaillées pour les chaînes longues, .. .

  • Mockito a reçu un support Nice BDD dans les spécifications: Mockito

  • specs a DataTables qui permettent de regrouper beaucoup de petits exemples dans une sorte de table (si vous pouvez supporter les opérateurs utilisés comme délimiteurs de table)

  • Dans les spécifications, vous pouvez définir des exemples imbriqués comme libidum et nettoyés automatiquement à chaque niveau

Il s'agit certainement d'une comparaison très partielle et biaisée et de nombreuses autres différences existent (et les bibliothèques évoluent toujours, ...).

À la fin de la journée, je pense que cela dépend vraiment de votre style de test/spécification. Si c'est simple (structure de spécification simple, configurations, attentes, ...) alors les deux bibliothèques apparaîtront très similaires. Sinon, les deux ont leur point de vue sur la façon dont les choses devraient être faites. Comme dernier exemple de cela, vous pouvez jeter un œil au balisage: dans ScalaTest et dans specs .

J'espère que ça aide.

48
Eric

Pour autant que je sache, à l'exception de quelques fonctionnalités hautement spécialisées, cela se résume à une préférence personnelle en fonction du style.

4
Daniel C. Sobral

Le support IDE peut être un autre point

J'ai essayé de faire fonctionner Specs avec Eclipse via JUnit, et j'ai trouvé la solution officielle un peu "hacky". Configuration des spécifications: http://code.google.com/p/specs/wiki/RunningSpecs#Run_your_specification_with_JUnit4_in_Eclipse

L'intégration de ScalaTest (également via JUnit) avec semble un peu moins hacky. Pourtant, je n'en ai aucun qui fonctionne aussi bien que JUnit et Java.

Configuration de ScalaTest: http://groups.google.com/group/scalatest-users/web/running-scalatest-from-Eclipse

2
Grav

Si un facteur de décision est le temps de compilation, le scalatest semble mieux fonctionner.

Nous utilisons actuellement specs2 dans notre projet, mais souffrons de temps de compilation lents dans les tests. Je viens de terminer un POC sur le passage au scalatest et j'ai vu les temps de compilation chuter d'un facteur d'environ 0,82 simplement en changeant les 2 frameworks dans certaines de nos sources.

0
sebi