Путь наименьшего сопротивления при модульном тестировании кода на С++ в exe, в Visual Studio 2012

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

Мне было приятно видеть, что Visual Studio 2012 теперь изначально поддерживает TDD на С++, поэтому я пошел дальше и прочитал как можно больше. К сожалению, Vs2012 является довольно новым, и я чувствую, что документация несколько отсутствует. Но это немного близко к делу. Я полагаюсь в основном на следующее руководство на сайте MSDN:

http://msdn.microsoft.com/en-us/library/hh419385.aspx#objectRef

В нем четко сказано, что если тестируемый код должен быть построен как .exe, то путь вперед создает отдельный тестовый проект и связывает выходной файл объекта. Я предполагаю, что они означают объектные файлы? Или, может быть, нет?

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

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

Ответ 1

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

  • Проект .lib, в котором есть исходный код.
  • Исполняемый проект, связанный с .lib. Это вызывает в .lib в вызове main()
  • Проект тестирования (exe), связанный с .lib.

С помощью этой структуры вы можете использовать кнопку Add New Reference... в разделе Common Properties, и ссылки будут отсортированы для вас (кроме заголовка include path, найденного в C++\General\Additional include directories).

Если вы не хотите реструктурировать свои проекты, вы можете рассказать компоновщику о каждом файле obj (Linker\Input\Additional dependencies). Это может быть значительное количество файлов .obj, если у вас много классов, которые вы хотите протестировать. К сожалению, у вас могут возникнуть проблемы, если вы используете предварительно скомпилированные заголовки.

Я бы предложил реструктурировать проекты, если вы можете.

Ответ 2

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

enter image description here

(Не волнуйтесь о вещах .NET на скриншоте, это было взято из проекта, в котором DLL С++/CLI включала собственный статический библиотечный проект. Просто сделайте то же самое с собственным тестовым проектом, включая родную DLL или EXE, выбрав ссылку со входами.)

Ответ 3

Unit Test Проект для собственного приложения (.exe) Project

  • Добавить проект Unit Test в решение
     Щелкните правой кнопкой мыши на Solution, Add, New Project. В Visual С++ выберите Native Unit Test Project.
  • Добавить приложение в качестве ссылки на проект Unit Test
    Щелкните правой кнопкой мыши проект Unit Test, Свойства, Общие свойства, Ссылки: Добавьте проект .DLL в качестве ссылки. Это говорит о том, что MSVC перестраивает приложение, если оно изменилось со времени последней сборки Unit Test, прежде чем перестраивать проект Unit Test.
  • Сообщите MSVC, где искать библиотеку приложений и файлы объектов
     Щелкните правой кнопкой мыши проект Unit Test, свойства, компоновщик, общий: отредактируйте дополнительные библиотечные каталоги и добавьте пути к объектам и библиотекам приложений.
  • Соберите все имена .obj и .lib
     Запустите этот командный файл из подкаталога или подкаталогов, где находятся ваш объект приложения и файлы библиотеки, объедините файлы .txt, если существует несколько каталогов. Для удобства вы можете добавить файл .txt в свой проект.

     : *** CollectObjLibFilenames.bat ***
     dir /B *.obj > ObjLibFilenames.txt
     dir /B *.lib >> ObjLibFilenames.txt

  • Скажите MSVC связать файлы приложения с приложением Unit Test
     Щелкните правой кнопкой мыши проект Unit Test, Свойства, Linker, Input: Edit Additional Dependencies и добавьте имена файлов и имена файлов приложения (.obj и .lib) (скопируйте и запустите файлы из ObjLibFileNames.txt).
    Если ваш проект приложения использует предварительно скомпилированные заголовки, не забудьте включить предварительно скомпилированный файл (-и) заголовка заголовка, обычно stdafx.obj. Если вы опустите его, вы получите сообщение об ошибке LNK2011.

    Microsoft говорит "Если вы используете предварительно скомпилированные заголовки, LINK требует, чтобы все объектные файлы, созданные с предварительно скомпилированными заголовками, были связаны."

    Я думал, что будет столкновение имен, если я добавлю объектный файл, содержащий точку входа в приложение, main(int argc, char *argv), но мои проекты проектов Unit Test успешно работают с или без main.obj. Я не пытался связать файл с другими элементами входа (WinMain, wWinMain, wmain). Если у вас есть столкновение имен с одним из них, вы можете изменить имя своей точки входа (что было бы странно): Properties, Linker, Advanced, отредактировать точку входа и переименовать функцию точки входа приложения соответственно. Опция не указана в проекте Unit Test, на который я только что посмотрел, что я подразумеваю по умолчанию, что почти наверняка составляет main(int argc, char *argv).

    Мои файлы main.cpp имеют только одну функцию (основную) и глобальные, т.е. Никакая другая часть приложения не ссылается на что-либо в main.cpp. Я предполагаю, что вы можете уйти с отсутствием любого объектного файла, если в нем нет ссылки связанного файла. Не стоит пытаться выяснить, какие требования удовлетворяют этим требованиям для небольших приложений. Для больших приложений... удачи в этом; В конце концов, вы все равно захотите проверить все свои пути выполнения.

    Вероятно, у вас будет предварительно скомпилированный файл объекта заголовка, файл stdafx.obj в проекте Unit Test, а также проект в вашем проекте приложения. Это не будет проблемой, поскольку имена объектных файлов по умолчанию для предварительно скомпилированных файлов заголовков: $(TargetName).pch, где $(TargetName) разрешает имя проекта. I.e., файлы объектов pch будут иметь разные имена.

    Предположение: вместо копирования содержимого моего файла приложения stdafx.h в соответствующий файл Unit Test, включите приложение stdafx.h в файл stdafx.h проекта Unit Test, поэтому вам не нужно обновлять Unit Test при изменении файла приложения. #include <stdafx.h> работает, но я использую относительный путь между двумя проектами (если их относительные пути стабильны) или полный путь к исходному файлу приложения, если он более стабилен, чтобы убедиться, что правильный файл найден. См. difference-between-include-hpp-and-include-hpp для беспокойства о том, как интерпретируются #include "header.h" и #include. Спойлер: это еще одна особенность реализации С++.
    _________________________________________________________________________

    Как и в стороне, предварительно скомпилированные файлы заголовков указываются в исходном файле (.cpp). Отдельный .cpp файл может использовать только один предварительно скомпилированный файл заголовка, но вы можете иметь более одного предварительно скомпилированного файла заголовка в том же проекте. См. следующее: