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

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

$('body').on('hidden.bs.modal', '.modal', function () { 
  $(this).find('input[type="text"],input[type="email"],textarea,select').each(function() { 
    if (this.defaultValue != '' || this.value != this.defaultValue) {
         this.value = this.defaultValue; 
    } else { this.value = ''; }
  }); 
}); 
32
задан IAdapter 18 June 2009 в 07:19
поделиться

16 ответов

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

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

Время ваших тестов . Обычно 90% из них выполняются практически мгновенно, а последние 10% занимают почти все время. Найдите эти 10% и посмотрите, что они делают.

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

29
ответ дан 27 November 2019 в 20:13
поделиться

Ну, я не знаю, что делает ваш Unit-тест, но вы должны спросить себя , почему он занимает 20 минут. По моему опыту, часто бывает много тестов, которые выполняются за несколько миллисекунд, и несколько тестов, которые составляют остальное необходимое время. Чаще всего это тесты с участием IO / network / DB-Stuff. Например, если вы тратите много времени на ожидание из-за сетевых задержек, вы можете рассмотреть возможность параллельного запуска тестов.

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

2
ответ дан 27 November 2019 в 20:13
поделиться

Перенести полный набор тестов в систему движка непрерывной интеграции, чтобы разработчикам не приходилось запускать их все каждый раз. У таких систем НАМНОГО больше терпения, чем у разработчиков.

1
ответ дан 27 November 2019 в 20:13
поделиться

Я согласен с Паблоджимом. Распараллеливайте свои тесты. Мы используем clearcase, и передача всего с серверов просмотра действительно замедляет работу. Когда мы распараллелили duelcore, мы получили более короткий тестовый прогон в 6-8 раз.

Мы используем фреймворк CPPUnit и просто добавили скрипты Python для запуска различных наборов тестов в разных потоках.

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

1
ответ дан 27 November 2019 в 20:13
поделиться

Очевидно, что в вашем тесте есть что-то, что занимает много времени.

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

Остальные тесты медленны либо потому, что они выполняют ввод-вывод, либо потому, что они чрезмерно ограничены процессором.

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

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

Тесты ограничения ЦП также бывают разных видов. Чистая проверка производительности и пропускной способности должна быть на этапе тестирования интеграции. Если вы запускаете кучу потоков, чтобы попытаться выявить ошибку параллелизма, вы можете переместить большой тест в фазу интеграции и сохранить «облегченную» версию в своем обычном наборе тестов.

И, наконец, профилировщик твой друг.

3
ответ дан 27 November 2019 в 20:13
поделиться

Используете ли вы fork = "yes" в своем вызове junit ? Если это так, убедитесь, что вы установили forkMode = "once" , иначе задача junit запустит новую виртуальную машину для каждого класса TestCase. С 3000 модульных тестов это будет иметь огромное значение.

http://ant.apache.org/manual/Tasks/junit.html

4
ответ дан 27 November 2019 в 20:13
поделиться

Для начала:
a) Получите статистику о времени выполнения ваших тестов Junit. Возможно, вы уже указываете эту информацию в своих отчетах об испытаниях.
б) Возьмите 10 лучших тестовых классов (по времени) и постарайтесь сократить время. Это нужно делать на постоянной основе.
c) Попробуйте сократить время выполнения за счет рефакторинга или даже изменения подхода к тестированию.
Один из таких случаев, с которыми я столкнулся, находится в одном классе Test для тестовых примеров CRUD. Тестовый пример обновления сначала создавал функциональность, а затем обновлял. Но мы уже тестировали создание в отдельном тестовом примере. Поэтому в этих случаях вы можете связать свои тестовые примеры, например

@Test()
    public void testCreate() throws Exception
    {}
    @Test(dependsOnMethods = "testCreate")
    public void testAmend() throws Exception
    {}
    @Test(dependsOnMethods = "testAmend")
    public void testDelete() throws Exception
    {} 

Таким образом, вы экономите на повторном тестировании.

