Кто-нибудь делает «настоящий» TDD с Visual-C ++, и если да, то как они это делают? [закрыто]

10

Разработка через тестирование подразумевает написание теста перед кодом и выполнение определенного цикла :

  • Написать тест
  • Проверить тест (запустить)
  • Написать производственный код
  • Проверить тест (запустить)
  • Очистить производственный код
  • Проверить тест (запустить)

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

Теперь, хотя существует множество модулей модульного тестирования для C ++ (я использую Bost.Test atm.), Кажется, что на самом деле не существует достойного (для нативного C ++ ) решения Visual Studio (Plugin), которое бы делало TDD цикл переносимый независимо от используемой основы.

«Bearable» означает, что одним щелчком мыши выполняется запуск теста для определенного файла cpp без необходимости вручную настраивать отдельный проект тестирования и т. Д. «Bearable» также означает, что простой тест запускается (связывание!) И выполняется очень быстро. ,

Итак, какие есть инструменты (плагины) и методы, которые делают возможным цикл TDD для разработки на C ++ с Visual Studio?

Примечание: я в порядке с бесплатными или «коммерческими» инструментами.

Пожалуйста : никаких базовых рекомендаций. (Если фреймворк не имеет выделенного плагина Visual Studio и вы хотите порекомендовать этот плагин.)


Редактировать примечание : ответы до сих пор содержали ссылки на то, как интегрировать инфраструктуру модульного тестирования в Visual Studio. Ресурсы более или менее описывают, как заставить UT-инфраструктуру скомпилироваться и запустить ваши первые тесты. Это не то, о чем этот вопрос. Я придерживаюсь мнения, что для действительно продуктивной работы, имея модульные тесты в поддерживаемом вручную (!), Отдельном vcproj от ваших производственных классов, вы добавите столько накладных расходов, что TDD «не возможен». Насколько мне известно, вы не добавляете дополнительные «проекты» в Java или C #, чтобы включить модульные тесты и TDD, и для этого есть веская причина. Это должно было бы возможно с C ++, учитывая правильные инструменты, но кажется (этот вопрос о), что есть очень мало инструментов для TDD / C ++ / VS.


Погуглив, я нашел один инструмент, VisualAssert , который, кажется, направлен в правильном направлении. Однако, на самом деле, похоже, что он не используется широко (по сравнению с CppUnit, Boost.Test и т. Д.).


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

Visual Studio не использует «сценарии сборки», которые могут быть изменены пользователем. Один проект производит один двоичный файл. Более того, у Java есть свойство, заключающееся в том, что Java никогда не создает полный двоичный файл - создаваемый двоичный файл представляет собой всего лишь ZIP из файлов классов. Поэтому возможно скомпилировать отдельно JAR-файл вручную (например, 7z). C ++ и C # на самом деле связывают свои двоичные файлы, поэтому, вообще говоря, вы не можете написать такой скрипт. Самое близкое, что вы можете получить - это скомпилировать все по отдельности, а затем выполнить две ссылки (одну для производства, другую для тестирования).

