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

Разработка, основанная на тестах для библиотек обработки сигналов

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

В настоящий момент я использую то, что я бы назвал глобальным подходом, основанным на тестах. Для этого я пишу блок обработки сигналов в С++, а затем создаю простой файл с текстом Matlab, который может взаимодействовать с моими классами. Я впоследствии добавляю функциональность, проверяя, что результаты совпадают с эквивалентным Matlab script, когда я иду. Это работает нормально, но тесты быстро устаревают по мере развития системы. Furtermore, я тестирую всю систему, а не только единицы.

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

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

4b9b3361

Ответ 1

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

  • FFT: тестовые сигналы на известных частотах: DC, Fs/Nfft, Fs/2 и разные фазы и т.д. Проверьте пики и фазу, как вы ожидаете, проверьте константу нормализации, как вы ожидаете.
  • Выбор пика: проверьте правильность нахождения максимумов/минимумов
  • Фильтры: генерируют вход на известных частотах и ​​проверяют амплитуду и фазу выхода, как ожидалось.

Вы вряд ли получите точно такие же результаты между С++ и Matlab, поэтому вам придется указывать ограничения на ошибки в некоторых тестах. TDD - отличный способ не только проверить правильность кода, который у вас есть, но и очень полезен при тестировании различных реализаций. Например, если вы хотите заменить одну реализацию FFT на другую, часто возникают небольшие различия с тем, как данные упаковываются, или константа нормализации, которая используется. TDD даст вам высокую степень уверенности в том, что новая библиотека правильно интегрирована.

Ответ 2

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

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

С другой стороны, мне всегда хочется сказать: "Если его не проверено, его сломал":)

Ответ 3

Хорошо, чтобы тест был таким же сложным или сложным, как и разрабатываемый код. Если вы измените (обновление, рефакторинг, исправление ошибок) код, а не тест, unit test предупредит вас о том, что что-то изменилось и нуждается в пересмотре (было ли исправление ошибки для режима A, который должен изменить режим B?, и т.д. )

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

Ответ 4

Я только начинаю думать о TDD в контексте обработки сигналов, поэтому я могу только добавить немного к предыдущим ответам. То, что я сделал, - это использование суперпозиции для тестирования примитивов. Например, при тестировании IIR-фильтра я самостоятельно проверял элементы b0, b1 и b2 с единицей и масштабированными коэффициентами усиления, а затем проверял элементы a1 и a2, которые следовали за легко моделируемыми распадами. Мой тестовый сигнал был комбинацией функций рампы для числителя и импульсных функций знаменателя. Я знаю, что это тривиальный пример, но этот процесс должен работать на множество линейных операций. Тесты также должны выполнять нестабильные регионы и показывать, что результаты взрываются соответствующим образом.

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