Проверка Drools с помощью junit

Какова наилучшая практика для проверки правил слюни с помощью junit?

До сих пор мы использовали junit с dbunit для проверки правил. У нас были образцы данных, которые были помещены в hsqldb. У нас было несколько пакетов правил, и к концу проекта очень сложно сделать хороший тестовый ввод, чтобы протестировать определенные правила и не запускать другие.

Поэтому точный вопрос заключается в том, как я могу ограничить тесты в junit одним или несколькими определенными правилами для тестирования?

Ответ 1

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

Вы можете написать тесты изоляции AgendaFilter и StatelessSession

StatelessSession session = ruleBase.newStatelessSesssion();

session.setAgendaFilter( new RuleNameMatches("<regexp to your rule name here>") );

List data = new ArrayList();
... // create your test data here (probably built from some external file)

StatelessSessionResult result == session.executeWithResults( data );

// check your results here.

Источник кода: http://blog.athico.com/2007/07/my-rules-dont-work-as-expected-what-can.html

Ответ 2

Я создал простую библиотеку, которая помогает писать модульные тесты для Drools. Одной из функций является именно то, что вам нужно: объявите конкретные файлы drl, которые вы хотите использовать для модульного теста:

@RunWith(DroolsJUnitRunner.class)
@DroolsFiles(value = "helloworld.drl", location = "/drl/")
public class AppTest {

    @DroolsSession
    StatefulSession session;

    @Test
    public void should_set_discount() {
        Purchase purchase = new Purchase(new Customer(17));

        session.insert(purchase);
        session.fireAllRules();

        assertTrue(purchase.getTicket().hasDiscount());
    }
}

Более подробную информацию можно найти в блоге: http://maciejwalkowiak.pl/blog/2013/11/24/jboss-drools-unit-testing-with-junit-drools/

Ответ 3

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

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

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

Ответ 4

A unit test с DBUnit действительно не работает. Тест интеграции с DBUnit. Вот почему: - A unit test должен быть быстрым. - Восстановление базы данных DBUnit происходит медленно. Снимает 30 секунд. - В реальном приложении много ненулевых столбцов. Таким образом, данные, выделенные для одной функции, все еще легко используют половину таблиц базы данных. - A unit test следует изолировать. - Восстановление базы данных dbunit для каждого теста, чтобы изолировать их, имеет недостатки: --- Запуск всех тестов занимает несколько часов (особенно по мере того, как приложение растет), поэтому никто не запускает их, поэтому они постоянно ломаются, поэтому они отключены, поэтому нет тестирования, поэтому приложение заполнено ошибками. --- Создание половины базы данных для каждого unit test - это много работы по созданию, большая работа по техническому обслуживанию, может легко стать недействительной (в отношении проверки, какая схема базы данных не поддерживается, см. Hibernate Validator) и обычно выполняет плохая работа по представлению реальности.

Вместо этого запишите интеграционные тесты с помощью DBunit: - Один DBunit, тот же для всех тестов. Загрузите его только один раз (даже если вы проведете 500 тестов). - Оберните каждый тест в транзакции и откатите базу данных после каждого теста. Большинство методов используют распространение в любом случае. Установите только пробные данные (до reset в следующем тесте, если есть следующий тест), только когда распространение требуется require_new. - Заполните эту базу с помощью угловых шкафов. Не добавляйте более распространенные случаи, чем это необходимо для проверки ваших бизнес-правил, поэтому обычно используются только 2 распространенных случая (чтобы проверить "один на многие" ). - Написать будущие тесты: - Не проверяйте количество активированных правил или количество вставленных фактов. - Вместо этого проверьте, присутствует ли в результате определенный вставленный факт. Отфильтруйте результат на определенном свойстве, установленном в X (отличном от общего значения этого свойства) и проверьте количество вставленных фактов с этим свойством, установленным в X.

Ответ 5

Почему бы не выбрать такой же подход, как у нас для Java-кода с модульными и интеграционными тестами? Модульное тестирование подразумевает получение минимального фрагмента кода и тестирование всех возможных вариантов использования, определяющих спецификацию. С интеграционными тестами ваша цель - не все возможные варианты использования, а интеграция нескольких устройств, которые работают вместе. Сделайте то же самое с правилами. Разделите правила по бизнес-значению и цели. Простейшим "тестируемым модулем" может быть файл с одним или набором правил с высокой степенью когезии и тем, что требуется для его работы (если есть), например общий файл определения dsl и таблица решений. Для тестирования интеграции вы можете взять осмысленное подмножество или все правила системы.

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

Рассмотрим тестовое правило JUnit, которое дает вам возможность загружать ресурсы декларативным способом и утверждать, что правила фактически сработали. Он сохранит ошибки внутреннего утверждения и сообщит о любых правилах, вызывающих несоответствие, которое намекает вам на то, что пошло не так. Регистрация проливает свет на причинно-следственные связи между событиями. Работает с SpringRunner.class для испытаний пружинной интеграции.

Пример:

@DroolsSession(resources = {
        "classpath*:/org/droolsassert/rules.drl",
        "classpath*:/com/company/project/*/{regex:.*.(drl|dsl|xlsx|gdst)}",
        "classpath*:/com/company/project/*/ruleUnderTest.rdslr" },
        ignoreRules = { "before", "after" })
public class DroolsAssertTest {

    @Rule
    public DroolsAssert drools = new DroolsAssert();

    @Test
    @AssertRules("atomic int rule")
    public void testInt() {
        drools.insertAndFire(new AtomicInteger());
        assertEquals(1, drools.getObject(AtomicInteger.class).get());
    }
}

Смотрите rules.drl
. Больше: https://github.com/droolsassert/droolsassert