Как структурировать модульные тесты для приложения с графическим интерфейсом, используя C # и NUnit

16

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

Моим первым инстинктом было просто включить тесты в код приложения, однако для этого потребовалось бы предоставить ряд специфичных для тестов зависимостей, которые я получил от инструкций, чтобы не доставлять их заказчику. Я также не могу выдать наличные деньги за специально созданный инструмент тестирования, поэтому мне нужно использовать имеющиеся у меня инструменты ( StoryQ , RhinoMocks и NUnit), которого на самом деле должно быть более чем достаточно, чтобы протестировать поведение простого приложения с графическим интерфейсом. Так что, насколько я вижу, это оставляет мне попытку найти хороший баланс между сохранением дизайна действительно простым или намеренно чрезмерным проектированием ради тестов. Похоже, я либо собираю приложение с бизнес-логикой в ​​отдельной библиотеке и тестирую по ней, как обычно, либо нахожу какой-то другой механизм, позволяющий мне запустить исполняемый файл, не разбивая дополнительные модули, которые дизайн приложения не делает очень нужно.

Изменить:
Обратите внимание, что этот вопрос о том, как структурировать отношения между NUnit и моим исполняемым файлом - в отличие от DLL - а не о том, как разделить представление и бизнес-логику.
/Редактировать

Итак, мой вопрос:

  1. Существует ли определенный / рекомендуемый метод для настройки простого приложения с графическим интерфейсом пользователя с помощью модульных тестов, позволяющий мне адекватно проверять состояние и поведение, используя имеющиеся у меня инструменты и не прибегая к чрезмерной разработке?
  2. Я пропустил что-то фундаментальное в том, как NUnit должен вызываться / настраиваться при тестировании EXE (в отличие от DLL)?
  3. Можете ли вы привести или указать мне примеры примеров того, как всего этого достичь?

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

S.Robins
источник
NUnit не предназначен для непосредственного тестирования GUI. Вам необходимо отделить уровень представления (т. Е. Представление) от данных и бизнес-логики (т. Е. Модели), чтобы можно было проверить, что входит в представление, без использования представления.
Бернард
1
@Bernard Этот вопрос не касается наслоения графического интерфейса для тестирования. Естественно, я делаю все свои приложения, даже тривиальные, так, чтобы это не было для меня проблемой. Я отредактировал вопрос так, чтобы он подходил, и я надеюсь, что он прояснит любые заблуждения. :)
С.Робинс
1
Нет ничего страшного в модульном тестировании в EXE-файлах. Просто сделайте так, чтобы ваша тестовая DLL ссылалась на ваш EXE-файл, и все готово.
whatsisname

Ответы:

3

В одном из моих комментариев к ответу симорамана я упомянул , что подумал о нескольких способах сделать это. Один из моих вариантов был похож на предложение в ответе Джалайна создать дублированный проект и сгенерировать DLL, в то время как другой моей идеей было просто связать файлы в проекте, где был код, который я хотел протестировать. Хотя оба варианта могут работать, они не идеальны.

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

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

S.Robins
источник
2

Я так думаю:

  • Код вашего бизнес-теста должен быть в отдельном проекте, тестирующем вашу библиотеку бизнес-кода.
  • Ваш тестовый код GUI должен быть в отдельном проекте, тестирующем вашу библиотеку GUI. Теперь, как построить библиотеку GUI вместо исполняемого файла, я попытаюсь ответить на это позже.
  • Если у вас есть my.namespace.biz.MyClass, ваш тестовый класс должен быть my.namespace.biz.MyClassTest (или MyClassTestCase).
  • Если вы хотите протестировать код, найденный в вашей исполняемой цели, то у вас должна быть установка, которая создает EXE, и другая установка, которая создает библиотеку (DLL), для которой вы будете запускать свои тесты.

Это правила, которым я хотел бы следовать, будь то Java или C # (за исключением того, что нет проблем с EXE с Java, конечно :-))

Что касается настройки вашей тестовой среды, мне кажется, что у вас есть по крайней мере эти два варианта:

Использование MSBuild

Создайте клон вашего файла .proj (скажем, myproject-as-dll.proj ). Измените OutputTypeв клонированном файле с " EXE" на " Library". С помощью команды MSBuild вы теперь можете создать библиотеку, которую вы можете установить в качестве ссылки в свой проект, содержащий тестовые примеры NUnit.

Кажется, это возможно для меня, но я никогда не использовал это так честно, поэтому я не уверен. Кроме того, у вас может не быть MSBuild на сервере тестирования интеграции, и я не знаю, можно ли его отделить от Visual Studio ...

Использование NAnt

