Как сделать TDD с оборудованием

Все проекты, над которыми я работаю, связаны с аппаратным обеспечением, и это часто является основной целью программного обеспечения. Есть ли какие-нибудь эффективные способы применить TDD к коду, который работает с оборудованием?

Обновление: извините за неясность моего вопроса.

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

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

2-е обновление: я также ищу несколько конкретных примеров того, как люди справились с этой ситуацией.

Ответов (7)

Решение

Разделите свой набор тестов на две части:

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

  2. Вторая часть противоречит макетам. Эта часть запускается автоматически.

Часть № 1 запускается вручную после того, как вы убедились, что оборудование правильно подключено, и т. Д. Хорошая идея - создать набор тестов, которые будут работать с чем-то, возвращаемым фабрикой, и выполнить эти тесты дважды: один раз с фабрикой, которая возвращает настоящий «водитель» и сразу против фабрики ваших макетных объектов. Таким образом, вы можете быть уверены, что ваши макеты работают точно так же, как и настоящие:

class YourTests extends TestCase {
    public IDriver getDriver() { return new MockDriver (); }
    public boolean shouldRun () { return true; }
    public void testSomeMethod() throws Exception {
        if (!shouldRun()) return; // Allows to disable all tests
        assertEquals ("1", getDriver().someMethod());
    }
}

В моем коде я обычно использую системное свойство (-Dmanual = yes) для переключения ручных тестов:

class HardwareTests extends YourTests {
    public IDriver getDriver() { return new HardwareDriver (); }
    public boolean shouldRun () { return "yes".equals (System.getProperty("manual")); }
}

Умно глумитесь.

Если у вас есть симулятор, вы можете написать тесты для симулятора и запустить эти тесты на оборудовании.

Сложно ответить на вопросы с такой маленькой детализацией :-)

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

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

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

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

В качестве альтернативы, в зависимости от устройства, вы можете использовать стандартное тестовое оборудование (генераторы сигналов и т. Д.) Для подачи на него «известных входов».

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

Создайте тонкий слой для управления оборудованием и используйте системные тесты (ручные или автоматические) с полным оборудованием, чтобы убедиться, что уровень управления работает должным образом. Затем создайте фальшивую / имитацию реализации уровня управления, которая внешне ведет себя как интерфейс к реальному оборудованию, и используйте ее при выполнении TDD для остальной части программы.


Несколько лет назад я писал программное обеспечение для проведения измерений с помощью СКВИД-магнитометра. Оборудование было большим, неподвижным и дорогим ( видео ), поэтому не всегда было возможно получить доступ к оборудованию. У нас была документация о протоколе связи с устройствами (через последовательные порты), но она не была на 100% точной.

Нам очень помогло создание программного обеспечения, которое прослушивает данные, поступающие из одного последовательного порта, регистрирует их и перенаправляет на другой последовательный порт. Затем мы смогли выяснить, как старая программа (которую мы заменяли) взаимодействовала с оборудованием, и перепроектировать протокол. Они были связаны следующим образом: Старая программа <-> Виртуальный последовательный порт с обратной связью <-> Наш регистратор данных <-> Реальный последовательный порт <-> Аппаратное обеспечение.

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

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

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

Мне также нравится идея разделить набор тестов на две части:

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

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

Когда я работал над телевизионными приставками, у нас был инструмент, который генерировал макеты из любого C API с комментариями doxygen.

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

Итак, в приведенном выше примере вы должны установить для результата FrameGrabber_API_IsDeviceAttached значение false, и когда ваш код вызывает эту функцию, он возвращает false, и вы можете его протестировать.

Насколько легко будет протестировать, зависит от того, как в настоящее время структурирован ваш код.

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

Просто проверяю - есть ли в вашем коде что-то вроде прямых вызовов ioctl или что-то в этом роде? Их всегда сложно смоделировать. У нас был слой оболочки ОС, для которого мы могли легко писать макеты, поэтому для нас это было довольно просто.