Si vous essayez d'utiliser un framework de test appelé framework spock pour les tests unitaires en Java Je voudrais le présenter car c'était plus pratique que ce à quoi je m'attendais. Cliquez ici pour le site officiel → Spock Framework
Puisqu'il y a des endroits où le flux jusqu'à l'introduction est un peu difficile à comprendre, J'ai essayé d'écrire un article de la première introduction et d'écrire un test en utilisant spock. Je suis content si tu peux penser à Spock ouais.
Au fait, mon environnement est Ubuntu 18.04 LTS + eclipse, Bien sûr, vous pouvez utiliser spock dans un environnement Windows. Est-ce vrai?
OS: Ubuntu 18.04 LTS IDE: eclipse
Cette fois, nous allons écrire le code de test avec groovy, donc nous allons introduire un plug-in pour gérer groovy dans eclipse.
Help > Install New Software >
Pour l'URL, reportez-vous à ce site (groovy-eclipse) et utilisez celui qui correspond à la version d'eclipse que vous utilisez. Vérifiez le paquet principal et terminez.
Cette fois, nous utiliserons gradle pour procéder rapidement. Accédez à n'importe quel répertoire dans lequel vous souhaitez placer le code source et exécutez gradle.
$ gradle init --type java-application --test-framework spock
c'est tout. Vous avez maintenant un projet qui utilise spock pour les tests unitaires. Facile!
Si ce n'est pas nouveau, ajoutez la description au build.gradle existant (pom.xml pour maven).
build.gradle
plugins {
id 'groovy'
}
repositories {
jcenter()
}
dependencies {
testImplementation 'org.codehaus.groovy:groovy-all:2.4.17'
testImplementation 'org.spockframework:spock-core:1.0-groovy-2.4'
testImplementation 'junit:junit:4.12'
}
Google Code Archive - Long-term storage for Google Code Project Hosting. Il est émietté, alors gardez celui en forme.
Spock version | Groovy version | JUnit version | Grails version | Spring version |
---|---|---|---|---|
0.5-groovy-1.6 | 1.6.1-1.6.x | 4.7-4.x | 1.2.0-1.2.x | 2.5.0-3.x |
0.5-groovy-1.7 | 1.7.0-1.7.x | 4.7-4.x | 1.3.0-1.3.x | 2.5.0-3.x |
0.6-groovy-1.7 | 1.7.0-1.7.x | 4.7-4.x | 1.3.0-1.3.x | 2.5.0-3.x |
0.6-groovy-1.8 | 1.8.1-1.8.x | 4.7-4.x | 2.0-2.x | 2.5.0-3.x |
0.7-groovy-1.8 | 1.8.1-1.8.x | 4.7-4.x | 2.0-2.x | 2.5.0-3.x |
0.7-groovy-2.0 | 2.0.0 -2.x.x | 4.7-4.x | 2.2-2.x | 2.5.0-3.x |
1.0-groovy-2.0 | 2.0.0 -2.2.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
1.0-groovy-2.3 | 2.3.0 -2.3.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
1.0-groovy-2.4 | 2.4.0 -2.x.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
Écrivons un test comme un essai. L'emplacement du test est src / test / groovy / [nom du package] /. L'extension est .groovy. Assurez-vous qu'il est dans le même package que la classe testée. Le nom de la classe de test est [Nom de la classe à tester] + Spec. En effet, il représente la spécification de la classe testée, même si cela s'appelle un test unitaire. C'est mon engagement, donc je pense que tout va bien.
Faites comme ça.
Maintenant, implémentons une méthode qui calcule le montant TTC (8%) de la taxe à la consommation.
TaxCalculaterSpec.groovy
import spock.lang.Specification
class TaxCalculaterSpec extends Specification {
def sut = new TaxCalculater()
def "calculate:Calculez le montant TTC"() {
expect:
sut.calculate(100) == 108
}
}
Soudain, j'ai écrit un test. Comme je l'ai dit plus tôt, il s'agit d'une spécification, donc le nom de la méthode de test est quelque chose qui représente la spécification. À ce stade, la construction ne réussira pas avant que le test ne réussisse, alors écrivez le code principal.
TaxCalculater.java
public class TaxCalculater {
public int calculate(int value) {
return 0;
}
}
Eh bien, quand j'essaye de l'exécuter ...
Condition not satisfied:
sut.calculate(100) == 108
| | |
| 0 false
Oui, le test a brillamment échoué. C'est vrai, cela échoue car c'est une méthode qui renvoie 0.
Le point d'intérêt est la façon dont ce message apparaît. À la suite de l'exécution de la méthode, 0 a été renvoyé, donc la comparaison avec 108 est devenue fausse et le test a échoué. Vous pouvez voir en un coup d'œil. Cette facilité de compréhension est l'un des attraits de Spock.
Maintenant que nous avons confirmé que le test échoue, écrivons du code qui passera le test.
TaxCalculater.java
public class TaxCalculater {
public int calculate(int value) {
return 108;
}
}
Le test a réussi. Je l'ai fait (je ne l'ai pas fait)
Avec un seul test, vous ne savez pas si ce test est vraiment valide. Peut-être que cela renvoie simplement une valeur fixe. Par conséquent, il existe des variations de valeurs et de situations. Avec jUnit, vous pouvez augmenter le nombre d'appels de méthode dans de tels cas. C'est assez ennuyeux à cause du code en double, mais spock le rend un peu plus facile à lire.
TaxCalculaterSpec.groovy
class TaxCalculaterSpec extends Specification {
def sut = new TaxCalculater()
def "Calculez le montant TTC"() {
expect:
sut.calculate(value) == $result
where:
value |$result
100 |108
200 |216
}
}
où! Quel mec! Soudain, un style d'écriture inconnu est sorti. C'est là une notation qui vous permet d'écrire une combinaison de valeurs qui s'écrit comme markdown. L'exemple ci-dessus montre que la méthode «calculer le montant TTC» est répétée pour le modèle. Puisqu'il existe deux modèles, cette méthode de test sera exécutée deux fois.
Si vous exécutez le test dans cet état, il échouera comme ceci.
Condition not satisfied:
sut.calculate(value) == $result
| | | | |
| 108 200 | 216
| false
216 est la valeur attendue, mais 108 est renvoyé, donc c'est vrai. C'est la mise en œuvre. On ne peut rien y faire.
Donc, je vais modifier l'implémentation.
TaxCalculater.java
public class TaxCalculater {
public int calculate(int value) {
return (int)(value * 1.08);
}
}
Le test est maintenant réussi.
Ajoutons une spécification à la méthode de calcul du montant TTC. Ajoutez une spécification selon laquelle «les valeurs après la virgule décimale incluses dans le montant TTC sont arrondies au premier chiffre».
TaxCalculaterSpec.groovy
class TaxCalculaterSpec extends Specification {
def sut = new TaxCalculater()
def "Calculez le montant TTC"() {
expect:
sut.calculate(value) == $result
where:
value |$result
100 |108
200 |216
and: "Les valeurs inférieures à la virgule décimale incluses dans le montant TTC sont arrondies au premier chiffre."
111 |120
}
}
Ajouté au modèle where. 111 est 119,88 multiplié par 1,08, donc la valeur attendue doit être 120.
Condition not satisfied:
sut.calculate(value) == $result
| | | | |
| 119 111 | 120
| false
Il a été tronqué! !! (Je savais) Alors, mettons dans un processus d'arrondi.
TaxCalculater.java
public class TaxCalculater {
public int calculate(int value) {
return (int)(Math.round(value * 1.08));
}
}
De cette façon, une fois les spécifications finalisées, nous ajouterons des modèles au test. Il est très facile de voir si vous écrivez les spécifications telles que les valeurs limites dans le test comme décrit ci-dessus. Et écrire un test vous donnera le courage de refactoriser.
TaxCalculater.java
public class TaxCalculater {
private final static double taxRate = 1.08;
public int calculate(int value) {
return (int)(Math.round(value * taxRate));
}
}
J'ai indiqué le taux d'imposition, mais le test réussit, il n'y a donc pas de problème. N'aimez-vous pas que le nom de la variable à valeur fixe soit camel case? Si tel est le cas, corrigeons-le et exécutons le test. C'est sûr si le test réussit.
L'une des spécifications est qu'une exception se produit sous certaines conditions. Écrivons un test qui lève une exception.
TaxCalculaterSpec.groovy
def "Une exception se produit lors du calcul du montant TTC à partir d'une valeur négative"() {
when:
sut.calculate(-1000)
then:
thrown(ApplicationException)
}
C'est facile à comprendre! Faisons un test.
Expected exception of type 'org.omg.CORBA.portable.ApplicationException', but no exception was thrown
at org.spockframework.lang.SpecInternals.checkExceptionThrown(SpecInternals.java:79)
at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:66)
at spockSampleProject.TaxCalculaterSpec.Une exception se produit lors du calcul du montant TTC à partir d'une valeur négative(TaxCalculaterSpec.groovy:27)
Le test a échoué car ApplicationException était censée être levée mais ne l'a pas été.
TaxCalculater.java
public int calculate(int value) throws ApplicationException {
if (value < 0) {
throw new ApplicationException(null, null);
}
return (int) (Math.round(value * taxRate));
}
Si vous l'implémentez pour lever une exception si elle est négative et relancez le test, tout réussira. Je l'ai fait (je l'ai fait)
Si vous décidez d'écrire la spécification du nom de méthode de la classe de test en japonais, le rapport sera beaucoup plus facile à lire.
Si vous regardez cela, vous pouvez comprendre les spécifications.
Personnellement, c'est beaucoup plus facile à lire que javadoc, donc je n'ai pas besoin d'écrire javadoc.
Je pense écrire correctement un test unitaire.
J'ai essayé la programmation pilotée par les tests en utilisant le framework spock, Qu'est-ce que tu penses.
Je serais heureux si vous pouviez exprimer la bonté de pouvoir rédiger les spécifications clairement et facilement. En plus du contenu introduit cette fois, il est assez puissant que vous puissiez écrire des tests moqueurs sans utiliser une bibliothèque fictive telle que mockit. Bien entendu, vous pouvez également tester les données en combinaison avec DbUnit. J'aimerais écrire ces articles bientôt.