Если вы не знакомы с NAnt, вам придется поискать, как настроить сборки проекта с его помощью. Может быть, проверить это , это немного устарело, но автор прокомментировал файлы NAnt, и если это окажется само собой разумеющимся. ( Правка: изучая его файл более подробно, я нахожу его файл конфигурации чрезвычайно пригодным для повторного использования ). Он также делает гораздо больше, чем просто строит, так как он выполняет тестовые случаи и запускает инструменты покрытия кода. Теперь я признаю, что никогда не использовал NAnt, в отличие от его Java-аналога и отцовского "Ant", которым я часто пользовался, но я вижу, что это одно и то же, и я не думаю, что это так сложно выучить.

С помощью этого инструмента вы можете создать конфигурацию, которая позволит вам:

  • Соберите все свои проекты (бизнес-логика, GUI и т. д.) в отдельные библиотеки
  • строить свои тестовые проекты
  • запустить тесты (эта конкретная часть выполняется с помощью задачи NUnit2 ).
  • проверьте покрытие кода с помощью задачи NCover .

С небольшим количеством кода вы можете даже:

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

Все делается без изменений в файлах Visual Studio. И, на самом деле, это не выглядит чрезмерно для меня, это всего лишь один файл. На то, чтобы все это заработало, у вас может уйти один, а может и два дня, но, на мой взгляд, у вас будет хорошая настройка.

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

Jalayn
источник
0

Тот факт, что проект мал (изначально), не означает, что правильная архитектура чрезмерна. Тот факт, что вы хотите писать тесты, говорит о том, что ваш проект не является тривиальным разовым взломом.

Вы не упомянули, какой GUI-Framework вы используете. WPF MVVM (Model-View-ViewModel) хорош и позволяет довольно легко писать тесты для всей логики. С WinForms я слышал хорошие вещи о MVP (Model-View-Presenter)

simoraman
источник
Я пишу тесты для всего кода, который я пишу. Даже вещи, которые вы могли бы найти тривиальными. Единственный раз, когда я не пишу тест, это когда я спайк. В этом случае я отправляю одноразовую утилиту заказчику, поэтому тестирование - это больше, чем просто роскошь, это требование для удовлетворения наших стандартов качества. С точки зрения «чрезмерного проектирования», это не выбор между хорошей или плохой архитектурой, а скорее избегание необходимости навязывать дополнительные уровни, которые не требуются в этом случае, так как приложение является единственной целью с относительно коротким жизненным циклом.
С.Робинс
Что касается выбора gui-framework, я не вижу, как это повлияет на настройку среды тестирования. Я ищу, КАК конкретно реализовать модульные тесты для уровня GUI, используя доступные мне инструменты. Этот конкретный ответ на самом деле ничего не говорит мне об этом.
С.Робинс
Simoraman - Если вы уберете довольно поверхностный первый абзац, вы получите ответ. Исправьте это, и я уберу свой -1. @ S.Robins отметить , что второй пункт является актуальным - хотя и не полный ответ, это помогло бы. Если ваш уровень графического интерфейса тонкий, хорошо структурированный и очевидный, а вся бизнес-логика проверена модульными тестами на уровне модели, возможно, вам не понадобится проходить лишние хлопоты по явному тестированию пользовательского интерфейса.
Марк Бут
1
Расслоение @MarkBooth на самом деле не проблема. Как упоминает симираман, я могу создать MVP, MVVM или создать что-то более тонкое. У меня, однако, есть некоторые специфичные для GUI элементы, которые потребуют явного тестирования, поэтому я решил написать это как вопрос. У меня есть пара идей, и если хуже станет хуже, я знаю, что со временем смогу решить проблему и сам напишу ответ. Однако я хотел открыть это для сообщества, так как думал, что это станет хорошим вопросом для ProgrammersSE. ;-)
S.Robins
0

Посмотрите на мой ответ на этот вопрос: как мне настроить MVP для решения Winforms?

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

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

Брайан Бетчер
источник
Спасибо за рекомендацию ReSharper. Это инструмент, который я использую при разработке. К сожалению, это не поможет при выполнении тестов на сервере интеграции сборки. Это также не говорит мне, как настроить тесты Nunit для доступа к коду в exe при тестировании.
С.Робинс
1
Неформально это так. Exe - это просто представление, которое загружает презентатора, модели и модели представления из библиотеки классов в процессе запуска приложения. По крайней мере, в моем решении представление настолько глупо, что мы не тестируем его с помощью автоматических тестов, а просто проводим приемочные тесты, чтобы убедиться, что все написано правильно, а кнопки находятся там, где они должны быть. NUnit-тестирование DLL очень легко сделать.
Брайан Бетчер
0

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

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