Мартин Ба
источник
2
As far as I am aware, you do not add extra "projects" to a Java or C# thing to enable Unit Tests and TDD,<- Я не думаю, что это правильно. Обычно у вас есть несколько проектов на C #; Вы не хотите отправлять свой тестовый код в свой рабочий бинарный файл.
Билли ОНил
2
Я никогда не видел, чтобы это обрабатывалось фреймворком. Генерация двоичного файла требует проекта. Вы хотите два двоичных файла; один с тестовым кодом и один с рабочим кодом. Поэтому вам нужно два проекта. Обойти это невозможно.
Билли ОНил
1
@BillyONeal, во всех, кроме одного из моих (Java) проектов, проект содержит основной и тестовый источники - сценарий сборки затем выбирает, какие части следует поместить в развертываемые артефакты.
Роберт Марк Брэм
2
@ Роберт: Visual Studio не использует «сценарии сборки», которые могут быть изменены пользователем. Один проект производит один двоичный файл. Более того, у Java есть свойство, заключающееся в том, что Java никогда не создает полный двоичный файл - создаваемый двоичный файл представляет собой всего лишь ZIP из файлов классов. Поэтому возможно скомпилировать отдельно JAR вместе вручную (используя, например 7z). C ++ и C # на самом деле связывают свои двоичные файлы, поэтому, вообще говоря, вы не можете написать такой скрипт. Самое близкое, что вы можете получить - это скомпилировать все по отдельности, а затем выполнить две ссылки (одну для производства, другую для тестирования).
Билли ONEAL
4
Шутки в сторону? «Совет: каждый тест должен содержать одну основную функцию и генерировать один исполняемый файл». Это звучит смехотворно медленно для любого разумного количества тестов. Даже если они означают только одно тестовое устройство на исполняемый файл, это все еще глупый совет IMO. Попробуйте сделать это с тысячами тестов (для проекта среднего размера) или сотнями тысяч тестов (для большого проекта), и вы наверняка сойдете с ума.
узаконить

Ответы:

4

Я написал серию из 5 статей о работе с TDD на C ++ и Visual Studio: часть 1 , часть 2 , часть 3 , часть 4 , часть 5 .

Я не уверен, почему вы говорите, что вы не создаете дополнительные проекты в C # для TDD, потому что это то, что я всегда делал с NUnit, и это типично для того, что другие люди делают с NUnit. Причина проста: всегда держите тестовый код отдельно от производственного кода. Для C ++ с Visual Studio это означает отдельные проекты, как это делается для C # и NUnit. Из того, что я знаю о мире Java, это также распространено там.

Очевидно, что у всех разные представления о том, что «терпимо» для выполнения TDD. Я практиковал метод, который обрисовал в общих чертах в своем блоге, я считаю его очень терпимым. C ++ - это скомпилированный язык, и процесс компиляции может быть медленным, когда тестируемая система тесно связана. От этого просто не уйти без рефакторинга в более слабосвязанную конструкцию.

Мое «действие в один клик» - «Построить решение». Если это слишком много, вы всегда можете выгружать ненужные проекты во время работы, а затем Build Solution создаст только минимальное подмножество проектов, которые необходимо обновить в результате ваших изменений.

Конечно, характер времени компиляции C ++ делает это дольше в каждом цикле процесса TDD, чем в NUnit и C #, но уверенность, которую я получаю из своего хорошо протестированного кода C ++, того стоит. В противном случае я буду проводить намного больше времени в отладчике. Я хотел бы предостеречь вас от использования gmock, так как это может существенно увеличить время компиляции теста. До сих пор я в основном получал удовольствие от легких «поддельных» объектов и редко нуждался в полномасштабной функциональности макетов. Фреймворки для C ++ в значительной степени основаны на шаблонах, и это может значительно увеличить время компиляции, поэтому они должны быть зарезервированы для случаев, когда вам действительно нужен макет, а фальшивка просто не подойдет.

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

Что касается решений со многими (150?) Проектами, то есть способы с этим справиться. Один из очевидных - найти группы связанных проектов, объединить их и начать использовать / публиковать как единое целое. Если вам действительно нужно перестроить / обработать все 150 проектов для небольших изменений, которые вы вносите во время цикла TDD, то ваш код в любом случае настолько сильно связан, что модульные тесты вряд ли будут иметь большое значение.

Глядя на ссылке NetBeans IDE, я считаю глаз конфеты иметь что - то , что разбирает результаты теста и показывает небольшой тест строку в окне с зеленым или красным символом рядом с ним то , что я думал , что скучаю, придя из NUnit, но на самом деле не скучал. Я обнаружил, что было бы более полезно, чтобы сборка просто проваливалась, а затем я мог дважды щелкнуть в окне ошибок, чтобы поместить курсор в место несостоявшегося утверждения.

