Question

Quelle est la meilleure pratique Drools de test règles avec JUnit?

Jusqu'à présent, nous avons utilisé JUnit avec DBUnit aux règles de test. Nous avons eu des exemples de données qui a été mis à hsqldb. Nous avons eu quelques paquets de règles et d'ici la fin du projet, il est très difficile de faire une bonne entrée de test pour tester certaines règles et pas à d'autres de feu.

La question exacte est que comment puis-je limiter les tests dans JUnit à une ou plusieurs certaine règle (s) pour le test?

Était-ce utile?

La solution

Personnellement, j'utiliser des tests unitaires pour tester des règles isolées. Je ne pense pas qu'il y ait quelque chose de trop mal avec elle, aussi longtemps que vous ne tombez pas dans un faux sentiment de sécurité que votre base de connaissances fonctionne parce que les règles isolées travaillent. Test de l'ensemble de la base de connaissances est plus important.

Vous pouvez écrire les tests de séparation avec AgendaFilter et 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.

Code source: http : //blog.athico.com/2007/07/my-rules-dont-work-as-expected-what-can.html

Autres conseils

Je crée la bibliothèque simple qui aide à écrire des tests unitaires pour Drools. L'une des caractéristiques est exactement ce dont vous avez besoin: DECLARE fichiers DRL particuliers que vous souhaitez utiliser pour votre test unitaire:

@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());
    }
}

Pour plus de détails ont un regard sur le post de blog: http://maciejwalkowiak.pl/blog/2013/11/24/jboss-drools-unit-testing-with-junit-drools/

Ne tentez pas de règle de limite d'exécution à une seule règle pour un test. Contrairement aux classes OO, des règles simples ne sont pas indépendantes d'autres règles, donc il n'a pas de sens pour tester une règle dans l'isolement de la même manière que vous tester une seule classe à l'aide d'un test unitaire. En d'autres termes, pour tester une seule règle, le test qu'il a l'effet escompté en combinaison avec les autres règles.

Au lieu, exécuter des tests avec une petite quantité de données sur toutes vos règles, à savoir avec un nombre minimal de faits dans la session de la règle, et tester les résultats et peut-être qu'une règle a été congédié. Le résultat ne fait que très différent de ce que vous avez à l'esprit, car un ensemble minimal de données de test ne peut activer une ou deux règles.

En ce qui concerne les données d'échantillon, je préfère utiliser des données statiques et définir des données de test minimal pour chaque test. Il existe différentes façons de le faire, mais la création d'objets de programmation en Java fait peut-être assez bon.

Un test unitaire avec DBUnit ne fonctionne vraiment pas. Un test d'intégration avec DBUnit fait. Voici pourquoi: - Un test unitaire doit être rapide. - Une base de données DBUnit restauration est lente. Prend 30 secondes facilement. - Une application dans le monde réel a beaucoup de colonnes non nulles. Ainsi, les données, isolées pour une seule fonction, utilise encore facilement la moitié des tables de la base de données. - Un test unitaire doit être isolé. - Restauration de la base de données de DBUnit pour chaque test pour les garder isolé présente des inconvénients: --- Exécution de tous les tests prend des heures (d'autant plus que l'application se développe), afin que personne ne se exécute eux, ils cassent en permanence, de sorte qu'ils sont désactivés, donc il n'y a pas de test, de sorte que vous application est plein de bugs. --- Création d'une demi-base de données pour chaque test unitaire est beaucoup de travail de création, beaucoup de travaux d'entretien, peut facilement devenir invalide (en ce qui concerne la validation qui de schéma base de données ne prennent pas en charge, voir Hibernate Validator) et fait ussually une mauvaise emploi de représenter la réalité.

Au lieu de cela, écrire des tests d'intégration avec DbUnit: - Un DbUnit, le même pour tous les tests. Chargez une seule fois (même si vous exécutez 500 tests). - Enveloppez chaque test dans une transaction et rollback la base de données après chaque test. La plupart des méthodes utilisent la propagation de toute façon nécessaire. Situé à seulement la sale testdata (pour le réinitialiser dans le test suivant s'il y a un prochain test) que lorsque la propagation est REQUIRES_NEW. - Remplir cette base de données avec des cas d'angle. Ne pas ajouter les cas les plus communes que sont strictement nécessaires pour tester vos règles métier, donc Ussually seulement 2 cas communs (pour être en mesure de tester « un à plusieurs »). - Rédiger des tests à l'épreuve: - Ne pas tester le nombre de règles activées ou le nombre de faits insérés. - Au lieu de cela, tester si un certain fait inséré est présent dans le résultat. Filtrer le résultat sur un certain ensemble de propriétés pour X (différente de la valeur courante de cette propriété) et de tester le nombre de faits insérés avec ce jeu de propriétés à X.

Pourquoi ne pas choisir même approche que nous avons pour le code java avec les tests unitaires et d'intégration? Test unitaire est de prendre morceau minimum de code et tester tous les usecases possibles définissant la spécification. Avec l'intégration des tests votre objectif n'est pas tous les usecases possibles, mais l'intégration de plusieurs unités qui travaillent ensemble. Faites la même chose avec les règles. règles de sens Séparer les affaires et le but. Simplest « unité sous test » pourrait être un fichier avec un seul ou l'ensemble des règles de cohension haute et ce qui est nécessaire pour que cela fonctionne (le cas échéant), comme fichier de définition de dsl commune et table de décision. Pour le test d'intégration, vous pouvez prendre un sens ou sous-ensemble de toutes les règles du système.

Avec cette approche, vous aurez beaucoup isolées des tests unitaires qui ne seront pas touchés et ne sera pas besoin d'un soutien lorsque vous ajoutez de nouvelles règles parce que vous aurez isolé ensemble de règles d'affaires avec sous-ensemble de données d'entrée pour tester des scénarios d'affaires respectifs. Et vous aurez quelques tests d'intégration avec quantité limitée de données d'entrée commune à reproduire et tester des scénarios « communs ». Ajout de nouvelles règles pour test d'intégration, il faudra à la sortie de test de mise à jour et refléter la façon dont les nouvelles règles données communes d'incidence sur les flux.

JUnit qui vous donne la possibilité aux ressources de charge dans déclarative manière et les règles de assert effectivement déclenché. Il conservera les erreurs d'assertion interne et rapport des règles de déclenchement non-concordance que des conseils que vous sur ce qui a mal tourné à un coup d'oeil. abris Logging lumière sur les relations de cause à effet entre les événements. Fonctionne avec SpringRunner.class pour les tests d'intégration de printemps.

Exemple:

@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());
    }
}

Voir rules.drl
En savoir plus: https://github.com/droolsassert/droolsassert

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top