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

14

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

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

Для этого хорошая идея:

  • Чтобы использовать модульные тесты, чтобы иметь представление о времени, потраченном на выполнение одного и того же действия² n раз,

  • Использовать тайм-аут на тестирование через [TestMethod, Timeout(200)]атрибут в C #?

Я ожидаю несколько проблем с этим подходом:

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

  • Действительно ли время ожидания модульных тестов в Visual Studio измеряет то, что ожидается измерить, учитывая, что инициализация и очистка для этих тестов отсутствуют или слишком коротки, чтобы повлиять на результаты?

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

  • Разработка через тестирование (TDD) невозможна для этих тестов. Как он потерпит неудачу, прежде всего, перед тем, как приступить к реализации кода?

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

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

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

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


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

«Под действием я подразумеваю довольно короткий фрагмент кода, который тратится на выполнение нескольких миллисекунд.

Арсений Мурзенко
источник

Ответы:

3

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

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

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

Тем не менее, вот несколько моментов для ваших соответствующих проблем:

  • концептуально: это правда, что это не то, что такое юнит-тесты. Но пока все знают, что тест не должен проверять что-либо, что должен делать QA, это нормально.

  • Visual Studio: ничего не могу сказать по этому поводу, так как мы не используем инфраструктуру модульного тестирования от VS.

  • Машина: зависит от продукта. Если ваш продукт разработан для конечных пользователей с индивидуальными настольными компьютерами, то на самом деле более реалистично выполнять тесты на машинах разных разработчиков. В нашем случае мы поставляем продукт для машины с заданной спецификацией и выполняем эти тесты производительности только на такой машине. Действительно, нет смысла измерять производительность на вашей двухъядерной машине разработчика, когда клиент в конечном итоге будет работать с 16 или более ядрами.

  • TDD: Хотя первоначальный сбой типичен, это не обязательно. На самом деле, написание этих тестов на ранних этапах делает их скорее регрессионным, нежели традиционным модульным тестом. То, что тест проходит успешно на ранних стадиях, не проблема. Но вы получаете то преимущество, что всякий раз, когда разработчик добавляет функциональность, которая замедляет работу, потому что он / она не знал о требовании нефункциональной производительности, этот тест TDD обнаружит его. Бывает много, и это потрясающая обратная связь. Представьте себе, что в вашей повседневной работе: вы пишете код, фиксируете его, вы идете на ланч, а когда вы вернетесь, система сборки сообщает вам, что этот код при выполнении в среде с большой нагрузкой слишком медленный. Это достаточно приятно для меня, чтобы признать, что тест TDD изначально не провалился.

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

Фрэнк
источник
3

Я в основном согласен с вашим мышлением. Просто мириться с независимым потоком.

1. Сделайте так, чтобы оно работало, прежде чем делать его лучше / быстрее.
Прежде чем код обеспечит какую-либо меру производительности (не говоря уже о гарантировании), его нужно сначала исправить то есть сделать его функционально работающим. Оптимизация кода, которая является функционально неправильной, является не только пустой тратой времени, но и препятствует разработке.

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

3. Масштабирование производительности должно выполняться по целям.
Когда у вас есть функциональная система, вам необходимо проанализировать производительность системы и найти узкие места, чтобы понять, где вам нужно увеличить производительность. Слепая попытка оптимизировать каждый метод даже до того, как вы узнаете, что производительность полной системы может повлечь за собой бесполезную работу (оптимизация методов, которая не имеет значения) и может создать ваш код излишне раздутый.

Я не совсем осведомлен о функциональности Visual Studio, но, как правило, вам нужен более широкий инструмент профилирования.

Дипан Мехта
источник
2

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

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

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

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

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

Олег Колосов
источник
0

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

Майк Баранчак
источник