Интеграция и юнит-тесты в крупном проекте Grails - PullRequest
12 голосов
/ 10 апреля 2011

Обычно писать модульные тесты сложнее из-за необходимости иметь дело с фиктивными объектами, чем интеграционные тесты в большом проекте Grails.В этой статье даже говорится, что мы можем вообще отказаться от модульных тестов и написать только интеграционные тесты, с которыми я склонен согласиться.

Единственный недостаток, который я вижу, - это скорость выполнения интеграционных тестов, посколькупо сравнению с тем же модульным тестом.

Что вы думаете об этом из своего реального опыта работы в крупномасштабном проекте Grails?

Если мы напишем модульный тест, который тестирует точно такой же метод, а также напишемИнтеграционный тест, который также тестирует точно такой же метод, является ли это нормальным способом написания тестов?

Что вы получили в плане соотношения юнит-тестов и интеграционных тестов в реальном крупном проекте Grails?

Вы успешно завершили большой проект Grails без написания каких-либо тестов?

Ответы [ 3 ]

12 голосов
/ 10 апреля 2011

Я всегда пишу свои тесты как модульные тесты, если это возможно.Я делаю это потому, что:

  • модульные тесты выполняются быстрее
  • Я предпочитаю тестировать каждый компонент отдельно, а не тестировать все компоненты, объединенные вместе, потому что это облегчает идентификациюисточник ошибки
  • среда модульного тестирования более проста (например, отсутствует контекст приложения Spring), поэтому существует меньше потенциальных источников отказа, которые не связаны с выполняемым тестом

AnПример того, где я мог бы написать интеграционный тест, - это если я хочу протестировать bean-компонент Spring, который я определил в resources.groovy.Хотя я мог бы создать экземпляр класса и протестировать его напрямую, мой тест должен был бы знать текущий класс реализации этого компонента (который может измениться).

В долгосрочной перспективе я думаю, что на самом деле написать сложнееинтеграционные тесты, потому что затраты на их поддержание с течением времени выше, чем модульные тесты.Groovy / Grails имеет отличную поддержку для mocking / stubbing, поэтому стоимость зависимостей mocking в модульных тестах относительно невелика.Вот реальный пример из одного из моих модульных тестов, где я:

  • смоделировал бин messageSource Spring, который обычно был бы доступен только в интеграционном тесте
  • команда mock twoклассы, в которых я могу вызвать метод validate(), проверить свойство .errors и т. д.

class MyUnitTests extends GrailsUnitTestCase {

    MessageSource messageSource

    protected void setUp() {

        super.setUp()
        // mockForConstraintsTests is a method provided by GrailsUnitTestCase
        [Complex, CategoryCommand].each {mockForConstraintsTests(it)}

        // 'mockMessage' will be returned by every method call on messageSource
        messageSource = {Object[] args -> "mockMessage"} as MessageSource
    }
}
7 голосов
/ 11 апреля 2011

Я работал над 3 большими приложениями Grails и неисчислимыми меньшими.В моем текущем проекте есть набор юнит-тестов и интеграционных тестов (в настоящее время 2110 юнит-тестов и 493 интеграционных тестов).

Я потратил кучу времени, пытаясь повысить скорость тестирования, а также сделать тесты более удобными в обслуживании.

Мои интеграционные тесты часто бывают гибридными, где, если я тестирую сервис, я мог бы смоделировать некоторые другие вызываемые сервисы / методы, чтобы убедиться, что я получаю нужные значения, но оставить в других частях интеграции для упражнения.HQL или интеграция с базой данных.С этой целью я использую прототипов экземпляров, которые обычно представляют собой одноэлементные сервисы , так что я могу работать с экземпляром сервиса, не загрязняя последующие тесты.

Я нахожу build-test-Плагин data неоценим для создания поддерживаемых модульных тестов, так как он позволяет мне создавать тестовые данные, где я явно заполняю нужные мне фрагменты и позволяю плагину заполнять другие необходимые детали.Создание тестовых данных в интеграционных тестах для меня проще, чем их моделирование в модульных тестах.

Если вы используете как интеграционные, так и модульные тесты, со временем скорость последовательного выполнения всех тестов станет препятствием.Моя команда использует скрипт splitTests.groovy , чтобы выделить два отдельных потока, один для модульных тестов, один для интеграционных тестов.Это делает наши тесты примерно на 40% быстрее.Дальнейшее распараллеливание возможно, но мы еще не пошли (а текущие скрипты Gant Grails довольно неприятны под обложками, я с нетерпением жду переписывания Gradle в Grails 2.0).

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

Я думаю, что смелость рефакторинга, которую вы получаете благодаря высокому охвату тестами, частично зависит от того, какие из тестов являются интеграционными.Если все, что у вас есть, это модульные тесты, которые не взаимодействуют с другими частями кода, вы не будете предупреждены об уязвимых областях при внесении изменений в код, а поскольку groovy является динамическим языком, компилятор, скорее всего, не поможет вам найтиэти области либо.

0 голосов
/ 17 мая 2011

В этой статье даже предлагается, что мы можем вообще отказаться от модульных тестов и написать только интеграционные тесты, к которым я склонен

Эта статья была написана с Grails 1.0

Отметьте дополнительную статью Тот же столбец, тот же автор

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...