Насколько должны быть сфокусированы JUnit-тесты BDD - PullRequest
0 голосов
/ 23 января 2012

Я тестирую некоторый код для практики и заметил странную ситуацию.

Существует ChannelRegistry, содержащее все ссылки на каналы связи, и PrimaryConsumer, которому необходимо подключиться к одному из этих каналов, выбранных во время выполнения при вызове initialize (). Итак, я сделал мой первый тест следующим образом:

@RunWith(MockitoJUnitRunner.class)
public class PrimaryConsumerTest {

    private @Mock ChannelsRegistry communicationRegistry;
    private PrimaryConsumer consumer;

    @Before
    public void setup() {
        consumer = new PrimaryConsumer(communicationRegistry);
    }

    @Test
    public void shouldAttachToChannel() throws Exception {
        consumer.initialize();
        verify(communicationRegistry).attachToChannel("channel", consumer);
    }
} 

Я проверяю, вызывается ли метод присоединения. Чтобы сделать его зеленым, я поставил impl так:

public void initialize() {
    communicationRegistry.attachToChannel("channel", this);
}

Теперь следующий тест: получить идентификатор канала по имени и присоединиться к этому конкретному каналу. Я хочу, чтобы мой тест описывал поведение класса, а не его внутренности, поэтому я не хочу, чтобы мой тест был "shouldGetSpecificChannel". Вместо этого я проверяю, может ли он подключиться к каналу, выбранному во время выполнения:

    @Test
    public void shouldAttachToSpecificChannel() throws Exception {
        String channelName = "channel";
        when(communicationRegistry.getChannel("channel_name")).thenReturn(channelName);
        consumer.initialize();
        verify(communicationRegistry).attachToChannel(channelName, consumer);
    }

Этот тест проходит немедленно, но реализация завинчена (жестко закодирован "канал").

2 вопроса здесь:

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

  • как справиться с такой ситуацией: тесты зеленые, импл "жестко закодированные"? Должен ли я написать другой тест с другим названием канала? Если так, я должен удалить это после исправления impl (поскольку это становится бесполезным?)

UPDATE: Просто некоторые уточнения. Я жестко запрограммировал «канал» здесь

public void initialize() {
    communicationRegistry.attachToChannel("channel", this);
}

только для того, чтобы быстро пройти первый тест. Но затем при запуске второго теста он проходит сразу. Я не проверяю, был ли вызван метод-заглушку, так как думаю, что заглушки не следует проверять явно. Это то, что вы, Родни, имеете в виду, говоря, что тесты излишни? Если да, то я сделаю заглушку в самом начале первого теста?

Ответы [ 2 ]

1 голос
/ 26 января 2012

В основном то же самое Родни на вопрос о множественных тестах. Я бы предложил, основываясь на вашем обновлении, одну или две вещи.

Во-первых, вы использовали одни и те же данные для обоих тестов. В книге Кента Бека о TDD он упоминает об использовании «триангуляции». Если бы вы использовали разные справочные данные во втором случае, то ваш код не прошел бы без дополнительной работы с вашей стороны.

С другой стороны, он также упоминает об удалении всего дублирования, а дублирование включает дублирование между кодом и тестами. В этом сценарии вы могли оставить оба теста без изменений и реорганизовать дублирование между строкой "channel" в коде и той же строкой в ​​тесте, заменив литерал в тестируемом классе на вызов вашего * 1006. *. После этого рефакторинга у вас теперь есть строковый литерал в одном-единственном месте: тест.

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

Напоминание, чтобы проверить ответ Родни на вопрос о нескольких тестах или нет. Я полагаю, вы могли бы удалить первый.

Спасибо!

Brandon

1 голос
/ 23 января 2012
  1. Больше тестов, как правило, предпочтительнее, чем слишком мало, поэтому два теста подходят. Лучший вопрос заключается в том, являются ли два теста избыточными: существует ли какая-либо ситуация или комбинация входных данных, которые могут привести к сбою одного из тестов, но не другого? Тогда оба теста необходимы. Если они всегда терпят неудачу или преуспевают вместе, то вам, вероятно, нужен только один из них.

  2. Когда вам понадобится другое значение для channelName? Похоже, что это настройка конфигурации, которая не имеет отношения к этим конкретным тестам. Это нормально, возможно, вы бы протестировали эту конфигурацию на более высоком уровне, в ваших интеграционных тестах. Больше всего меня беспокоит то, почему он изначально жестко запрограммирован: его нужно внедрить в ваш класс (возможно, через конструктор). Затем вы можете проверить разные названия каналов - или нет. В любом случае, вы не хотите изменить свой код только для тестирования, если это означает, что вы вернете его обратно, когда закончите.

...