Лигалайз
источник
«... не знаю, почему вы говорите, что не делаете дополнительные проекты в C # ... Из того, что я знаю о мире Java, это также распространено там ...» Возможно, это было ошибочное мнение с моей стороны. (По крайней мере, для .NET, потому что вам нужен исполняемый файл для .NET - для java вам просто нужны файлы классов, поэтому я не совсем понимаю, куда вписался бы дополнительный проект.)
Martin Ba
Я не уверен, как Java работает с проектами; У меня там ограниченный опыт. Из того, что я мало знаю, я понимаю, что проекты - это артефакт IDE, а не язык. (Строго говоря, это также верно для C #, но я не знаю никого, кто бы просто использовал компилятор командной строки для чего-либо, кроме коротких статей или демонстраций в блогах.) Однако даже в Java вы определенно держите тестовый код отдельно от производственный код, который для вас делают отдельные проекты. Я никогда не рекомендую условно компилировать C ++ для разделения производственного и тестового кода.
узаконить
1
«держите тестовый код отдельно от производственного кода, что для вас делают отдельные проекты» - ага! Ну не совсем, ИМХО. Отдельный «проект» является необходимостью для C ++ и .NET, потому что оба должны создать исполняемый файл для запуска чего-либо и создать (один) исполняемый файл, вам нужен (один) проект. Я хорошо держу тестовый код отдельно (или нет) от производственного кода, но я нахожу необходимость добавить (избыточный) «проект» для генерации раздражающего исполняемого файла теста. :-)
Мартин Ба
1
Вам нужны два встроенных продукта: производственный код (статическая библиотека, разделяемая библиотека, исполняемый файл и т. Д.) И тестовый исполняемый файл. В Visual Studio каждый построенный продукт соответствует проекту, поэтому вам нужно два проекта. Это действительно не сложнее, чем это. Проект модульного тестирования НЕ является избыточным.
узаконить
2

Я не использую Visual-C ++, но я выполняю TDD с C ++, используя googletest и googlemock, с QtCreator в качестве моей IDE. Несколько лет назад у меня была похожая настройка с Visual-C ++, но я использовал другую платформу для модульных тестов.

Что я нашел полезным, это разделить проект на несколько подпроектов.

  1. Статическая или динамическая библиотека, которая содержит 99% фактического исходного кода проекта.
  2. Проект, который состоит в основном из метода main () для запуска обычной программы.
  3. Тестовый проект, который содержит функцию main () для запуска моей тестовой среды и множество файлов, содержащих тесты и фиктивные объекты.

При такой настройке моя среда IDE заботится о добавлении файлов в различные проекты, и, если зависимости определены правильно, я могу запустить все свои модульные тесты с частичной перестройкой. У меня даже сейчас настроен запуск всех моих тестов сразу после сборки. Дженкинс, CI, которым я сейчас пользуюсь, также запускает и предоставляет результаты тестов и данные покрытия.

Может быть возможно добавить пользовательский модуль запуска в вашей среде IDE для файла для запуска модульных тестов для файла Foo.cpp, если вы случайно назвали все модульные тесты для Foo в тестовом приспособлении TestFoo. Как настроить это точно для Visual-C ++ Я не уверен, но я думаю, что это возможно.

Кори Д
источник
Полезная информация, хотя я бы зашел так далеко, что назвал ее «общим советом» :-) ... и это не очень реально для наших устаревших вещей, но тогда добавление тестов к устаревшим вещам в любом случае является проблемой ( и мне бы хотелось, чтобы тат меньше всего облегчал добавление тестовой оснастки).
Мартин Ба,
2

Я использую MSTest для тестирования нативного кода C ++.
Вот отличное сообщение в блоге об этом: http://blogs.msdn.com/b/jsocha/archive/2010/11/19/writing-unit-tests-in-visual-studio-for-native-c. ASPX

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

