Корень нашей проблемы - это Singletons. Но Singletons трудно сломать, и тем временем у нас есть много модульных тестов, которые используют Singletons, не пытаясь полностью очистить их в методе tearDown(). Я считаю, что хороший способ обнаружить такие тесты - это поиск утечек памяти. Если память, используемая после tearDown() и System.gc(), больше, чем при запуске теста, либо тест просочился, либо больше классов были загружены загрузчиком классов. Есть ли способ автоматически обнаружить такую проблему?Автоматический способ поиска тестов JUnit, которые утечки памяти
ответ
Просто мысль: если у вас есть два пустых теста, запускаемых сразу после друг друга, у второго не должно быть разной памяти, используемой после teardown(). Если это так, у вас (возможно) есть утечка где-то в вашей системе setup()/teardown().
Я не думаю, что это хороший подход. System.gc()
не гарантирует полную очистку любых неиспользуемых объектов, как вы думаете.
Если ваша корневая проблема заключается в том, что у вас есть модульные тесты, которые в конечном итоге используют глобальные данные (синглтоны), не исправляя их должным образом, вы должны атаковать корневую проблему: эти модульные тесты. Не должно быть слишком сложно найти все тесты, которые не используют tearDown()
, или найти все тесты, в которых используется конкретный синглтон.
Нетрудно найти их. Их десятки тысяч. Большинство из них вызывает Singleton.getInstance(). Reset() или что-то впоследствии смягчает проблему. Вероятно, есть несколько тестов, которых нет, и их очень сложно найти. –
Время, чтобы избавиться от всех синглтонов тогда :) –
Я согласен в теории, но потребовались годы. Это десятимиллиметровая база кода, и очень сложно реорганизовать синглтоны в небольших кусках. –
Не могли бы вы ввести подкласс между TestCase и вашими отдельными классами тестов, которые сделали очистку? Тогда подклассы будут отвечать только за вызов super.teardown() - и только те, у кого был собственный разрыв().
Если ваш Singleton's предназначен только для инициализации один раз, у вас может быть код, который проверяет наличие повторной инициализации и регистрирует текущий стек, когда он обнаруживает это. Затем, если вы проверите стек, вы увидите, какой тест получил мяч, и вы можете проверить журналы JUnit, чтобы увидеть, что тест прошел прямо до этого.
С точки зрения решения этой проблемы более подробно, вместо того, чтобы ее обнаружить, я бы порекомендовал вам инициализатор синглтона, который помнит, что он инициализировал, и имеет один метод слежения, который срывает все, что он инициализировал. Таким образом, тесты могут быть сделаны только для инициализации через этот класс, и только нужно сделать одно дело в режиме срыва.
Я также думаю, что предложение Карла Манастера является хорошим, но если вы используете JUnit4, тогда у вас может быть метод срыва, который запускается в суперклассе, не забудьте вспомнить супер. Если вы не используете графический интерфейс JUnit3, JUnit4 должен быть заменой. Единственное, что нужно использовать в своих новых функциях, которые вы должны перенести на весь тест, вы не можете жить в одном классе. Таким образом, тесты, которые взаимодействуют с этими синглонами, должны были быть перенесены на один класс тестов за раз.
Я полностью согласен с другими плакатами, что мониторинг использования памяти не является жизнеспособным способом отслеживания этого - System.gc() не будет вести себя так, как вы ожидаете, или с достаточной точностью для достижения своей цели.
Вам понадобится инструмент, который позволит вам просмотреть ссылочный граф и показать стеки вызовов вызовов.
Я использовал Optimizeit от Borland и JProfiler из EJ-технологий, как с успехом (быстрый Google показывает, что OptimizeIt может теперь быть мертвым.)
Там также Possiblity использования JVMTI бросить вместе лучше монитор для этой конкретной проблемы.
Edit: Wierd, но, как я просматривал этот ответ, я получил телефонный звонок от Embarcadero, который, по-видимому купленного Optimizeit, сделал некоторые обновления и теперь маркетинг под названием J Optimizer.
Вы можете использовать Eclipse Memory Analyzer для автоматизации анализа свалок кучи, полученных после каждого теста или, вероятно, лучше после всех испытаний. MAT может автоматически обнаруживать утечки памяти.
Разве сумма кучи не увеличивалась бы где-то между тестовыми прогонами - так как junit теперь должен записывать дополнительный TestResult? –
До тех пор, пока не запускается сбор мусора, память, используемая при первом запуске теста, не восстанавливается. – Mnementh