Совет, необходимый для рефакторинга устаревшего кода

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

Обратите внимание, что в текущей кодовой базе НЕТ UT.

У меня есть класс Calculator со следующей реализацией:

public final class Calculator extends CalculatorBase {
    public Calculator(Document document) throws Exception {
        super(document);
    }

    public int Multiply(int source, int factor) {
        return source * factor;
    }
}

Этот класс наследуется от следующего базового класса:

public class CalculatorBase {
    public CalculatorBase(Document document) throws Exception {
        throw new Exception("UNAVAILABLE IN UT CONTEXT.");
    }
}

ПРИМЕЧАНИЕ. Конструктор на самом деле делает много вещей, которых я бы не хотел делать в UT. Для простоты я заставил конструктор генерировать исключение.

Теперь я хочу добавить к классу Calculator функцию «Добавить». Эта функция выглядит так:

public int Add(int left, int right) {
    return left + right;
}

UT для этого конкретного фрагмента кода должен быть очень простым.

@Test
@DisplayName("Ensure that adding numbers DOES work correctly.")
void addition() throws Exception {
    // ARRANGE.
    Calculator calculator = new Calculator(null);

    // ACT.
    int result = calculator.Add(1, 1);

    // ASSERT.
    Assertions.assertEquals(2, result);
}

Поскольку конструктор базы CalculatorBase действительно вызывает исключение, этот модульный тест НИКОГДА не пройдет.

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

Какие (детские) шаги я должен предпринять, чтобы убедиться, что метод Add в классе Calculator можно протестировать? Цель состоит в том, чтобы сделать весь проект тестируемым и даже избавиться от автоматически сгенерированного материала, но я хотел бы использовать TDD везде, где это возможно, чтобы постепенно реорганизовать код.

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


person Complexity    schedule 02.04.2020    source источник
comment
Действительно :-) Обновил код.   -  person Complexity    schedule 02.04.2020
comment
Я считаю, что разработка через тестирование, как следует из названия, - это дисциплина, используемая для разработки программного обеспечения. Вы можете выполнить рефакторинг и модульное тестирование кода без TDD.   -  person Themelis    schedule 02.04.2020
comment
Итак, как мне провести рефакторинг и убедиться, что я ничего не нарушаю?   -  person Complexity    schedule 02.04.2020


Ответы (1)


Ты сможешь:

  1. Создайте новый метод как статический
  2. Создайте временный альтернативный конструктор с пометкой «Только для тестирования».
  3. Реорганизуйте класс, чтобы удалить зависимость
  4. Подавите его с помощью PowerMock.

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

person borjab    schedule 02.04.2020
comment
1. Предположим, что метод Add действительно использует состояние класса Calculator, поэтому его static НЕ будет работать. 2. Затем временный конструктор должен быть добавлен в класс CalculatorBase, но он создается автоматически. Итак, как только файл будет регенерирован, конструктор снова будет удален, и UT больше не будет компилироваться. 3. Удаление зависимостей без тестов - дело хрупкое. Я могу ввести ошибки, о которых я не осведомлен. Я не разбираюсь в тестировании на Scaldfold. Не могли бы вы объяснить это немного подробнее? - person Complexity; 02.04.2020
comment
Тест каркаса - это просто временной тест, используемый для рефакторинга класса без внесения новых ошибок. (Как вы сказали, она хрупкая). Также как когда вы ремонтируете старое здание. Вы можете предпочесть название Temporal ugly test Вот несколько приемов: youtube.com / watch? v = 1Z_h55jMe-M # t = 1h1m7s - person borjab; 02.04.2020
comment
Это больше похоже на интеграционный тест на первом этапе, чтобы его можно было протестировать ... - person Complexity; 02.04.2020
comment
Вы можете запросить тест временной интеграции. Remeber TDD! = Модульный тест - person borjab; 02.04.2020
comment
Мне нравится Виктор Рентя. :-) - person Complexity; 02.04.2020