[-] Solution 'Foo'      Foo\Foo.sln
 |-[-] Foo              Foo\Foo\Foo.vcproj
 |  |-[-] include
 |  |  |- foo.h         Foo\Foo\foo.h
 |  |  |- bar.h         Foo\Foo\bar.h
 |  |
 |  |-[-] source
 |     |- foo.cpp       Foo\Foo\foo.cpp
 |
 |-[-] Foo.Tests        Foo\Foo.Tests\Foo.Tests.vcproj
    |                        (Additional include directory: "..\Foo")
    |-[-] include
    |  |- FakeBar.h     Foo\Foo.Tests\FakeBar.h
    |
    |-[-] source
       |-[-] app
       |  |- foo.cpp    Foo\Foo\foo.cpp    -- not in Foo.Tests\
       |
       |-[-] unit-tests
          |- foo_Tests.cpp   Foo\Foo.Tests\foo_Tests.cpp
          |- bar_Tests.cpp   Foo\Foo.Tests\bar_Tests.cpp
Abyx
источник
Я обнаружил, что использование C ++ / CLI для модульного тестирования просто запутывает воду при тестировании чистого нативного кода C ++. Однако я использовал NUnit для тестирования кода приложения C ++ / CLI. Я написал свои тесты на C #, и это сработало просто отлично. (Существующей кодовой базой был C ++ / CLI, и я не хотел переносить ее на C #.)
узаконить
Кроме того, если ваши тесты находятся в C ++ / CLI, вы не можете запускать их на других платформах. В большинстве мест, где я использовал C ++, им нужна была возможность кросс-платформенной компиляции. Конечно, вы не можете повторно использовать проект VS на других платформах, но для него не так уж важно иметь Makefiles или SConscripts для него.
узаконить
@legalize Мы не можем повторно использовать WinAPI (а также COM и другие специфичные для Windows технологии) на платформах, отличных от Windows.
Абикс
Да, конечно, вы не можете использовать специфичные для Windows технологии на платформах, отличных от Windows. Мое наблюдение состояло в том, что если у вас есть независимый от платформы код, вы не хотите связывать свои модульные тесты с конкретной платформой. У предыдущего работодателя мы оценили большое количество структур и методов модульного тестирования. Мы выбрали Boost.Test, потому что он был кроссплатформенным, и, если что-нибудь попадало в стандартную библиотеку C ++ в отношении модульного тестирования, это, скорее всего, Boost.Test.
узаконить
2

Может быть, немного в конце дня, но если я правильно прочитал ваш вопрос, вы ищете методы для улучшения цикла TDD? Здесь не упоминалось, но вы смотрели события после сборки в VS?

Наши решения обычно организованы (показаны зависимости проекта) ...

MAIN-APP > LIB1, LIB2, UNIT-TEST-APP
UNIT-TEST-LIB1 > LIB1
UNIT-TEST-LIB2 > LIB2
UNIT-TEST-APP > UNIT-TEST-LIB1, UNIT-TEST-LIB2

Событие после сборки MAIN-APP будет запускать UNIT-TEST-APP

Событие после сборки UNIT-TEST-APP будет запущено само (просто введите «$ (TargetPath)» в качестве команды для запуска в событии после сборки).

(Это означает, что при создании MAIN-APP модульные тесты могут выполняться дважды, но в нашем случае это не было проблемой!)

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

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

Стив Фолли
источник
1

Ну, не знаю, поможет ли это, но есть несколько отличных видео о TDD от Бретта Л. Шухерта. К сожалению, он не показывает комбинацию "C ++" и "VS", но

TDD с C # и VS: http://vimeo.com/album/210446

TDD с C ++ и Eclipse: http://vimeo.com/13240481

Возможно, вы можете решить это из этих двух.

РЕДАКТИРОВАТЬ: видео C ++ об использовании фреймворка тестирования CppUTest с Eclipse, конечно. Когда я отправил это, я думал, что это должно быть легко принято для использования в VS. Так что я немного погуглил и нашел это:

http://schuchert.wikispaces.com/tdd.cpp.NotesOnCppUTest

который дает вам информацию о том, как использовать CppUTest в Visual Studio.

Док Браун
источник
2
Док - Я (только) посмотрел видео TDD / Eclipse, но я собираюсь понизить это. Видео точно показывает, что меня не интересует, а именно, как написать код модульного теста. Проблема (этого вопроса) не в том, чтобы писать модульные тесты, а в том, как правильно интегрировать их с вашей производственной разработкой на C ++, и я не вижу, как эти видео помогают здесь.
Мартин Ба
Хотя я и проголосовал против этого ответа в контексте этого вопроса, я хотел бы добавить, что видео довольно хорошие. Я нашел Eclipse / TDD / C ++ интересным для просмотра. Это только не помогает здесь :-)
Мартин Ба
@Martin: см. Мое редактирование.
Док Браун
Мы ценим ваши усилия, и хотя я не думаю, что эта дополнительная ссылка действительно полезна в контексте этого вопроса, я думаю, что мне нужно будет немного отредактировать себя.
Мартин Ба
@Martin: хорошо, я снова прочитал ваш вопрос и ваше определение «терпимо», но разве вы не ожидаете слишком многого? Настройка проекта модульного тестирования - это не решение «в один клик», но усилия по написанию реальных модульных тестов перевешивают их на порядки, независимо от того, какую среду вы используете.
Док Браун
1

Googletest
Как интегрироваться с vc ++

Вам не нужен плагин, тест является еще одной целью. Нет плагинов для генерации теста с c ++, даже если бы вы могли это тестировать бессмысленные вещи, такие как задания

Мартин Беккет
источник
«даже если бы вы могли это проверять бессмысленные вещи, такие как задания» - что это должно означать? Вы действительно думаете, что лучшая поддержка IDE для модульных тестов в C ++ ничего не стоит ??
Мартин Ба
Я имею в виду, что на языке, подобном с ++, система не может автоматически создавать тесты для чего-либо, кроме очевидных утверждений
Мартин Беккет,
2
Почему бы нет? Что мешает плагину для автоматической генерации vcprojфайла на лету, извлечения файла тестового файла, который я написал, и рабочего файла, на который есть ссылка, и попытки его запустить? (Просто мечтаю, но это можно заставить работать.)
Мартин Ба
2
Я не уверен, что могу следовать. очевидно, я должен написать тесты сам. Но их запуск может быть намного проще, чем ручная настройка (и поддержка!) Отдельных файлов test-project.
Мартин Ба
2
Нет, я не имел в виду тестовый код, а скорее скаффолдинг проекта / компилятора, необходимый для получения тестового кода плюс работающий производственный код.
Мартин Ба
1

Не могу комментировать инструменты C ++, поскольку я не касался около 20 лет (в наши дни .NET dev), и я думаю, что большинство инструментов в эти дни предназначены для управляемого кода, а для методов ...

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

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

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

Книга, которую вы можете найти полезной; Майкл Фезерс, эффективно работающий с Legacy Code. Он использует несколько языков в своих примерах и может помочь вам определить конкретные подходы для безопасной адаптации кода / методов, которые изначально не были предназначены для тестирования.

Небольшое предостережение: я пьян от Agile Kool-Aid много лет назад: D

Крис Ли
источник
Примечание: у меня уже есть Working Effectively with Legacy Codeна моем столе :-)
Мартин Ба
0

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

В поисках плагинов я нашел:

http://incubator.apache.org/npanday/

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

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

Гьян ака Гари Буйн
источник
0

Рекомендация по фреймворку: в нашем офисе мы используем TestDriven.NET, который интегрируется с Visual Studio. Классы unittest написаны на C ++ / CLI, который затем может вызывать для выполнения любой нативный код, который вам нужно протестировать. Да, классы C ++ / CLI собираются в свою собственную сборку, поэтому к решению (ям) добавляется «тестирующий» проект.

Крис О
источник