Giter Club home page Giter Club logo

trools's Introduction

trools: A test framework for rules. Build Status

Authored and maintained by Daniel Akiva and Derek Abdine (derek abdine gmail dot com).

Why trools?

The primary goal is to build a framework that focuses on quickly bringing test cases online without having to mess with boilerplate code for configuring a rules environment. We want to be able to write tests that are portable between rules engines so that migrating from one engine to another without breaking rules can be done with confidence.

Alternatives

Some rules engines have been integrated with Spring. A similar approach to what trools provides can be exposed by working with Spring's support for JSR-94 and specific rule engine implementations. Trools was designed to be spring-agnostic.

Engine support

Extending trools to support other rules engines is a trivial task. Please submit a ticket if you'd like to see support for other JSR-94 rules engines. The currently supported engines are:

  • Drools
  • Jess

Quick start

Below are a couple examples to help you get started. Keep in mind that the test logic has not changed between the jess/drools examples -- only the test class configuration (by way of annotations) and the rule language has changed. This helps facilitate test-driven development for rules.

Dependencies

Trools depends on JUnit 4.1+ and the JSR-94 specification, as well as a plugin JSR-94 implementation (aka rules engine). As of October 17th 2013, trools is an official Sonatype OSS project and is synchronized with the Maven central repository. The maven dependency configuration would look like:

   <dependencies>
      <dependency>
         <groupId>com.rapid7.trools</groupId>
         <artifactId>trools-core</artifactId>
         <version>1.0</version>
         <scope>test</scope>
      </dependency>
   </dependencies>

Create your rules file:

(defclass Person org.rapid7.trools.jess.example.fact.Person static)

(defrule simple-test
   ?personFact <- (Person
      (name ?name &: (eq ?name "Bill")))
=>
   (retract ?personFact)
   (add (new String "hello world"))
)

Create a trools-powered stateless rule session test case:

@RunWith(JessRulesJUnit4ClassRunner.class)
@RuleContext(resourceURI = "org/rapid7/trools/jess/example/simple-test.clp")
public class StatelessExampleTest {
    @Test
    public void statelessExample() throws InvalidRuleSessionException,
            RemoteException {
        // when
        List results = m_ruleSession.executeRules(Arrays.asList(new Person().setName("Bill")));
    
        // then
        assertEquals("hello world", results.get(0));
    }

    @InjectRuleSession
    private StatelessRuleSession m_ruleSession;
}

OR create a trools-powered stateful rule session test case:

@RunWith(JessRulesJUnit4ClassRunner.class)
@RuleContext(resourceURI = "org/rapid7/trools/jess/example/simple-test.clp")
public class StatefulExampleTest {
    @Test
    public void statefulExample() throws InvalidRuleSessionException,
            RemoteException {
        // given
        m_ruleSession.addObject(new Person().setName("Bill"));
    
        // when
        m_ruleSession.executeRules();
    
        // then
        List results = m_ruleSession.getObjects(new ClassTypeObjectFilter(
            String.class));
        assertEquals("hello world", results.get(0));
    }

    @InjectRuleSession
    private StatefulRuleSession m_ruleSession;
}

Create your rules file:

package org.rapid7.trools.example; 
import org.rapid7.trools.example.Person;

rule "simple-test"
    when 
        p : Person ( name == "Bill" )  
    then 
        retract(p);
        insert(new String("hello world"));
end

Create a trools-powered stateless rule session test case:

@RunWith(DroolsJUnit4ClassRunner.class)
@RuleContext(resourceURI = "org/rapid7/trools/drools/example/simple-test.drl")
public class StatelessExampleTest {
    @Test
    public void statelessExample() throws InvalidRuleSessionException,
            RemoteException {
        // when
        List results = m_ruleSession.executeRules(Arrays.asList(new Person().setName("Bill")));
    
        // then
        assertEquals("hello world", results.get(0));
    }

    @InjectRuleSession
    private StatelessRuleSession m_ruleSession;
}

OR create a trools-powered stateful rule session test case:

@RunWith(DroolsJUnit4ClassRunner.class)
@RuleContext(resourceURI = "org/rapid7/trools/drools/example/simple-test.drl")
public class StatefulExampleTest {
    @Test
    public void statefulExample() throws InvalidRuleSessionException,
            RemoteException {
        // given
        m_ruleSession.addObject(new Person().setName("Bill"));
    
        // when
        m_ruleSession.executeRules();
    
        // then
        List results = m_ruleSession.getObjects(new ClassTypeObjectFilter(
            String.class));
        assertEquals("hello world", results.get(0));
    }

    @InjectRuleSession
    private StatefulRuleSession m_ruleSession;
}

That's it. Run the test cases and you should see results :) For more interesting test cases, try combining mockito mock objects with trools test cases by passing the mock objects to the StatefulRuleSession#addObject(Object) or StatelessRuleSession#executeRules(List) methods, which can then be used by your rules and verified in the unit test methods.

Contributing

We need support for other rules engines!

When making contributions, please use Java coding standards. If using Eclipse to develop changes, these standards are built in and can be turned on in the Eclipse project Java code style settings configuration page.

Licensing

This project is available under the MIT license.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.