г) Был еще один случай, когда я смог значительно сократить время. У нас была система (inherietd), в которой каждый тестовый пример вызывал SetUp (Strating Spring Server и т. Д.) И после запуска отключал системные ресурсы. Это занимало очень много времени, поэтому я реорганизовал ее, чтобы запустить ресурсы coomon перед тестовым костюмом и после того, как весь набор готово, затем закройте их.

e) В зависимости от вашего проекта могут возникнуть другие узкие места, которые вам, возможно, придется устранить.

Как управлять временем сборки в TDD

5
ответ дан 27 November 2019 в 20:13
поделиться

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

Если так, один из подходов - это многопоточность выполнения вашего теста. Test-NG очень хорошо это поддерживает. Преобразование тестов из junit в test-ng не так сложно, и их нужно выполнить только один раз.

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

@Test(sequential = true)
public class ATest {
  ...

На многоядерной машине вы увидите огромные улучшения во времени выполнения. Даже на одном ядре вы увидите хорошее улучшение, так как некоторые потоки ждут операций io.

Подробнее о том, как это настроить, см. Здесь:

http://beust.com/weblog/archives/000407 .html

Надеюсь, это поможет.

....

Еще несколько предложений - Не могу поверить, что вы не используете непрерывную интеграцию. Поверьте, 30 разработчиков не станут перегружать ваш CI-сервер. Даже если вы не можете получить бай-ин для CI, установите hudson на свой компьютер - это займет 10 минут, и преимущества огромны. Спросите своего менеджера, что хуже, если каждый разработчик ждет завершения модульных тестов или сервер делает это за вас. Иметь дурацкую шляпу для человека, который сломал сборку, обычно достаточно, чтобы убедить разработчиков запустить свои модульные тесты.

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

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

Но помните, что умные инструменты, такие как test-ng, teamcity и clover, дадут вам только пока - хорошие тесты не будут писать сами себя!

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

  1. Оптимизация тестов - макеты, стандартная настройка и т. д.
  2. Запуск тестов параллельно
  3. Получите что-нибудь еще для запуска тестов - сделайте это автономной задачей, используя hudson или аналогичный
  4. Запускать только тесты, которые необходимо запустить - рассортируйте их по пакетам или используйте клевер и бамбук.
4
ответ дан 27 November 2019 в 20:13
поделиться

Вы можете разделить свои модульные тесты на наборы. Ваше приложение модульное? Как часто действительно нужно запускать все тесты? Было бы приемлемо, если бы ваши разработчики запускали только модульные тесты, относящиеся к их собственному модулю, и у вас был массив тестов, запускаемых каждую ночь и / или на CI?

Существуют ли какие-либо конкретные модульные тесты, которые очень сложны (я знаю , Здесь я скатываюсь к функциональному и интеграционному тестированию, но строка иногда нечеткая), но можно ли запустить любой из них на уровне работоспособности во время разработки, а затем полностью запустить на CI?

Править : Ради удовольствия, я кратко опишу процедуры тестирования в одном из моих предыдущих проектов

Во-первых, рост тестовой системы был органичным, Это означает, что изначально он не планировался, а модифицировался и изменялся по мере роста. Следовательно, он не был идеальным, и были некоторые соглашения об именах, которые со временем стали апокрифическими.

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

Автоматическое тестирование - это чокнутый тупик.

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

Автоматическое тестирование - это чокнутый тупик.

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

Автоматическое тестирование - это чокнутый тупик.

все модульные тесты и все регрессионные тесты.
  • Сложные наборы тестов (по количеству часов) запускались днем ​​и ночью удаленно, а результаты собирались на следующее утро.
  • Автоматическое тестирование - это чокнутый тупик.

    все модульные тесты и все регрессионные тесты.
  • Сложные наборы тестов (по количеству часов) запускались днем ​​и ночью удаленно, а результаты собирались на следующее утро.
  • Автоматическое тестирование - это чокнутый тупик.

    10
    ответ дан 27 November 2019 в 20:13
    поделиться

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

