В настоящее время я добавляю новую функцию в LibFX , для которой я создаю некоторые пользовательские коллекции, схожие с таковыми из Java Collections Framework . Я отправился на поиски тестов, которые мог бы выполнить против них, и был рад узнать, что Google Guava содержит именно то, что мне нужно: массивный набор тестов, который проверяет каждый уголок моей реализации для всех интерфейсов сбора из JDK и Guava.
Давайте кратко рассмотрим это.
обзор
В этом посте сначала будет показано, как настроить проект, а затем посмотреть, как начать работу с реальными тестами.
Я не создал специальных примеров, но вы можете видеть, как я использовал это в LibFX .
Содержание [ скрыть ]
Настроить
Чтобы это работало, нам нужен JUnit, Guava-Testlib и небольшой шаблонный код.
Получить JUnit
Если вы еще не используете JUnit в своем проекте, загрузите его здесь . Если вы используете Maven или Gradle:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
testCompile 'junit:junit:4.12'
Получить гуаву
Что нам действительно нужно, так это не сама Гуава, а Гуава-Тестлиб . Вы можете скачать его из центрального репозитория , который также содержит информацию о зависимостях для разных менеджеров.
Для вашего удобства:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava-testlib</artifactId> <version>18.0</version> <scope>test</scope> </dependency>
testCompile 'com.google.guava:guava-testlib:18.0'
Напишите немного
Предположим, вы хотите написать MySet и соответствующий MySetTest .
Делая это JUnit-3.8.x-way, создайте метод publicstaticTest suite (); , JUnit ищет этот метод и использует его для определения всех тестов, которые он будет выполнять для этого класса. Внутри этого метода создайте TestSuite и добавьте тесты, которые мы собираемся записать ниже:
public class MySetTest { public static Test suite() { return new MySetTest().allTests(); } public Test allTests() { TestSuite suite = new TestSuite("package.name.of.MySetTest"); suite.addTest(testForOneToWayUseMySet()); suite.addTest(testForAnotherWayToUseMySet()); return suite; } }
(Я не пытался сделать это с помощью аннотаций JUnit 4. Если вы это сделали, пингуйте меня, и я включу это здесь.)
Имея этот шаблон, вы можете запускать этот класс с JUnit, например, изнутри вашей IDE или с вашего CI-сервера.
Проверьте свои реализации
Теперь, когда это сделано, мы можем начать создавать тесты для наших реализаций. Или, точнее, скажите Гуаве, как это сделать для нас. Это процесс, состоящий из двух частей: один создает генератор для элементов коллекции и тестируемый модуль, другой использует один из сборщиков тестовых наборов Guava для создания полного набора тестов, адаптированных к реализации.
Мы продолжим тестировать реализацию Set . Ниже мы увидим, для каких других интерфейсов доступны тестовые наборы.
Генератор для элементов и тестируемого устройства
Разработчик набора тестов требует, чтобы вы дали ему возможность создавать образцы элементов в коллекции и создавать экземпляры вашей коллекции. Для этого вам нужно реализовать TestSetGenerator <E> (где E — тип элементов).
Это прямо с порядком (List <E>), который является единственным методом, который может потребовать некоторого размышления. Обратите внимание, что в отличие от документации, текущая версия testlib (18.0) вызывает этот метод, даже если CollectionFeature.KNOWN_ORDER не сообщается (подробности о функциях см. Ниже). В моем случае достаточно вернуть порядок вставки.
Test Suite Builder
Теперь, когда происходит настоящее волшебство. Вы берете свой генератор сверху, передаете его правильному сборщику тестов, указываете, какие функции имеет ваша коллекция, и он создаст индивидуальный и всеобъемлющий набор тестов:
public Test testForOneToWayUseMySet() { return SetTestSuiteBuilder .using(new MySetGenerator()) .named("one way to use MySet") .withFeatures( CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES, CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, CollectionFeature.SUPPORTS_ADD, CollectionFeature.SUPPORTS_ITERATOR_REMOVE, CollectionFeature.SUPPORTS_REMOVE, ) .createTestSuite(); }
Характеристики
Важно указать правильные функции. Взгляните на два перечисления CollectionSize и CollectionFeatures, чтобы увидеть, какие существуют возможности для описания поведения вашей коллекции.
Обратите внимание, что созданные тесты проверяют возможности в обоих направлениях! Например, если не указывать ALLOWS_NULL_VALUES, сборщик сгенерирует тесты, которые проверяют, что добавление null в коллекцию приводит к исключению NullPointerException .
Подавляющие тесты
Вызывая подавление на компоновщике, вы можете указать методы тестирования, которые не будут выполняться. Похоже, что существует последнее средство, когда функции не позволяют точно определить поведение. Я не использовал это.
Установка и удаление
Если вам нужно выполнить код до или после каждого теста, вы можете передать его как Runnable для withSetUp или withTearDown , соответственно (оба могут быть вызваны в компоновщике).
Доступные тесты
Конечно, вы можете создавать тестовые наборы и для других интерфейсов. Первый взгляд дает следующие возможности:
Коллекции Java:
- Коллекция
- Итератор
- Список
- карта
- NavigableMap
- NavigableSet
- Очередь
- Поставил
- SortedMap
- SortedSet
Коллекции Гуавы:
- BiMap
- ListMultimap
- Multimap
- Multiset
- SetMultimap
- SortedMultiset
- SortedSetMultimap
Поиск типа для * TestSuiteBuilder (обратите внимание на подстановочный знак) приводит к появлению некоторых других сборщиков. Я не исследовал их, но возможно, что они могут быть использованы для создания тестов для других случаев.
Чтобы использовать их, просто внедрите соответствующий генератор Test … и передайте его соответствующему … TestSuiteBuilder .
отражение
Мы увидели, как тестировать реализации коллекций с помощью Testlib из Guava: как включить его и JUnit в наш проект, какой шаблон нам нужен для его запуска, и обзор генератора и генератора тестовых наборов. В последнем случае происходит вся магия, поскольку она создает всесторонние тесты с учетом нашего описания нашей реализации и ее возможностей.