Повторение кода в тестах JUnit - PullRequest
3 голосов
/ 20 февраля 2012

«Плохо» дублировать код в тестовом классе?Как видите, я добавляю записи вождения в список вождения, чтобы иметь возможность протестировать несколько методов.Лучше извлечь это из метода частного помощника или лучше для ясности оставить все как есть?Что вы делаете в таких случаях?

@Test
public void shouldRemoveAllDrivingRecords() {
    Duration duration1 = new Duration(1, 30, 45);
    Duration duration2 = new Duration(2, 50, 12);

    DrivingRecord drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
    DrivingRecord drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");

    drivingLog.addDrivingRecord(drivingRecord1);
    drivingLog.addDrivingRecord(drivingRecord2);

    drivingLog.removeAllDrivingLogs();

    assertEquals(0, drivingLog.numberOfDrivingRecords());
}

@Test
public void shouldSumTheDistanceDriven() {
    Duration duration1 = new Duration(1, 30, 45);
    Duration duration2 = new Duration(2, 50, 12);

    DrivingRecord drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
    DrivingRecord drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");

    drivingLog.addDrivingRecord(drivingRecord1);
    drivingLog.addDrivingRecord(drivingRecord2);

    double expectedDistanceDriven = drivingRecord1.getDistance() + drivingRecord2.getDistance();
    double totalDistanceDriven = drivingLog.getDistanceDriven();

    assertEquals(expectedDistanceDriven, totalDistanceDriven, 0.1);
}

Ответы [ 9 ]

7 голосов
/ 20 февраля 2012

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

Тем не менее, повторение создание тестовых данных - это плохо. Что лучше, так это продумать набор данных, тщательно созданный для тестирования, и поддерживать тестирование в большинстве случаев. Этот набор данных может быть создан методом setUp. Может быть несколько наборов тестовых данных, охватывающих варианты бизнес-правил, если это необходимо. Создать полезные наборы тестовых данных непросто, но на это стоит потратить некоторое время. Кроме того, тестовые данные могут быть загружены из JSON или около того. В некоторых случаях легче поддерживать.

Юнит-тесты обычно не должны зависеть друг от друга. Но часто тестовый пример зависит друг от друга . Например, чтобы проверить список, нужно проверить, что add() работает, что isEmpty() работает, что remove() работает. Тестирование remove() предполагает, что add() работает. Для такого сценария вы можете использовать JExample , фреймворк для модульного тестирования, с помощью которого вы можете «связывать» тесты.

7 голосов
/ 20 февраля 2012

«Плохо» дублировать код где угодно.Этот код дублируется по какой-либо причине или это было просто удобство.Если есть причина, по которой вы хотите использовать одни и те же данные в обоих и добавлять их одинаково, то имеет смысл использовать метод «настройки».

6 голосов
/ 20 февраля 2012

Вы можете аннотировать метод с помощью @org.junit.Before и инициализировать переменные в этом методе:

public class DrivingLogTest { 
     //suposing DrivingLog class...
     private DrivingLog drivingLog;

     private Duration duration1;
     private Duration duration2;

     private DrivingRecord drivingRecord1;
     private DrivingRecord drivingRecord2;


    @Before 
    public void setUp() { 
       drivingLog=new DrivingLog();
       duration1 = new Duration(1, 30, 45);
       duration2 = new Duration(2, 50, 12);

       drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
       drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");

       drivingLog.addDrivingRecord(drivingRecord1);
       drivingLog.addDrivingRecord(drivingRecord2);

    }


    @Test
    public void shouldRemoveAllDrivingRecords() {

       drivingLog.removeAllDrivingLogs();

       assertEquals(0, drivingLog.numberOfDrivingRecords());
    }

    @Test
    public void shouldSumTheDistanceDriven() {

       double expectedDistanceDriven = drivingRecord1.getDistance() +  drivingRecord2.getDistance();
       double totalDistanceDriven = drivingLog.getDistanceDriven();

       assertEquals(expectedDistanceDriven, totalDistanceDriven, 0.1);
    }
}
2 голосов
/ 20 февраля 2012

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

Обычно я использую метод @Before для инициализации всех переменных или класс TestUtility, который может использоваться несколькими модульными тестами / проектами.

1 голос
/ 20 февраля 2012

См. Также Meszaros ' Тестовые таблицы XUnit , которые включают в себя раздел дублирование тестового кода .

@Before - путь для данного фрагмента.

1 голос
/ 20 февраля 2012

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

1 голос
/ 20 февраля 2012

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

@Test
public void shouldRemoveAllDrivingRecords() {
    theTest(0);
} 

@Test
public void shouldSumTheDistanceDriven() {
    theTest(0.1);
} 

Вы также можете создавать TestSuites, если вам нужно. Это позволяет запускать группы тестов с разными параметрами.

0 голосов
/ 05 декабря 2012

распаковывает все общие конфигурации в @before.Вы также можете использовать параметры с @Parametrized или с моим проектом: zohhak , например.

@Before
public void prepareBank() {
  ...
}

@TestWith({
   "25 USD",
   "38 GBP",
   "null"
})
public void testMethod(Money money) {
   ...
}
0 голосов
/ 20 февраля 2012

Я следую за СУХОЙ ПРИНЦИПОМ также в Юните!Я даже пишу вспомогательные или конструктор классов для выполнения повторяющихся задач.Хороший метод Junit должен содержать на первый взгляд только данные, поэтому очевидно, что проверено без загрязнения как проверено.

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