Статьи

Разработка через тестирование (TDD) сияет с помощью насмешек

В статье представлены перспектива и некоторые примеры кода о том, как можно сделать кое-что интересное с помощью разработки через тестирование (TDD) и Mocking. Примеры кода сделаны на Java.

Кратко разберемся, что такое TDD и издевательство?

Что такое TDD?

Проще говоря, разработка через тестирование — это процесс разработки программного обеспечения, в котором разработчики сначала пишут тесты, а затем пишут достаточно кода, чтобы пройти эти тесты. После того, как все тесты пройдены, они проводят рефакторинг кода для повышения качества кода. Ниже приведены ключевые преимущества использования TDD в качестве процесса разработки:

  1. Заставляет разработчиков тщательно продумывать различные тесты, которые можно использовать для проверки функциональных / бизнес-требований. Таким образом, он устраняет множество ошибок, которые могут быть обнаружены на этапах QA и постпроизводства, которые очень трудно исправить.
  2. Разработчики очень тесно сотрудничают как с бизнес-аналитиками, так и с инженерами-тестировщиками. Это пропагандирует командную работу .
  3. Рефакторинг кода можно сделать простым способом.

Следующая диаграмма представляет процесс TDD:

Разработка через тестирование

Разработка через тестирование (Courtesy: Wikipedia)

Вот несколько хороших страниц в Интернете, чтобы начать работу с TDD:

Что такое издевательство?

Mocking — это явление модульного тестирования, которое помогает тестировать объекты изолированно, заменяя зависимые объекты сложным поведением тестовыми объектами с предопределенным / смоделированным поведением. Эти тестовые объекты называются фиктивными объектами.

Как TDD сияет с Mocking?

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

  • Без насмешек : напишите весь код в одном классе и пройдите тесты. Как только тесты пройдут, проведите рефакторинг кода, извлекая методы и классы. Убедитесь, что тесты пройдены.
  • С Mocking : вместо необходимости писать весь код одновременно в одном и том же классе, просто реализуйте поток, используя зависимые классы, и убедитесь, что тесты пройдены. При этом просто определите зависимые классы и смоделируйте их в модульных тестах. Делая это, можно было бы обеспечить прохождение потока метода без необходимости писать весь код. Преимущество использования насмешек заключается в интересных моделях поведения, которые можно моделировать без необходимости в коде. Это продемонстрировано позже в этой статье с примерами кода. Следующая диаграмма демонстрирует тот факт, что при моделировании может не потребоваться написать зависимые классы и все же завершить поток кода, в то же время убедившись, что все связанные тесты пройдены.tdd_thumb
Требование к программному обеспечению

Мы попробуем и посмотрим, как TDD сияет с насмешками с этим требованием. Требуется добавить новый ресторан в систему базы данных ресторанов. Нужно иметь возможность добавить ресторан, если введены обязательные данные.

Модульный тест, написанный первым

Глядя на требования, можно придумать несколько следующих тестов:

  1. restaurantNotCreatedDueToValidationFailure
  2. restaurantNotCreatedDueToPersistenceFailure
  3. restaurantCreated

Вот как выглядит модульный тест (написанный первым):

Модульный тест: NewRestaurantTest.java

public class NewRestaurantTest {

@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void restaurantCreated() {
}
@Test
public void restaurantNotCreatedDueToValidationFailure() {
}
@Test
public void restaurantNotCreatedDueToPersistenceFailure() {
}

}
Класс Дизайн

Глядя на вышеприведенные тесты, можно увидеть следующие классы:

  1. NewRestaurant: Включая логику для создания ресторана
  2. Ресторан: Доменный объект, представляющий ресторан
  3. RestaurantValidation: состоит из логики проверки, соответствующей бизнес-правилам, необходимым для добавления нового ресторана
  4. RestaurantDAO: состоит из логики для сохранения объекта ресторана в базе данных

Класс Java: NewRestaurant.java

Обратите внимание на метод createRestaurant, в котором проверенные и постоянные методы вызываются для классов RestaurantValidation и RestaurantDAO соответственно. Эти методы, однако, являются пустыми методами в соответствующих классах. Однако с этими методами процесс создания ресторана завершен. Посмотрите на код ниже.

public Restaurant createRestaurant( Restaurant restaurant ) {
Restaurant retRest = null;
if( resVal.validated( restaurant ) ) {
if( resDAO.persist( restaurant ) ) {
retRest = new Restaurant( restaurant );
}
}
return retRest;
}

Чтобы проверить приведенный выше код, следующий код демонстрирует использование макетов. Обратите внимание, как проверенные и сохраняемые методы для RestaurantValidation и RestaurantDAO соответственно подвергаются насмешкам в трех различных тестах, показанных ниже.

Модульный тест: NewRestaurantTest.java

@Test
public void restaurantCreated() {
Restaurant restaurant = new Restaurant();
Mockito.when( restVal.validated(restaurant)).thenReturn( true );
Mockito.when( restDAO.persist(restaurant)).thenReturn( true );

Restaurant newRest = newRestaurant.createRestaurant(restaurant);
Mockito.verify( restVal ).validated(restaurant);
Mockito.verify( restDAO ).persist(restaurant);
assertNotNull( newRest );
}

@Test
public void restaurantNotCreatedDueToValidationFailure() {
Restaurant restaurant = new Restaurant();
Mockito.when( restVal.validated(restaurant)).thenReturn( false );
Mockito.when( restDAO.persist(restaurant)).thenReturn( true );

Restaurant newRest = newRestaurant.createRestaurant(restaurant);
Mockito.verify( restVal ).validated(restaurant);
Mockito.verify( restDAO, Mockito.never() ).persist(restaurant);
assertNull( newRest );
}

@Test
public void restaurantNotCreatedDueToPersistenceFailure() {
Restaurant restaurant = new Restaurant();
Mockito.when( restVal.validated(restaurant)).thenReturn( true );
Mockito.when( restDAO.persist(restaurant)).thenReturn( false );

Restaurant newRest = newRestaurant.createRestaurant(restaurant);
Mockito.verify( restVal ).validated(restaurant);
Mockito.verify( restDAO ).persist(restaurant);
assertNull( newRest );
}

Таким образом, в качестве резюме, если вы хотите получить больше удовольствия от TDD, используйте насмешки, поскольку они позволяют моделировать некоторые интересные варианты поведения без необходимости написания какого-либо кода.