Как бороться с длительными модульными тестами?

У меня около 100 модульных тестов с охватом 20%, который я пытаюсь увеличить, а также это проект в разработке, поэтому продолжайте добавлять новые тесты.

В настоящее время выполнение моих тестов после каждой сборки невозможно, они занимают около 2 минут.

Тест включает:

  • Файл, прочитанный из тестовых папок (стиль, управляемый данными, для имитации некоторых вещей HTTP)
  • Выполнение фактических HTTP-запросов к локальному веб-серверу (это огромная боль, чтобы высмеивать, поэтому я не буду)
  • Не все из них модульные тесты, но есть также довольно сложные многопоточные классы, которые необходимо протестировать, и я тестирую общее поведение теста. Это можно рассматривать как функциональное тестирование, но его тоже нужно запускать каждый раз.

Большая часть функциональности требует чтения HTTP, выполнения TCP и т. д. Я не могу их изменить, потому что в этом вся идея проекта, если я изменю эти тесты, будет бессмысленно тестировать материал.

Также я не думаю, что у меня есть самые быстрые инструменты для запуска модульных тестов. Моя текущая установка использует VS TS с Gallio и nUnit в качестве фреймворка. Я думаю, что VS TS + Gallio тоже немного медленнее, чем другие.

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

Дальнейшее уточнение Править:

Код - сильно связаны! К сожалению, изменение похоже на огромный процесс рефатирования. И в нем есть синдром куриного яйца, когда мне нужны модульные тесты для рефакторинга такого большого кода, но у меня не может быть больше модульных тестов, если я его не реорганизую :)

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

И я могу подтвердить, что все модульные тесты (с должной изоляцией) на самом деле довольно быстрые, и у меня нет проблем с производительностью с ними.


Дальнейшее уточнение:

Код - сильно связаны! К сожалению, изменение похоже на огромный процесс рефатирования. И в нем есть синдром куриного яйца, когда мне нужны модульные тесты для рефакторинга такого большого кода, но у меня не может быть больше модульных тестов, если я его не реорганизую :)

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

И я могу подтвердить, что все модульные тесты (с должной изоляцией) на самом деле довольно быстрые, и у меня нет проблем с производительностью с ними.

За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
TL;DR: Angular Signals может облегчить отслеживание всех выражений в представлении (Component или EmbeddedView) и планирование пользовательских...
Sniper-CSS, избегайте неиспользуемых стилей
Sniper-CSS, избегайте неиспользуемых стилей
Это краткое руководство, в котором я хочу поделиться тем, как я перешел от 212 кБ CSS к 32,1 кБ (сокращение кода на 84,91%), по-прежнему используя...
8
0
3 894
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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

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

Можете ли вы сказать, какие тесты у вас есть: модульные (тестирование только одного объекта) и функциональные тесты (тестирование двух или более объектов одновременно)? Какие из них быстрые, а какие медленные?

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

dr. evil 15.12.2008 18:29

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

Brad Wilson 15.12.2008 19:00

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

dr. evil 15.12.2008 20:17

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

Во-первых, это не модульные тесты.

Нет особого смысла запускать подобные функциональные тесты после каждого небольшого изменения. После значительных изменений вы захотите запустить функциональные тесты.

Во-вторых, не бойтесь издеваться над Http-частью приложения. Если вы действительно хотите провести модульное тестирование приложения, это ОБЯЗАТЕЛЬНО. Если вы не хотите этого делать, вы потратите гораздо больше времени, пытаясь проверить свою фактическую логику, ожидая возврата HTTP-запросов и пытаясь настроить данные.

Я бы сохранил ваши тесты уровня интеграции, но постараюсь создать настоящие модульные тесты. Это решит ваши проблемы со скоростью. Настоящие модульные тесты не имеют взаимодействия с БД или HTTP-взаимодействия.

Я всегда использую категорию «LongTest». Эти тесты выполняются каждую ночь, а не днем. Таким образом, вы можете значительно сократить время ожидания. Попробуйте: классифицируйте свое модульное тестирование.

Я думаю, мне нужно поиграть с панелями VS TS, я обычно использую NUnit, но почему-то после последних обновлений .NET Framework графический интерфейс NUnit не работает, поэтому я застрял с глупым MS test Suite и Gallio.

dr. evil 15.12.2008 20:20

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

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

Я согласен с Брэдом, что это похоже на функциональные тесты. Если бы вы могли разобрать код, это было бы здорово, но до тех пор я бы переключился на менее частое тестирование.

Собственно в настоящее время я этим и занимаюсь. Просто запускайте юнит-тесты примерно 3 раза в день.

dr. evil 15.12.2008 18:46

Я бы порекомендовал комбинированный подход к вашей проблеме:

  • Часто запускайте подмножество тестов, близких к коду, в который вы вносите изменения (например, тесты из того же пакета, модуля или аналогичного). Реже запускайте тесты, которые дальше удалены от кода, над которым вы сейчас работаете.
  • Разделите свой набор как минимум на две части: быстрые и медленные тесты. Чаще запускайте быстрые тесты.
  • Подумайте о том, чтобы некоторые из тестов с меньшей вероятностью провалить тесты выполнялись только автоматизированным сервером непрерывной интеграции.
  • Изучите методы повышения производительности ваших тестов. Самое главное, заменив доступ к медленным системным ресурсам более быстрыми фейками. Например, использовать в памяти потоки вместо файлов. Заглушка / имитация http-доступа. и т.п.
  • Узнайте, как использовать методы устранения зависимостей с низким уровнем риска, например, перечисленные в (очень рекомендуемой) книге «Эффективная работа с устаревшим кодом». Это позволяет вам эффективно сделать ваш код более тестируемым без применения рефакторинга с высоким риском (часто за счет временного ухудшения фактического дизайна, например нарушения инкапсуляции, до тех пор, пока вы не сможете выполнить рефакторинг для улучшения дизайна с помощью страховочной сети тестов).

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

Другие вопросы по теме