writing unit tests with spock framework
Написання одиничних тестів із Spock Framework: тестові матеріали, твердження та звітність
У цьому Повне керівництво для початківців на Spock , бриф Вступ до Spock Framework та Groovy програмування було подано в нашому попередньому уроці.
У цьому посібнику ми розглянемо всі деталі / кроки, необхідні для початку роботи Блокове тестування в Спок.
Для простоти ми збираємося протестувати просту програму-калькулятор, яка має різні методи, такі як додавання, віднімання, множення, ділення тощо, які приймають цілочисельні параметри і повертають цілочисельний результат.
Що ви дізнаєтесь:
- Модельне тестування за допомогою відео-підручника Spock
- Починаємо
- Ключове слово „def”
- Життєвий цикл специфікації Spock
- Спок Твердження
- Звітність
- Висновок
- Рекомендована література
Модельне тестування за допомогою відео-підручника Spock
Починаємо
Подібно до будь-яких інших модульних модульних тестів, Spock також може використовуватися для написання сценаріїв / тестових випадків для тестованої програми. Ми спробуємо порівняти та порівняти різні функції фреймворка Spock із існуючими / відомими фреймворками, такими як JUnit .
Ключове слово „def”
Спершу спробуємо коротко зрозуміти ключове слово 'def' Groovy. Ключове слово def використовується для визначення типу-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, щоб зробити тести менш зайвими та більш читабельними.
Давайте обговоримо деякі особливості нижче:
Визначення входів / змінних як частини специфікації
Розгляньте можливість проведення декількох тестів, використовуючи однакові вхідні значення. Одним із способів було б ініціалізувати вхідні значення в кожному тесті окремо, інакше ми можемо безпосередньо визначати поля на рівні специфікації та гарантувати, що перед кожним тестом поля будуть ініціалізовані та доступні виконуваному тесту.
Давайте подивимось Приклад для нашого класу калькуляторів .
Ми визначимо вхідні дані на рівні специфікації, щоб вони були доступні з початковими значеннями для всіх тестів, представлених у специфікації.
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 також надає методи налаштування та очищення для виконання спеціальної логіки / завдань за певних подій життєвого циклу виконання тесту.
і очищення
Ці методи викликаються один раз для кожного виконання специфікації і викликаються відповідно до та після виконання тесту. Вони порівнянні з @ BeforeClass та @ Після занять анотації JUnit.
налаштування та очищення
Ці методи викликаються до і після виконання кожного тесту в специфікації.
Ці хуки є правильним місцем для будь-якої логіки / фрагмента коду, який ви хотіли б виконати до і після виконання тесту. Наприклад , Під час очищення ви можете написати код, щоб закрити підключення до бази даних (якщо таке є), яке було використано під час тесту.
Їх можна порівняти з @ BeforeTest та @ 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 називаються твердженням сили (і воно було прийняте Groovy пізніше після введення Spock). Ствердження Спока надають багато діагностичних винятків у випадку будь-яких помилок твердження.
яка найкраща програма для завантаження відео YouTube
Можна легко дізнатися, що пішло не так, просто подивившись діагностику несправності, на відміну від детальної AssertionErrors в JUnit та інших рамках.
Спробуємо зрозуміти це на прикладі та порівняти з JUnit
Ми будемо працювати з простим тестом, який перевіряє рівність рядків і бачимо, яка діагностика генерується у випадку помилки твердження.
Тест Спока
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 } }
Ствердження кинутих винятків
Можна стверджувати, що винятки можуть бути додані до блоку “then” (що означає, коли блок також потрібен). Деталь винятку можна діагностувати, присвоївши викинутому полю і затвердивши необхідні властивості викинутого винятку.
Давайте використаємо той самий клас 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, є доступні бібліотеки, які можна додати у файл збірки, і тепер, коли тести виконуються під час збірки (або безпосереднім виконанням), детальний звіт на основі 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” або виконавши “ чистий тест '.
Можна відкрити index.html файл, щоб отримати узагальнений звіт щодо всіх специфікацій Spock, які були доступні для виконання.
Якщо ви хочете переглянути детальний звіт для конкретної специфікації, натисніть на специфікацію з наведеного вище списку, і ви зможете побачити детальний звіт про невдачі та успіхи.
Висновок
У цьому посібнику ми розглянули основи модульного тестування за допомогою Spock Framework. Ми побачили різні способи та скорочення для написання тверджень та різновиди розширеної діагностичної інформації, створеної структурою Spock для помилок твердження.
Ми також розглянули, як ми можемо створювати тихі звіти на основі HTML для тестів Spock, які включають однакову детальну діагностику для виконаних тестів.
У нашому майбутньому підручнику ви дізнаєтесь про те, як детально писати параметризовані тести зі Spock !!
НАЗАД Підручник | НАСТУПНИЙ підручник
Рекомендована література
- Тестування на основі даних або параметризоване за допомогою Spock Framework
- Запитання для інтерв’ю у Spock (найпопулярніші)
- Spock для інтеграції та функціональних випробувань із селеном
- Спок знущання та придушення (приклади з відеоуроками)
- Підручник із Spock: Тестування за допомогою Spock and Groovy
- Підручник Mockito: Mockito Framework для знущань під час модульного тестування
- Різниця між модульним тестуванням, інтеграційним тестуванням та функціональним тестуванням
- Ключ до успішного модульного тестування - як розробники перевіряють власний код?