writing unit tests with spock framework
Rédaction de tests unitaires avec Spock Framework: montages de test, assertions et rapports
Dans ce Guide du débutant complet sur Spock , une brève Introduction sur Spock Framework et la programmation Groovy a été donnée dans notre tutoriel précédent.
Dans ce didacticiel, nous allons parcourir tous les détails / étapes nécessaires pour commencer avec Test unitaire à Spock.
Par souci de simplicité, nous allons tester une application de calcul simple qui a différentes méthodes comme l'addition, la soustraction, la multiplication, la division, etc., qui acceptent toutes des paramètres entiers et renvoient une sortie entière.
Ce que vous apprendrez:
- Test unitaire avec le didacticiel vidéo Spock
- Commencer
- Mot clé 'def'
- Le cycle de vie d'une spécification Spock
- Assertions de Spock
- Rapports
- Conclusion
- lecture recommandée
Test unitaire avec le didacticiel vidéo Spock
Commencer
Semblable à tous les autres frameworks de tests unitaires, Spock peut également être utilisé pour écrire des scénarios / cas de test pour une application en cours de test. Nous allons essayer de comparer et de mettre en contraste les différentes fonctionnalités du framework Spock avec les frameworks existants / connus tels que JUnit .
Mot clé 'def'
Essayons d'abord de comprendre brièvement le mot-clé 'def' de Groovy. Le mot-clé def est utilisé pour définir le type-def et peut être utilisé pour déclarer une fonction ainsi qu'un champ / variable.
'Def' est généralement utilisé lorsque nous ne voulons pas restreindre le type d'un champ ou renvoyer le type d'une méthode. Voyons quelques exemples de mot-clé def dans une classe groovy et toutes ses utilisations valides.
// def as variable types def inputNum = 100 def inputStr = 'hello world!!' def app = new CalculatorApp() // def as return type of function def 'test function'() { // function body here }
Le cycle de vie d'une spécification Spock
Spock spec une fois exécuté recherche tous les tests définis et les exécute un par un. Cependant, il existe peu d'autres fonctionnalités / fonctionnalités fournies par Spock pour rendre les tests moins redondants et plus lisibles.
Voyons quelques fonctionnalités ci-dessous:
Définition des entrées / variables dans le cadre de Spec
Pensez à avoir plusieurs tests utilisant tous les mêmes valeurs d'entrée. Une façon serait d'initialiser les valeurs d'entrée dans chaque test individuellement, sinon nous pouvons définir directement les champs au niveau des spécifications et nous assurer qu'avant chaque test, les champs seront initialisés et disponibles pour le test en cours d'exécution.
Voyons un exemple pour notre classe d'application calculatrice .
Nous définirons les données d'entrée au niveau de la spécification afin qu'elles soient disponibles avec les valeurs initiales pour tous les tests présents dans la spécification.
applications pour télécharger des vidéos sur youtube
class CalculatorAppSpec extends Specification { def input1 = 50 def input2 = 10 def result = 0 def app = new CalculatorApp() def 'addition with valid inputs return expected result'() { when: result = app.add(input1, input2) then: result == 60 } def 'multiplication with valid inputs return expected result'() { when: result = app.multiply(input1, input2) then: result == 500 } def 'division with valid inputs return expected result'() { when: result = app.divide(input1, input2) then: result == 5 } def 'subsctraction with valid inputs return expected result'() { when: result = app.substract(input1, input2) then: result == 40 } }
Dans cet exemple de code, vous pouvez voir que nous avons défini input1, input2, l'application testée et le résultat au niveau des spécifications. Cela garantit que chaque fois qu'un test est exécuté à partir des fichiers de spécifications, et que les champs initialisés sont transmis à ce test. Cela élimine en effet la nécessité de configurer des tests à chaque fois avec des valeurs d'entrée.
Appareils d'essai
Semblable à la plupart des frameworks de tests unitaires, Spock fournit également des méthodes de configuration et de nettoyage pour exécuter une logique / des tâches spéciales lors d'événements spécifiques du cycle de vie de l'exécution des tests.
setupSpec et nettoyageSpec
Ces méthodes sont appelées une fois pour chaque exécution de Spec et sont appelées respectivement avant et après l'exécution du test. Ceux-ci sont comparables à @ Avant les cours et @ Après les cours annotations de JUnit.
configuration et nettoyage
Ces méthodes sont appelées avant et après l'exécution de chaque test dans la spécification.
Ces hooks sont le bon endroit pour toute logique / morceau de code que vous souhaitez exécuter avant et après l'exécution du test. Par exemple , Lors du nettoyage, vous pouvez écrire un code pour fermer la connexion à la base de données (le cas échéant) qui a été utilisée pendant le test.
Ceux-ci peuvent être comparés à @ AvantTest et @ Après le test annotations dans JUnit.
Voyons un exemple de ces appareils dans notre test d’application de calculatrice.
def setupSpec() { println('###in setup spec!') } def cleanupSpec() { println('###in cleanup spec!') } def setup() { println('>>>in test setup!') } def cleanup() { println('>>>in test cleanup!') }
Si le code de montage de test ci-dessus est ajouté à une spécification contenant 4 tests, la sortie sera comme ci-dessous:
###in setup spec! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! ###in cleanup spec!
Assertions de Spock
Les affirmations de Spock sont appelées affirmation de pouvoir (et elle a été adoptée par groovy plus tard après avoir été introduite par Spock). Les assertions Spock fournissent de nombreuses exceptions de diagnostic en cas d'échec des assertions.
On peut facilement découvrir ce qui a mal tourné en regardant simplement le diagnostic de panne par opposition à verbeux AssertionErreurs dans JUnit et d'autres frameworks.
Essayons de comprendre cela avec un exemple et comparons-le avec JUnit
Nous travaillerons avec un test simple qui vérifie l’égalité des chaînes et voit quels diagnostics sont générés en cas d’échec d’une assertion.
Test de Spock
def 'check case-insensitive equality of 2 strings'() { given: 'two input strings' String str1 = 'hello' String str2 = 'HELLO world' when: 'strings are lowercased' str1 = str1.toLowerCase() str2 = str2.toLowerCase() then: 'equal strings should return success' str1 == str2 }
Test JUnit
@Test public void compareStrings_withValidInput_shouldReturnSuccess() { // Arrange String str1 = 'hello'; String str2 = 'HELLO world'; // Act str1 = str1.toLowerCase(); str2 = str2.toLowerCase(); // Assert Assert.assertEquals(str1,str2); }
Sortie Spock
Condition not satisfied: str1 == str2 | | | hello| hello world false 6 differences (45% similarity) hello(------) hello( world) Expected :hello world Actual :hello
Sortie JUnit
org.junit.ComparisonFailure: Expected :hello Actual :hello world
Comme vous pouvez le déduire ci-dessus, les informations de diagnostic fournies par Spock ont de meilleurs détails et sont plus conviviales par rapport aux autres frameworks tels que JUnit.
Trucs et astuces d'assertion
Affirmation de plusieurs éléments à la fois - Spock fournit divers raccourcis pour les assertions et l'un d'eux est la notation «*» qui permet d'affirmer les éléments de la liste.
Comprenons cela avec un exemple:
Considérez une classe CityInfo ayant cityName et population comme champs. Nous écrirons un test de Spock pour affirmer les noms des villes qui sont là dans la liste donnée.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; }
Voyons maintenant le test:
modèles de cycle de vie de développement logiciel pdf
def 'Assert multiple elements of list' () { given: def cityList = new LinkedList() cityList.add(new CityInfo('Mumbai', 120)) cityList.add(new CityInfo('Delhi', 80)) cityList.add(new CityInfo('Chennai', 100)) expect: cityList*.cityName == ('Mumbai', 'Delhi', 'Chennai') }
Comme indiqué dans le raccourci d'assertion ci-dessus, vous pouvez valider la liste entière à l'aide du mot-clé «*».
Voyons également à quoi aurait ressemblé un échec. Je supprimerai le nom d'une ville de l'affirmation ci-dessus.
Condition not satisfied: cityList*.cityName == ('Delhi', 'Chennai') | | | | | false | (Mumbai, Delhi, Chennai) (app.CityInfo@31368b99, app.CityInfo@1725dc0f, app.CityInfo@3911c2a7)
Vous pouvez voir que les informations de diagnostic d'échec d'assertion sont riches et faciles à comprendre.
Exploiter le paramètre de fermeture - chaque ().
Voyons comment nous pouvons tirer parti du paramètre de fermeture nommé every () pour ajouter une assertion pour chaque élément d'une liste ou d'une collection. Dans le même exemple, essayons d'ajouter une assertion qui valide la population de chaque ville si l'entrée donnée est> 50.
def 'Assert multiple elements of list' () { given: def cityList = new LinkedList() cityList.add(new CityInfo('Mumbai', 120)) cityList.add(new CityInfo('Delhi', 80)) cityList.add(new CityInfo('Chennai', 100)) expect: cityList*.cityName == ('Mumbai', 'Delhi', 'Chennai') and: cityList.population.every() { it > 50 } }
Affirmation d'exceptions levées
Des exceptions peuvent être déclarées pour être lancées dans le bloc «alors» (ce qui signifie que lorsque le bloc est également requis). Le détail de l'exception peut être diagnostiqué en affectant l'exception levée à un champ et en affirmant les propriétés requises de l'exception levée.
Utilisons la même classe CityInfo et définissons une méthode qui lève une exception et écrivons un test pour celle-ci.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; public CityInfo() { } public int getCleanlinessScore() { throw new RuntimeException('method not implemented'); } }
Examinons maintenant le test:
def 'cleanliness score throws runtime exception with message - method not implemented'() { given: CityInfo app = new CityInfo(); when: app.cleanlinessScore() then: def e = thrown(RuntimeException) e.message == 'method not implemented' }
Rapports
Afin de générer des rapports HTML magnifiques et détaillés, il existe des bibliothèques disponibles qui peuvent être ajoutées dans le fichier de construction et maintenant chaque fois que les tests sont exécutés pendant la construction (ou par exécution directe), un rapport détaillé basé sur HTML sera généré dans le dossier de sortie.
Afin d'obtenir les rapports de test générés, ajoutez les bibliothèques suivantes au fichier build.gradle (et de même pour le fichier Maven pom.xml).
testCompile 'com.athaydes:spock-reports:1.6.1' testCompile 'org.slf4j:slf4j-api:1.7.13' testCompile 'org.slf4j:slf4j-simple:1.7.13'
Construisez maintenant le projet et exécutez les tests en exécutant tous les tests dans le dossier «test» ou en exécutant « test de nettoyage gradle ».
Tu peux ouvrir index.html fichier pour obtenir un rapport récapitulatif de toutes les spécifications Spock disponibles pour être exécutées.
Si vous voulez voir le rapport détaillé pour une spécification spécifique, cliquez sur la spécification dans la liste ci-dessus et vous pouvez voir un rapport détaillé des échecs ainsi que des réussites.
Conclusion
Dans ce didacticiel, nous avons abordé les bases des tests unitaires avec Spock Framework. Nous avons vu les différentes manières et raccourcis d'écrire des assertions et le type d'informations de diagnostic riches générées par le framework Spock pour les échecs d'assertions.
Nous avons également examiné comment nous pourrions générer de jolis rapports HTML discrets pour les tests Spock qui incluent les mêmes diagnostics détaillés pour les tests exécutés.
Notre prochain tutoriel vous expliquera en détail l'écriture de tests paramétrés avec Spock !!
Tutoriel PREV | Tutoriel SUIVANT
lecture recommandée
- Tests pilotés par les données ou paramétrés avec Spock Framework
- Questions d'entrevue Spock avec réponses (les plus populaires)
- Spock pour l'intégration et les tests fonctionnels avec sélénium
- Spock Mocking and Stubbing (Exemples avec des didacticiels vidéo)
- Tutoriel Spock: Test avec Spock et Groovy
- Tutoriel Mockito: Framework Mockito pour la simulation dans les tests unitaires
- Les différences entre les tests unitaires, les tests d'intégration et les tests fonctionnels
- La clé du succès des tests unitaires - Comment les développeurs testent leur propre code?