TDD для коммуникатора устройства - PullRequest
1 голос
/ 04 марта 2009

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

Проект

У меня есть несколько единиц оборудования, которые поставляются с интерфейсом ASCII-over-RS232. Я могу давать простые команды, получать простые ответы и управлять ими, как будто с их лицевой панели. Каждый из них имеет немного другой синтаксис и очень разные наборы команд. Моя цель - создать абстракцию / интерфейс, чтобы я мог управлять ими через графический интерфейс и / или удаленные вызовы процедур.

Проблема

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

Теперь, для модульных тестов, я не думаю, что мне действительно нужно реальное оборудование или последовательное соединение. Что я хотел бы сделать, так это передать моим коммуникаторам InputStream и OutputStream (или Reader and Writer), которые могут быть из последовательного порта, файла stdin / stdout, переданы из тестовой функции, что угодно. Итак, я бы просто попросил конструктор Communicator использовать их в качестве входных данных? Если это так, было бы легко возложить ответственность за настройку всего этого на среду тестирования, но для реального, кто устанавливает фактическое соединение? Отдельный конструктор? Функция снова вызывает конструктор? Отдельный класс, кому поручено «подключить» коммуникатор к правильным потокам ввода / вывода?

Редактировать

Я собирался переписать проблемный раздел, чтобы получить ответы на вопрос, который, как мне казалось, я задавал, но, думаю, я понял это. Я (правильно?) Определил две разные функциональные области.

1) Работа с последовательным портом

2) Связь с устройством (понимание его вывода и генерация команд)

Несколько месяцев назад я бы объединил все это в один класс. Моей первой идеей покончить с этим было передать только потоки ввода-вывода классу, который понимает устройство, и я не мог понять, кто будет отвечать за создание потоков.

Проведя больше исследований по инверсии управления, я думаю, что у меня есть и ответ. Иметь отдельный интерфейс и класс, который решает проблему # 1, и передавать его конструктору класса (ов?), Который решает проблему # 2. Таким образом, легко проверить оба по отдельности. # 1, подключаясь к реальному оборудованию и позволяя тестовой среде делать разные вещи. № 2 может быть проверен, если ему дразнить # 1.

Это звучит разумно? Нужно ли мне делиться информацией?

Ответы [ 3 ]

2 голосов
/ 04 марта 2009

Извините за то, что я немного ориентирован на Linux ..

Мой любимый способ симуляции гаджетов - писать драйверы символьных устройств , которые имитируют их поведение. Это также дает вам забавные возможности, такие как предоставление интерфейса ioctl (), который заставляет моделируемое устройство работать ненормально.

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

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

2 голосов
/ 04 марта 2009

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

Уточнено: Начните с конкретного класса, чтобы отправить одну команду, протестируйте его с помощью макета или заглушки. Когда он будет работать достаточно (возможно, не со всеми опциями), протестируйте его на своем реальном устройстве, чтобы проверить ваш макет / заглушку / симулятор.

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

1 голос
/ 11 марта 2009

После просмотра ваших изменений я думаю, что вы движетесь в правильном направлении. TDD ведет вас к дизайну, состоящему из небольших классов с четко определенной ответственностью. Я также хотел бы повторить совет Тинкертима - симулятор устройства, которым вы можете управлять и «провоцировать» себя на поведение по-разному, неоценим для тестирования.

...