Статьи

Первый взгляд на структуру тестирования Спока

Спок: отличный тестовый фреймворк

Эта статья является выдержкой из  тестирования Java со Споком  Константиносом Капелонисом. Spock — это новая тестовая среда, реализованная в Groovy, которая может тестировать как Java, так и Groovy-код. В отличие от JUnit, он поставляется со встроенным макетом / заглушкой и несколькими другими вкусностями. Сэкономьте 39% на тестировании Java со Споком с кодом 15dzamia на manning.com.

При представлении новой библиотеки / языка / фреймворка все ожидают
простого примера для иллюстрации. В этой статье я покажу вам, как выглядит тест Спока в минимальном, но полностью функциональном примере

Вот класс Java, который мы будем тестировать. Для сравнения сначала показан возможный тест JUnit, так как JUnit — это структура тестирования де-факто для Java. 

Тестируемый класс Java перечисления 1 и тест JUnit  

public class Adder { #A  	
	public int add(int a, int b) 
 { 
 	 return a+b; 
 	} 
} 
public class AdderTest {    #B 
 	@Test 
 	public void simpleTest() 
 	{ 
 	 Adder adder = new Adder(); #C 
 	 assertEquals("1 + 1 is 2",2,adder.add(1, 1)); #D 
 	} 
 	@Test 
 	public void orderTest() #E 
 	{ 
 	 Adder adder = new Adder(); 
 	 assertEquals("Order does not matter ",5,adder.add(2, 3)); #F
  assertEquals("Order does not matter ",5,adder.add(3, 2)); 
 	} 
} 

#A Тривиальный класс, который будет тестироваться (он же тестируемый класс) 
#B Тестовый пример для рассматриваемого класса 
#C Инициализация тестируемого класса 
#D JUnit Утверждение assert, которое сравнивает 2 и результат сложения (1,1) 
#EA Второй сценарий для теста в классе 
#F Два утверждения assert, которые сравнивают 5 с добавлением 2 и 3  

Мы представляем два метода тестирования, один из которых проверяет основные функциональные возможности нашего класса Adder, а другой — тестирует порядок аргументов в нашем методе «add».

Запуск этого теста JUnit в среде разработки Eclipse (щелкните правой кнопкой мыши файл .java и выберите в меню команду «Выполнить как-> тест Junit»):

Рисунок 1 — Запуск теста JUnit в Eclipse

Очень простой тест со Споком

И вот такой же тест в Groovy / Spock. Опять же, этот тест проверяет правильность класса Java Adder, который создает сумму двух чисел. 

Тест Спока перечисления 2 для Java-класса Adder 

class AdderSpec extends spock.lang.Specification{ #A  	
def "Adding two numbers to return the sum"() { #B  	 
  when: "a new Adder class is created" #C  	 
  def adder = new Adder(); #D 
 
 	 then: "1 plus 1 is 2" #E 
 	 adder.add(1, 1) == 2 #F 
 	} 
 	 def "Order of numbers does not matter"() { #G   	 
  when: "a new Adder class is created"  	
  def adder = new Adder(); 
 
 	 then: "2 plus 3 is 5" 
 	 adder.add(2, 3) == 5 #H 
 	  
 	 and: "3 plus 2 is also 5" #I  	 
  adder.add(3, 2) == 5 
 	} 
} 

#A Все тесты Spock расширяют класс Specification 
#BA Groovy методом с понятным для человека именем, содержащим тестовый сценарий 
#CA «когда» блок, который устанавливает сцену 
#D Инициализация тестируемого Java-класса 
#EA «then» блок, который будет содержать проверочный код 
#FA Groovy assert оператор #G 
Еще один тестовый сценарий 
#IA «и» блок, который сопровождает блок «then»

Если вы никогда не видели Groovy-код раньше, этот сегмент Спока действительно покажется вам очень странным. В коде есть смешанные строки вещей, которые вы знаете (например, первая строка с ключевым словом extends ) и вещи, совершенно чуждые вам, например ключевое слово def .

С другой стороны, если вы уже знакомы с концепциями проектирования на основе поведения (BDD), вы будете знакомы с шаблоном тестирования функций «когда / тогда».

ОТБОРЫ ОТ ЭТИХ ПРИМЕРОВ КОДА

Что вам нужно взять из этого примера кода:

· Почти англоязычный поток кода. Очень легко увидеть, что тестируется, даже если вы бизнес-аналитик или не знаете Groovy.

· Отсутствие каких-либо утверждений утверждения. Спок имеет декларативный синтаксис, в котором вы объясняете, что считаете правильным поведением.

Итак, как вы проводите этот тест? Вы запускаете его так же, как тест JUnit! Опять вы щелкаете правой кнопкой мыши по классу Groovy и выбираете Run as -> Junit test во всплывающем меню. Результат в Eclipse выглядит так: 

Рисунок 2 — Запуск теста Спока в Eclipse

Кроме самых описательных имен методов, в этом тривиальном примере нет большой разницы между результатами JUnit и Спока.

Некоторая сила Спока начнет проявляться в нашем следующем примере.

Проверка неудачных испытаний с помощью Спока

