Les essais statiques pour Scala
-
13-09-2019 - |
Question
Il y a quelques bibliothèques pour les tests de belles Scala ( Spécifications , ScalaTest , ScalaCheck ). Cependant, avec puissant système de type Scala, des éléments importants d'une API en cours d'élaboration à Scala sont exprimés de manière statique, généralement sous la forme d'un comportement indésirable ou interdit d'être empêché par le compilateur.
Alors, quelle est la meilleure façon de vérifier si quelque chose est empêché par le compilateur lors de la conception d'une bibliothèque ou une autre API? Il est peu satisfaisant pour commenter le code qui est censé être uncompilable puis décommenter pour vérifier.
Un exemple test Liste artificielle:
val list: List[Int] = List(1, 2, 3)
// should not compile
// list.add("Chicka-Chicka-Boom-Boom")
Est-ce que l'une des bibliothèques de tests existants traitent les cas comme celui-ci? Y at-il une approche que les gens utilisent qui fonctionne?
L'approche que je considérais était d'inclure du code dans une chaîne guillemet triple ou un élément XML et appeler le compilateur dans mon test. code appelant à la recherche quelque chose comme ceci:
should {
notCompile(<code>
val list: List[Int] = List(1, 2, 3)
list.add("Chicka-Chicka-Boom-Boom")
</code>)
}
Ou, quelque chose le long des lignes d'un attendre scénario -type appelé l'interprète.
La solution
J'ai créé quelques caractéristiques d'exécution des extraits de code et la vérification des résultats de l'interprète.
Vous pouvez jeter un oeil à la page trait d'Snippets. L'idée est de stocker dans une org.specs.util.Property [Snippet] le code à exécuter:
val it: Property[Snippet] = Property(Snippet(""))
"import scala.collection.List" prelude it // will be prepended to any code in the it snippet
"val list: List[Int] = List(1, 2, 3)" snip it // snip some code (keeping the prelude)
"list.add("Chicka-Chicka-Boom-Boom")" add it // add some code to the previously snipped code. A new snip would remove the previous code (except the prelude)
execute(it) must include("error: value add is not a member of List[Int]") // check the interpreter output
Le principal inconvénient que j'ai trouvé avec cette approche était la lenteur de l'interprète. Je ne sais pas encore comment cela pourrait être accéléré.
Eric.