Подтвердить что ты не робот

Как проверить типы перечислений?

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

public enum Month {
    January,
    February,
    ...
    December;
}

Здесь я хочу убедиться, что все типы перечислений действительно существуют. Это даже необходимо? В настоящее время я использую Hamcrests assertThat, как в следующем примере:

assertThat(Month.January, is(notNullValue()));

Отсутствие перечня "Январь" приведет к ошибке времени компиляции, которую можно исправить, создав отсутствующий тип перечисления.

Я использую Java здесь, но я не против, если ваш ответ для другого языка.

Edit:

Поскольку mkato и Mark Heath оба указали, что перечисления для тестирования могут быть не нужны, поскольку компилятор не будет компилироваться, когда вы используете тип перечисления, которого нет. Но я все же хочу протестировать эти перечисления, так как мы хотим создать отдельный TCK-подобный test.jar, который будет запускать те же тесты для разных реализаций. Таким образом, мой вопрос был больше похож: как лучше всего проверить типы перечислений?

Подумав об этом чуть больше, я изменил инструкцию Hamcrest выше:

assertThat(Month.valueOf("January"), is(notNullValue()));

Это утверждение теперь бросает NPE, когда января нет (пока). Что-то не так с этим подходом?

4b9b3361

Ответ 1

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

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

Ответ 2

Я согласен с aberrant80.

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

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

Я бы расширил его, добавив, что модульные тесты Enum могут быть очень полезными. Если вы работаете в большой базе кода, время сборки начинает монтироваться, а unit test может быть более быстрым способом проверки функциональности (тесты только строят свои зависимости). Другое действительно большое преимущество в том, что другие разработчики не могут непреднамеренно изменить функциональность вашего кода (огромная проблема с очень большими командами).

И при всех тестовых разработках тесты вокруг методов Enums уменьшают количество ошибок в вашей базе кода.

Простой пример

public enum Multiplier {
    DOUBLE(2.0),
    TRIPLE(3.0);

    private final double multiplier;

    Multiplier(double multiplier) {
        this.multiplier = multiplier;
    }

    Double applyMultiplier(Double value) {
        return multiplier * value;
    }

}

public class MultiplierTest {

    @Test
    public void should() {
        assertThat(Multiplier.DOUBLE.applyMultiplier(1.0), is(2.0));
        assertThat(Multiplier.TRIPLE.applyMultiplier(1.0), is(3.0));
    }
}

Ответ 3

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

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

Ответ 4

Если вы используете все месяцы в своем коде, ваша среда IDE не позволит вам скомпилировать, поэтому я думаю, что вам не требуется модульное тестирование.

Но если вы используете их с отражением, даже если вы удалите один месяц, он будет скомпилирован, поэтому допустим положить unit test.

Ответ 5

вы можете проверить, имеют ли какие-то значения, например:

for(MyBoolean b : MyBoolean.values()) {
    switch(b) {
    case TRUE:
        break;
    case FALSE:
        break;
    default:
        throw new IllegalArgumentException(b.toString());
}

for(String s : new String[]{"TRUE", "FALSE" }) {
    MyBoolean.valueOf(s);
}

Если кто-то удаляет или добавляет значение, некоторые из тестов терпят неудачу.