Одним из важных моментов в коде Спока является отсутствие утверждений assert по сравнению с JUnit. В предыдущем разделе вы увидели, что происходит, когда все тесты пройдены, и в Eclipse показана счастливая зеленая полоса. Но как Спок справляется с неудачами тестов?

Чтобы продемонстрировать преимущество над JUnit, мы добавим еще один (тривиальный) класс Java, который мы хотим протестировать. 

public class Multiplier { 
	 	public int multiply(int a, int b) 
	 	{ 
	 	 	return a * b; 
	 	} 
} 

Для этого класса мы также напишем соответствующий тест JUnit. Но в качестве дополнительного поворота (для демонстрационных целей) мы хотим протестировать этот класс не только сам по себе, но и в связи с классом Adder, показанным в предыдущем разделе. 

Перечисление 3 Тест JUnit для двух классов Java 
public class MultiplierTest { 
 	@Test 
 	public void simpleMultiplicationTest() 
 	{ 
 	 Multiplier multi = new Multiplier(); 
 	 assertEquals("3 times 7 is 21",21,multi.multiply(3, 7)); 
 	} 
 	@Test 
 	public void combinedOperationsTest() #A 
 	{ 
 	 Adder adder = new Adder(); #B 
 	 Multiplier multi = new Multiplier(); #C 
 	  
 	 assertEquals("4 times (2 plus 3) is 20", #D 
 	  	      20,multi.multiply(4, adder.add(2, 3))); 
 	 assertEquals("(2 plus 3) times 4 is also 20",   	 	 
         20,multi.multiply(adder.add(2, 3),4)); 
 	} 
} 

#A Тестовый сценарий, который будет проверять два Java-класса одновременно 
#B Создание первого Java-класса 
#C Создание второго Java-класса 
#D Проверка математического результата, полученного из обоих Java-классов

Запуск этого модульного теста приведет к зеленой полосе, поскольку оба теста пройдены.

А теперь для эквивалентного теста Спока: 

Тест Спока перечисления 4 для двух классов Java 

class MultiplierSpec extends spock.lang.Specification{  
	def "Multiply two numbers and return the result"() {  	 
  when: "a new Multiplier class is created"  	 
  def multi = new Multiplier(); 
 
 	 then: "3 times 7 is 21"  	 
   multi.multiply(3, 7) == 21 
 	} 

 	def "Combine both multiplication and addition"() { #A  	 
  when: "a new Multiplier and Adder classes are created"  	
  def adder = new Adder(); #B  	 
  def multi = new Multiplier() #C 
 
 	 then: "4 times (2 plus 3) is 20" #D  	
  multi.multiply(4, adder.add(2, 3)) == 20 
 	  
 	 and: "(2 plus 3) times 4 is also 20"  	 
  multi.multiply(adder.add(2, 3),4) == 20  	 
 	} 
} 

#A Тестовый сценарий, который будет проверять два Java-класса одновременно
#B Создание первого Java-класса 
#C Создание второго Java-класса 
#D Проверка математического результата, полученного из обоих Java-классов 

Давайте введем искусственную ошибку в нашем коде, чтобы увидеть, как JUnit и Spock справляются с ошибками. Чтобы имитировать реальную ошибку, мы представим ее в классе Multiplier, но только для особого случая. 

Перечисление 5, Представляющее искусственную ошибку в тестируемом классе Java 

public class Multiplier { 
 	public int multiply(int a, int b) 
 	{ 
 	 if(a == 4)  #A 
 	 {  	  	return 5 * b; //multiply an extra time. 
 	 } 
 	 return a *b; 
 	} 
} 

Теперь давайте запустим весь тест JUnit и посмотрим, что произойдет.

Рисунок 3 — Сбой теста JUnit в Eclipse

У нас есть провал теста. Заметили что-нибудь странное здесь? Поскольку ошибка, которую мы ввели, очень неуловима, JUnit говорит нам:

· Добавление само по себе работает нормально.

Умножение само по себе работает нормально.

· Когда они оба бегут вместе, у нас проблемы.

Но в чем проблема? Ошибка в коде сложения или умножении? Мы не можем сказать, просто посмотрев на результат теста (хорошо, хорошо, математика здесь может дать вам подсказку в этом примере). 

 Нам нужно вставить отладчик в модульный тест, чтобы выяснить, что произошло. Это дополнительный шаг, который занимает много времени, потому что воссоздание одной и той же контекстной среды может быть длительным процессом.

СПОК ЗНАЕТ ВСЕ ДЕТАЛИ, КОГДА ТЕСТ НЕ ПРОВЕРИЛ

Спок приходит на помощь! Если мы запустим ту же ошибку со Споком, мы получим следующее: 

Рисунок 4 — Провал теста Спока в Eclipse 

Из теста видно, что сложение работает правильно (2 + 3 действительно 5) и ошибка в коде умножения (4 умножить на 5 не равно 25)

Вооружившись этими знаниями, мы можем перейти непосредственно к коду множителя и найти ошибку. Это одна из самых страшных функций Spock, и ее может быть достаточно, чтобы побудить вас переписать все ваши тесты JUnit в Spock. 

Если вам понравилась эта статья, вы можете найти полную книгу в  Мэннинг  !