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

Единичное тестирование неэкспортированных классов в DLL

Мы разрабатываем С++-приложение с использованием Visual Studio 2008 и unit test с помощью Boost.Test. На данный момент у нас есть отдельное решение, которое содержит наши модульные тесты.

Многие из наших проектов в основном решении создают DLL. Мы ограничены в охвате тестированием, потому что мы не можем тестировать неэкспортированные классы.

У меня есть две идеи о том, как они могут быть протестированы:

  • Экспортировать все
  • Поместите тесты внутри DLL (тот же проект и решение) и используйте внешний бегун Boost.Test

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

Итак, существуют ли какие-либо серьезные недостатки вышеприведенных методов или вы можете думать о других решениях?

4b9b3361

Ответ 1

Развернув на Tom Quarendon ответ на этот вопрос, я использовал небольшой вариант ответа Саймона Стил:

  • Создайте тестовый проект (используя любую структуру тестов, которая вам нравится, я использую CppUnit).
  • В вашем файле test_case.cpp, #include <header/in/source/project.h>.
  • В свойствах тестового проекта:
    • В Linker- > General добавьте исходный проект $(IntDir) в дополнительные библиотеки.
    • В Linker- > Input добавьте файлы .obj к дополнительным зависимостям.
  • Добавьте зависимость от тестового проекта к исходному проекту в Project- > Project Dependencies.

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

Ответ 2

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

Другая возможность заключалась бы в компиляции неэкпортируемого кода в lib, который используется как DLL с экспортом, так и проектом unit test.

Ответ 3

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

Добавить новую конфигурацию сборки, например. "Unit testing Debug" в проект DLL и измените тип конфигурации "Статическая библиотека .lib" ( "Общие" → "Тип конфигурации" ).

Затем просто добавьте зависимость от ваших модульных тестов в этом проекте, теперь все должно связываться, когда вы используете новую конфигурацию сборки "Unit testing Debug". Если вы используете сборки релизов для модульных тестов, вам нужно добавить еще одну конфигурацию с оптимизацией выпуска.

Таким образом, преимущества этого решения заключаются в следующем:

  • низкая стоимость обслуживания.
  • один проект библиотеки DLL/Static
  • не нужно вручную ссылаться на файлы .obj.

Недостатки:

  • Дополнительные профили конфигурации потребуют некоторых изменений в вашей среде сборки (CI).
  • Большее время компиляции

Обновление: На самом деле мы использовали другой подход.

Мы добавили новые конфигурации "Test debug" / "Test release" для каждого существующего проекта, который у нас есть.

Для проектов .exe/.dll мы отключаем исходный файл main.cpp от компиляции и заменяем его тем, который создает среду тестирования (например, gtest) и запускает все тесты, тесты находятся в отдельных файлах .cpp, которые также исключается из компиляции в обычных конфигурациях (Release/Debug) и разрешается только в тестовых конфигурациях.

Для проектов .lib у нас также есть новые конфигурации "Test debug" / "Test release", и мы преобразуем статическую библиотеку в файл .exe и предоставляем main.cpp, который создает среду тестирования и запускает тесты и сами тестируют. Файлы, связанные с тестированием, исключаются из компиляции в конфигурациях Release/Debug.

Ответ 4

Попробуйте сделать определение, например следующее: все файлы будут включать:

#define EXPORTTESTING __declspec(dllexport)

И используйте его вместо dllexport, например:

class EXPORTTESTING Foo 
{
 ...
};

Затем вы сможете отключить флаг для создания DLL-релиза, но сохраните его для DLL с возможностью тестирования.