Рубрики
Без рубрики

Randoop: Автоматическая генерация модульных тестов для Java

Этот пост был первоначально опубликован 2017-12-25 в моем старом блоге. Я не хочу терять содержание,… Помеченный как java, тестирование.

Этот пост был первоначально опубликован 2017-12-25 в моем старом блоге. Я не хочу терять контент, поэтому перенес его сюда. Содержание может быть более или менее устаревшим.

Randoop – это автоматический генератор модульных тестов для Java (и .NET). Randoop написан на Java и доступен либо на его странице project или Страница GitHub . Он доступен по лицензии MIT. По состоянию на 2017-12-24 проект, похоже, вполне жив, хотя большинство коммитов создано одним разработчиком (но проект принимает случайные PR). Randoop, по-видимому, управляется исследовательской группой Вашингтонского университета, но общее качество структуры проекта, вспомогательной документации, системы сборки и других артефактов проекта отличное.

рэндольф/рэндуп

Автоматическая генерация тестов для Java

Основы

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

Однако из этого есть исключение – Randoop может определять, когда тестируемый класс не соответствует базовым контрактам Java ( Object.equals() и тому подобное) и несколько других вероятных ошибок, таких как NullPointerException , которые выдаются, когда никакие null значения не передаются в качестве параметров методу. В документации указано, что можно добавить дополнительные контракты для проверки.

Установка и использование

Я клонировал репозиторий Git и следовал руководству по сборке Randoop из исходного кода с использованием Gradle. Сборка продолжалась около пяти минут и привела к созданию JAR-файла. Я попытался выполнить Randoop в небольшой библиотеке, которую я разработал, работая над статическим анализом программ на C, smg .

петр-Мюллер/smg

Библиотека графов символьной памяти в Java

Я начал с создания тестов для простого SMG Region класса . Немного повозившись с параметрами, Randoop некоторое время работал, генерируя 9 файлов размером около 2 МБ каждый с 4286 тестами (всего около 18 МБ, что выглядит немного чрезмерно для класса длиной ~ 60 строк). Никаких тестов “выявления ошибок” создано не было, только регрессионные тесты. Я попытался выполнить тесты, и все они прошли успешно. Их общее время выполнения составило 0,105 секунды, и это хорошо. Я попытался внести изменения в тестируемый класс и повторно запустить тесты, и теперь в результате 2506 тестов завершились неудачей.

Впоследствии я попытался включить все общедоступные классы, и результаты были примерно одинаковыми – около ~ 4200 тестов, без выявления ошибок (но, тем не менее, Randoop может найти только основные нарушения контракта Java).

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

Когда я мог бы им воспользоваться?

Randoop кажется мне весьма полезным. Он достаточно зрелый, хорошо документированный и довольно простой в использовании. Я также не столкнулся с какими-либо проблемами с инструментом. Его режим обнаружения ошибок может быть запущен как часть CI, являясь в основном простым фаззером для Java-контрактов (но я думаю, что существующие статические анализаторы могли бы выполнять ту же работу).

Полезность сгенерированных тестов несколько более сомнительна. Они могли бы служить регрессионными тестами, поскольку они могут только предупредить вас позже, когда вы, возможно, ошибочно, измените наблюдаемое поведение. Хорошо то, что Randoop действительно может создавать тесты, которые вам, возможно, понадобятся, но которые вы не писали. Вы могли бы сгенерировать набор тестов в определенный момент времени и продолжать его выполнять: таким образом, у вас был бы хороший набор регрессий, но вы не тестировали бы какой-либо код, добавленный после создания набора. Регенерация пакета после каждого изменения кажется слишком дорогостоящей, но имеет некоторые преимущества (конечно, только в том случае, если исходный пакет был запущен и передан первым). Возможно, там можно было бы использовать какую-нибудь стратегию отбрасывания нескольких старых и создания нескольких новых (я предполагаю, что эти стратегии, вероятно, обсуждаются где-то в соответствующих научных статьях, таких как статья авторов Scaling Up Automated Test Generation ASE’2011.

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

Оригинал: “https://dev.to/czafri/randoop-automatic-unit-test-generation-for-java-1353”