    • использовать лучшее оборудование (извините )
    • упростите логику тестирования

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

    2
    ответ дан 27 November 2019 в 20:13
    поделиться

    Некоторые идеи:

    • Используйте фиктивный фреймворк, чтобы избежать попадания в базы данных (или выполнения вызовов веб-служб и т. Д.).
    • Если вы делаете такую ​​же или похожую настройку для лотов отдельных тестов, попробуйте сделать это в настройках тестовой среды (то есть что-то, что выполняется один раз для каждого устройства, а не один раз за тест).
    • Я считаю, что некоторые тестовые среды позволяют запускать тесты параллельно
    14
    ответ дан 27 November 2019 в 20:13
    поделиться

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

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

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

    Еще одна область, в которой вы могли бы в конечном итоге найти проблемы с производительностью, - это настраиваемые «базовые» классы тестовых примеров. Это, как правило, вещи, которые добавляют много удобства, но может быть трудно помнить, что ваше поведение, добавляющее удобство, потенциально будет амортизировано более 10 тысяч тестов в большом проекте, независимо от того, требуется ли каждому тесту удобное поведение или нет.

    1
    ответ дан 27 November 2019 в 20:13
    поделиться

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

    Добавочная сборка запускает более короткие тесты примерно за 7 минут, тогда как Полная сборка запускает все тесты дольше, чем за 40 минут.

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

    Примечание. Один сервер непрерывной интеграции может иметь любое количество агентов, и если вы не можете позволить себе более одного сервера, вы можете использовать ПК в качестве агентов сборки. (У вас должно быть не менее 30 штук)

    1
    ответ дан 27 November 2019 в 20:13
    поделиться

    Вот подход, который я бы выбрал.

    1. Просмотрите свои тестовые примеры, найдите любые повторяющиеся тесты. Имея 3000 тестов, вы, скорее всего, в два или в пять раз покрываете детали, которые не должны быть обязательными.
    2. Выбери свои «канарейки». Это тесты, которые вы хотите запускать всегда, те, которые унюхают опасность в других частях. Скорее всего, это тестовые примеры более высокого уровня, которые тестируют общедоступные интерфейсы API, используемые между компонентами. Если один из них не работает, вы можете запустить полный набор тестов для компонента.
    3. Начните переход на такую ​​платформу, как TestNG , и начните классифицировать свои тестовые примеры, затем запустите только классификацию того, над чем вы работаете, с помощью полных ночных тестов.
    1
    ответ дан 27 November 2019 в 20:13
    поделиться

    Самый эффективный способ ускорить большой набор тестов - запускать его постепенно, чтобы повторно выполнялись только тесты, код касания которых изменился с момента последнего запуска теста. В конце концов, самыми быстрыми тестами всегда будут те, которые не выполняются. 8 ^)

    Самое сложное - заставить это работать. В настоящее время я работаю над инкрементным тестированием для JUnit 4, которое является частью инструмента «JMockit Coverage» в наборе инструментов тестирования разработчика JMockit . Он еще незрелый, но я считаю, что он будет работать хорошо.

    0
    ответ дан 27 November 2019 в 20:13
    поделиться

    DB access and network latency might be an area to examine. If you're performing a lot of database access in your integration tests, you may want to explore using an in-memory database like HSQL, H2 or Derby instead of a "real" database like Oracle. If you're using Hibernate, you will also have to change settings in your Hibernate configs to use the dialect specific to that DB (eg, HSQLDialect instead of OracleDialect). Was on a project once where each full build would end up having to drop and recreate an entire Oracle schema and perform numerous db tests over the network and it would sometimes take up to 20 minutes, and then you find someone checked in and things were broken again. :(

    Ideally you'd want to have just one DB script that is usable for both databases, but you might end up having to sychronize two different DB creation scripts - one for production, one for the integration tests.

    DB in same JVM vs DB across the network - might make a difference.

    0
    ответ дан 27 November 2019 в 20:13
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: