Зарегистрируйтесь, чтобы продолжить обучение

Плохие и хорошие практики тестирования Java: Автоматическое тестирование

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

Взаимное влияние тестов

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

Нарушить это правило очень просто. Один тест может создать файл, изменить переменную или записать что-то в базу. Если остальные тесты наткнутся на эти изменения, то они могут упасть там, где не должны падать, или наоборот — успешно пройти там, где не должны проходить. Кроме этого, в такой ситуации вводится неопределённость. Такие тесты могут падать эпизодически без видимых на то причин. Например, когда тест запускают изолированно, то он работает, а когда вместе с остальными — падает.

Особенно часто такая ситуация возникает в тестах, активно взаимодействующих с внешней средой: базой данных или файловой системой. Тестирование побочных эффектов имеет свои хитрости и выходит за рамки текущего курса.

Условные конструкции в тесте

@Test
public void myTest() {
    if (/* что-нибудь */) {
        // Выполняем код одним способом
        // Проверка может быть тут
    } else {
        // Выполняем код другим способом
        // Проверка может быть тут
    }
}

Любое ветвление внутри тестов это фактически несколько тестов в рамках одного теста. От этого надо избавляться и никогда так не писать.

Тест вне тестов

Задача @BeforeEach — готовить данные и среду для тестирования, а задача @Test — вызывать код, который тестируется, и проводить проверки. Но иногда разработчики переусердствуют:

class SomeClassTest {
    private int result;

    @BeforeEach
    public void beforeEach() {
        // Вызывается тестируемый код. Это противоречит идее @BeforeEach.
        this.result = sum(5, 9);
    }

    @Test
    public void testSum() {
        // Здесь только проверка
        assertEquals(14, result);
    }
}

В этом примере тестируемый код вызывается в @BeforeEach. Такой подход усложняет анализ тестов, так как переворачивает всё с ног на голову.

Слишком сильная детализация

Программисты под влиянием голосов из интернета стремятся максимально разносить код по файлам, модулям и методам. То же самое наблюдается и в тестах. Вместо одного теста, в котором содержатся все необходимые проверки, программист создаёт 5 тестов, в каждом из которых ровно одна проверка:

class SomeClassTest {
    @Test
    public void testGetName() {
        var user = new User("Mark", 15);
        assertEquals("Mark", user.getName());
    }

    @Test
    public void testGetAge() {
        var user = new User("Mark", 15);
        assertEquals(15, user.getAge());
    }
}

Чаще всего, единственным результатом такого разделения будет большее количество кода и усложнение рефакторинга в будущем, когда тестов станет по-настоящему много. Удобнее сделать так:

class SomeClassTest {
    @Test
    public void testGetName() {
        var user = new User("Mark", 15);
        assertEquals("Mark", user.getName());
        assertEquals(15, user.getAge());
    }
}

Код с тестами писать дольше, чем код без тестов

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

  • Тесты влияют на дизайн кода. Они помогают выявить неудачные решения намного раньше.
  • Подготовка входных данных может занимать значительное время. С тестами это нужно сделать один раз.
  • Проверка результата работы кода может быть сложной и разнообразной. Тесты позволяют об этом не думать, они сами проверяют, что всё хорошо, включая пограничные случаи.
  • Если в проекте тесты пишутся регулярно, то проще и быстрее делать рефакторинг, так как не придётся проверять вручную другие части кода.
  • Тесты снижают уровень стресса.

Дополнительные материалы

  1. Начинаем писать тесты правильно

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»