Философия TDD мотивировать методы с использованием композиции - PullRequest
0 голосов
/ 26 июля 2011

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

  • EventDispatcher -> TypedEventDispatcher -> FooEventDispatcher
  • EventDispatcher -> TypedEventDispatcher -> BarEventDispatcher

Таким образом, EventDispatcher отправляет общие события (String, Number, Object), TypedEventDispatcher отправляет только события, основанные на объектах, а FooEventDispatcher только отправляет события Foo, BarEventDispatcher отправляет события Bar и так далее.

Тесты для всех классов имеют идентичное поведение, единственное отличие - тип объекта, с которым проверяется. Я обнаружил, что когда я хочу добавить новый тип события, я получаю тот же тестовый код, что и для других классов.

Это количество дублирования явно неверно. Получающиеся в результате тесты довольно хрупкие, поскольку, когда я добавляю новую функцию в TypedEventDispatcher, мне нужно добавить те же тесты для любых объектов, которые ее используют.

В Java, .NET или Haxe я хотел бы создать универсальный тип и протестировать его, однако я использую ActionScript, который не поддерживает обобщенные типы, поэтому мне нужен новый класс для каждого типа для обеспечения безопасности типов .

Насколько я вижу, мои варианты:

  1. Продолжайте создавать одинаковые тесты для каждого нового класса.
  2. Игнорируйте тесты для производных классов, просто создайте новые классы и предположите, что они работают.

Вариант № 1 представляется наиболее «правильным», но также приводит к хрупким тестам. Вариант № 2 имеет смысл в том, что базовый объект (TypedEventDispatcher) тестируется, поэтому производные классы все еще должны работать.

Итак, мой вопрос: какова философия TDD для мотивации создания новых классов на основе композиции?

Обновление: Чтобы задать вопрос по-другому, нормально ли в итоге получить дубликат тестового кода при получении функциональности из существующего кода?

Обновление:

Тест BaseEventDispatcher:

class BaseEventDispatcherTest {
    protected function test_dispatchEvent(dispatcher:Object, event:*):void {
        dispatcher.dispatch(event);
        assertEventDispatched(event)
    }
}

Тест TypedEventDispatcher:

class TypedEventDispatcherTest extends BaseEventDispatcherTest {
    [Test]
    public function dispatchEvent_TypedEvent_should_dispatch_event():void {
        var event:TypedEvent = new TypedEvent();
        test_dispatchEvent(dispatcher, event);
    }
}

FooEventDispatcher test:

class FooEventDispatcherTest extends BaseEventDispatcherTest {
    [Test]
    public function dispatchEvent_FooEvent_should_dispatch_event():void {
        var event:FooEvent = new FooEvent();
        test_dispatchEvent(dispatcher, event);
    }
}

Ответы [ 3 ]

2 голосов
/ 26 июля 2011

Вы знаете, что тестовые классы могут наследоваться от других тестовых классов?

Это, вероятно, подойдет для вашей ситуации.

1 голос
/ 28 июля 2011

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

Вместо набора тестов, подобных этому:

  • test EventDispatcher's addEventListener
  • test EventDispatcher's removeEventListener
  • test EventDispatcher's displatchEvent
  • test TypedEventDispatcher's addEventListener
  • ...

У меня был бы такой набор тестов:

  • тест, который отправляет dispatchEvent, уведомляет прослушивателей, которые были добавлены
  • проверить, что dispatchEvent не уведомляет слушателей, которые были удалены
  • проверка того, что удаление прослушивателя, который никогда не был добавлен, игнорируется

Эти поведенческие тесты, несомненно, являются функциями EventDispatcher, и я не чувствую необходимости дублировать их для TypedEventDispatcher, FooEventDispatcher и т. Д.

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

  • проверка того, что FooEventDispatcher не уведомляет слушателей о событиях Bar
  • проверка того, что TypedEventDispatcher не уведомляет слушателей о событиях String
  • ...

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

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

1 голос
/ 26 июля 2011

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

Если вы создаете один и тот же тест для разных классов, то они, вероятно, совместно используют некоторую функциональность, что может означать, что вы можете повысить упомянутую функциональность в иерархии и тестировать только при переопределении.

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