writing unit tests with spock framework
Proves d'unitat d'escriptura amb Spock Framework: accessoris de prova, afirmacions i informes
En aquest Guia completa per a principiants a Spock , una breu Introducció a la programació de Spock Framework i Groovy es va donar al nostre tutorial anterior.
En aquest tutorial, recorrerem tots els detalls / passos necessaris per començar Proves d’unitat a Spock.
Per simplificar, anem a provar una aplicació de calculadora senzilla que té diferents mètodes com sumar, restar, multiplicar, dividir, etc., tots els quals accepten paràmetres enters i retornen una sortida sencera.
Què aprendreu:
- Prova d’unitat amb Spock Video Tutorial
- Començant
- Paraula clau 'def'
- Especificació del cicle de vida d'un Spock
- Afirmacions de Spock
- Informes
- Conclusió
- Lectura recomanada
Prova d’unitat amb Spock Video Tutorial
Començant
De manera similar a qualsevol altre marc de prova de la unitat, Spock també es pot utilitzar per escriure escenaris / casos de prova per a una aplicació sotmesa a prova. Intentarem comparar i contrastar les diferents característiques del marc Spock amb els marcs existents / coneguts com JUnit .
Paraula clau 'def'
Intentem primer comprendre en breu la paraula clau 'def' de Groovy. La paraula clau def s'utilitza per definir el tipus-def i es pot utilitzar per declarar una funció, així com un camp / variable.
'Def' s'utilitza generalment quan no volem restringir el tipus de camp o retornar el tipus d'un mètode. Vegem alguns exemples de paraules clau definides en una classe fantàstica i tots els seus usos vàlids.
// 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 }
Especificació del cicle de vida d'un Spock
L'especificació de Spock quan s'executa busca totes les proves definides i les executa una per una. Tot i això, hi ha poques altres funcions / funcions que proporciona Spock per fer les proves menys redundants i més llegibles.
A continuació, parlem d'algunes funcions:
Definició d'entrades / variables com a part de l'espec
Penseu en la possibilitat de realitzar diverses proves amb els mateixos valors d’entrada. Una manera seria inicialitzar els valors d’entrada de cada prova individualment, en cas contrari podem definir directament els camps a nivell d’especificació i assegurar-nos que abans de cada prova, els camps s’inicialitzaran i estaran disponibles per a la prova que s’executa.
Vegem un exemple per a la nostra classe d'aplicacions de calculadores .
Definirem les dades d’entrada a nivell d’especificació perquè estiguin disponibles amb els valors inicials de totes les proves presents a l’especificació.
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 } }
En aquest exemple de codi, podeu veure que hem definit input1, input2, l'aplicació que es prova i el resultat a nivell d'especificació. Això garanteix que cada vegada que s'executa una prova des dels fitxers d'especificacions i els camps inicialitzats es passen a aquesta prova. De fet, això elimina la necessitat de configurar proves cada vegada amb valors d’entrada.
Dispositius de prova
De manera similar a la majoria dels marcs de proves d’unitats, Spock també proporciona mètodes de configuració i neteja per a l’execució de tasques i lògiques especials en esdeveniments específics del cicle de vida de l’execució de la prova.
setupSpec & cleanupSpec
Aquests mètodes es diuen una vegada per a cada execució de Spec i es diuen abans i després de l'execució de la prova, respectivament. Aquests són comparables a @ BeforeClass i @ Després de classe anotacions de JUnit.
configuració i neteja
Aquests mètodes es diuen abans i després de l'execució de cada prova a l'especificació.
Aquests ganxos són el lloc adequat per a qualsevol lògica / tros de codi que vulgueu executar abans i després de l'execució de la prova. Per exemple , A la neteja, podeu escriure un codi per tancar la connexió de base de dades (si n'hi ha) que es va utilitzar durant la prova.
Es poden comparar amb @ BeforeTest i @ AfterTest anotacions a la JUnit.
Vegem un exemple d’aquests accessoris a la nostra prova d’aplicació de calculadores.
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 el codi del dispositiu de prova anterior s’afegeix a una especificació que conté 4 proves, la sortida serà la següent:
###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!
Afirmacions de Spock
Les afirmacions de Spock s'anomenen power assert (i va ser adoptada per Groovy més tard després de ser introduïda per Spock). Les afirmacions de Spock ofereixen moltes excepcions diagnòstiques en cas de fallades de l'afirmació.
Es pot esbrinar fàcilment què ha fallat simplement mirant el diagnòstic d’errors en lloc del detallat AssertionErrors a JUnit i altres marcs.
Intentem entendre-ho amb un exemple i contrastem-ho amb JUnit
Treballarem amb una prova senzilla per comprovar la igualtat de cadenes i veure quins diagnòstics es generen en cas d’error de l’asserció.
Prova 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 }
Prova 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); }
Sortida Spock
Condition not satisfied: str1 == str2 | | | hello| hello world false 6 differences (45% similarity) hello(------) hello( world) Expected :hello world Actual :hello
Sortida JUnit
org.junit.ComparisonFailure: Expected :hello Actual :hello world
Com es pot deduir a la part superior, la informació de diagnòstic proporcionada per Spock té millors detalls i és més fàcil d'utilitzar en comparació amb altres marcs com JUnit.
Consells i trucs per afirmar
Afirmació de diversos elements alhora: Spock proporciona diverses taquigrafies per afirmacions i una d’aquestes és la notació “*” que permet fer valer els elements de la llista.
Entenguem això amb un exemple:
Penseu en una classe CityInfo que tingui cityName i població com a camps. Escriurem una prova de Spock per afirmar els noms de les ciutats que hi ha a la llista donada.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; }
Vegem la prova ara:
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') }
Com es mostra a la abreviatura de l’asserció anterior, podeu validar tota la llista amb l’ajut de la paraula clau “*”.
Vegem també com hauria estat un fracàs. Eliminaré el nom de qualsevol ciutat de l'afirmació anterior.
Condition not satisfied: cityList*.cityName == ('Delhi', 'Chennai') | | | | | false | (Mumbai, Delhi, Chennai) (app.CityInfo@31368b99, app.CityInfo@1725dc0f, app.CityInfo@3911c2a7)
Podeu veure que la informació de diagnòstic del fracàs de l'afirmació és rica i fàcil de comprendre.
Aprofitant el paràmetre de tancament: every ().
Vegem, com podem aprofitar el paràmetre de tancament anomenat every () per afegir una afirmació per a cada element d'una llista o col·lecció. En el mateix exemple, provem d’afegir una afirmació que valida la població de cada ciutat si l’entrada aportada és> 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 } }
Afirmació d’excepcions llançades
Es pot afirmar que es llancen excepcions al bloc 'llavors' (que significa un quan també es requereix el bloc). Es pot diagnosticar el detall de l'excepció assignant l'excepció generada a un camp i afirmant les propietats necessàries de l'excepció generada.
Utilitzem la mateixa classe de CityInfo i definim un mètode que genera una excepció i escrivim-ne una prova.
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'); } }
Vegem la prova ara:
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' }
Informes
Per generar informes bells i detallats basats en HTML, hi ha biblioteques disponibles que es poden afegir al fitxer de compilació i ara, sempre que s’executin les proves durant la compilació (o mitjançant l’execució directa), es generarà un informe detallat basat en html. carpeta de sortida.
Per obtenir els informes de proves generats, afegiu les biblioteques següents al fitxer build.gradle (i de manera similar també per al fitxer pom.xml de Maven).
testCompile 'com.athaydes:spock-reports:1.6.1' testCompile 'org.slf4j:slf4j-api:1.7.13' testCompile 'org.slf4j:slf4j-simple:1.7.13'
Ara creeu el projecte i executeu les proves executant totes les proves a la carpeta 'test' o executant ' prova de neteja gradle '.
com obrir el fitxer de dades en pdf
Podeu obrir index.html per obtenir un informe resumit de totes les especificacions de Spock que estaven disponibles per executar-se.
Si voleu veure l'informe detallat d'una Especificació específica, feu clic a l'especificació de la llista anterior i podreu veure un informe detallat d'errors i d'èxits.
Conclusió
En aquest tutorial, hem tractat els conceptes bàsics de la prova d’unitat amb Spock Framework. Vam veure les diferents maneres i abreviatures per escriure afirmacions i el tipus d'informació de diagnòstic enriquida generada pel marc Spock per a fallades en l'assertió.
També vam examinar com podríem generar informes silenciosos i basats en HTML per a les proves Spock, que inclouen els mateixos diagnòstics detallats per a les proves executades.
El nostre proper tutorial us informarà sobre com escriure detalls parametritzats amb Spock !!
Lectura recomanada
- Proves basades en dades o parametritzades amb Spock Framework
- Preguntes d'entrevistes de Spock amb respostes (més populars)
- Spock per a la integració i proves funcionals amb seleni
- Spock burleta i obstrucció (exemples amb tutorials de vídeo)
- Spock Tutorial: proves amb Spock i Groovy
- Tutorial de Mockito: marc Mockito per burlar-se de les proves unitàries
- Les diferències entre la prova unitària, la prova d’integració i la prova funcional
- Clau per a la prova unitària amb èxit: com els desenvolupadors proven el seu propi codi?