writing unit tests with spock framework
Писане на единични тестове с Spock Framework: Тестови елементи, твърдения и отчитане
В това Пълно ръководство за начинаещи на Spock , кратко Въведение в Spock Framework и Groovy програмиране беше даден в предишния ни урок.
В този урок ще разгледаме всички подробности / стъпки, необходими за започване Единично тестване в Спок.
За по-голяма простота ще тестваме просто приложение за калкулатор, което има различни методи като събиране, изваждане, умножение, деление и т.н., като всички те приемат цели параметри и връщат цяло число изход.
Какво ще научите:
- Единично тестване с видео урок Spock
- Приготвяме се да започнем
- Ключова дума „def“
- Животният цикъл на Spock Спецификация
- Спок Утвърждения
- Отчитане
- Заключение
- Препоръчително четене
Единично тестване с видео урок Spock
Приготвяме се да започнем
Подобно на всички други модулни тестови рамки, Spock също може да се използва за писане на сценарии / тестови случаи за тествано приложение. Ще се опитаме да сравним и сравним различните характеристики на рамката Spock със съществуващите / известни рамки като JUnit .
Ключова дума „def“
Нека първо се опитаме да разберем накратко ключовата дума „def“ на Groovy. Ключовата дума def се използва за дефиниране на type-def и може да се използва за деклариране на функция, както и поле / променлива.
„Def“ обикновено се използва, когато не искаме да ограничаваме типа на полето или типа на връщане на метод. Нека да видим някои примери за ключова дума def в грууви клас и всички нейни валидни употреби.
// 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 }
Животният цикъл на Spock Спецификация
Spock spec при изпълнение търси всички дефинирани тестове и ги изпълнява един по един. Има обаче няколко други функционалности / функции, които се предоставят от Spock, за да направят тестовете по-малко излишни и по-четливи.
Нека обсъдим някои функции по-долу:
Определяне на входове / променливи като част от Spec
Помислете за провеждането на множество тестове, като се използват едни и същи входни стойности. Един от начините би бил да се инициализират входните стойности във всеки тест поотделно, в противен случай можем директно да дефинираме полетата на ниво спецификация и да гарантираме, че преди всеки тест полетата ще бъдат инициализирани и достъпни за изпълнявания тест.
Нека да видим пример за нашия клас на приложение на калкулатора .
Ще дефинираме входните данни на ниво спецификация, така че да бъдат достъпни с първоначалните стойности за всички тестове, представени в спецификацията.
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 } }
В тази примерна програма можете да видите, че ние сме дефинирали input1, input2, приложението, което се тества и резултат на ниво спецификация. Това гарантира, че всеки път, когато се изпълнява тест от спец файловете, и инициализираните полета се предават на този тест. Това наистина премахва необходимостта от настройване на тестове всеки път с входни стойности.
Тестови тела
Подобно на повечето рамки за модулно тестване, Spock също предлага методи за настройка и почистване за изпълнение на специална логика / задачи при конкретни събития от жизнения цикъл на изпълнението на теста.
настройка и почистване Спецификация
Тези методи се извикват веднъж за всяко изпълнение на Spec и се извикват съответно преди и след тестовото изпълнение. Те са сравними с @ Преди Клас и @ След часовете анотации на JUnit.
настройка и почистване
Тези методи се извикват преди и след изпълнението на всеки тест в спецификацията.
Тези куки са правилното място за всяка логика / парче код, което искате да изпълните преди и след изпълнението на теста. Например , При почистване можете да напишете код за затваряне на връзката с базата данни (ако има такава), която е била използвана по време на теста.
Те могат да бъдат сравнени с @ Преди Тест и @ AfterTest анотации в JUnit.
Нека да видим Пример за тези тела в нашия тест за приложение на калкулатора.
def setupSpec() { println('###in setup spec!') } def cleanupSpec() { println('###in cleanup spec!') } def setup() { println('>>>in test setup!') } def cleanup() { println('>>>in test cleanup!') }
Ако горният код на тестовото приспособление се добави към спецификация, съдържаща 4 теста, тогава изходът ще бъде както по-долу:
най-добрият безплатен софтуер за часовник за служители
###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!
Спок Утвърждения
Твърденията в Spock се наричат power assert (и то беше прието от groovy по-късно, след като беше представено от Spock). Твърденията на Spock предоставят много диагностични изключения в случай на някакви неуспешни твърдения.
Човек може лесно да разбере какво се е объркало, като просто погледне диагностиката на неизправността, вместо многословно AssertionErrors в JUnit и други рамки.
Нека се опитаме да разберем това с пример и да го сравним с JUnit
Ще работим с прост тест, който проверява за равенство на низовете и ще видим каква диагностика се генерира в случай на неуспех на твърдение.
Тест 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 }
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); }
Spock изход
Condition not satisfied: str1 == str2 | | | hello| hello world false 6 differences (45% similarity) hello(------) hello( world) Expected :hello world Actual :hello
JUnit изход
org.junit.ComparisonFailure: Expected :hello Actual :hello world
Както можете да заключите по-горе, диагностичната информация, предоставена от Spock, има по-добри детайли и е по-лесна за потребителя в сравнение с другите рамки като JUnit.
Съвети и трикове за твърдение
Утвърждаване на няколко елемента наведнъж - Spock предоставя различни стенографии за твърдения и един такъв е обозначението „*“, което позволява да се утвърдят елементите в списъка.
Нека разберем това с пример:
Помислете за клас CityInfo, който има cityName и население като полета. Ще напишем тест на Spock, за да утвърдим имената на градовете, които се намират в дадения списък.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; }
Нека да видим теста сега:
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') }
Както е показано в стенографията на твърдението по-горе, можете да проверите целия списък с помощта на ключовата дума “*”.
Нека също да видим как би изглеждал един провал. Ще премахна името на който и да е град от горното твърдение.
Condition not satisfied: cityList*.cityName == ('Delhi', 'Chennai') | | | | | false | (Mumbai, Delhi, Chennai) (app.CityInfo@31368b99, app.CityInfo@1725dc0f, app.CityInfo@3911c2a7)
Можете да видите, че диагностичната информация за неуспешно твърдение е богата и лесна за разбиране.
Параметър за затваряне на лоста - всеки ().
Нека да видим как можем да използваме параметъра за затваряне, наречен every (), за да добавим твърдение за всеки елемент от списък или колекция. В същия пример, нека опитаме да добавим твърдение, което потвърждава населението на всеки град, ако даденият вход е> 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 } }
Утвърждаване на хвърлени изключения
Изключения могат да се твърдят, че ще бъдат хвърлени в блока „тогава“ (което означава, когато блокът също се изисква). Детайлът на изключението може да бъде диагностициран чрез присвояване на хвърленото изключение на поле и утвърждаване на необходимите свойства на хвърленото изключение.
Нека използваме същия клас CityInfo и да дефинираме метод, който хвърля изключение и да напишем тест за него.
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'); } }
Нека да разгледаме теста сега:
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' }
Отчитане
За да се генерират красиви и подробни отчети, базирани на HTML, има налични библиотеки, които могат да бъдат добавени във файла на компилация и сега, когато тестовете се изпълняват по време на компилацията (или чрез директно изпълнение), в изходна папка.
За да получите генерирани тестови отчети, добавете следните библиотеки към файла build.gradle (и по подобен начин и към файла 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'
Сега изградете проекта и изпълнете тестовете, като стартирате всички тестове в папката „test“ или като изпълните „ тест за почистване на gradle ”.
Можете да отворите index.html файл, за да получите обобщен отчет за всички спецификации на Spock, които са били на разположение за изпълнение.
c срещу c ++ разлики
Ако искате да видите подробния отчет за конкретна спецификация, кликнете върху спецификацията от горния списък и можете да видите подробен отчет за неуспехите, както и за успехите.
Заключение
В този урок разгледахме основите на тестването на модули със Spock Framework. Видяхме различните начини и съкращения за писане на твърдения и вида богата информация за диагностика, генерирана от рамката на Spock за неуспехи в твърдения.
Също така разгледахме как можем да генерираме тихи, доста базирани на HTML отчети за тестовете Spock, които включват същата подробна диагностика за изпълнените тестове.
Нашият предстоящ урок ще ви запознае подробно с писането на параметризирани тестове със Spock в детайли !!
Препоръчително четене
- Управлявано от данни или параметризирано тестване със Spock Framework
- Спок интервю въпроси с отговори (най-популярни)
- Spock за интеграция и функционални тестове със селен
- Спок подигравки и сбиване (Примери с видео уроци)
- Урок за Spock: Тестване със Spock и Groovy
- Mockito Tutorial: Mockito Framework for Mocking in Unit Testing
- Разликите между модулното тестване, интегрираното тестване и функционалното тестване
- Ключ към успешното тестване на единици - Как разработчиците тестват собствения си код?