Understanding Test Expressions

From ABL
Revision as of 09:40, 19 September 2006 by Kane (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

A test expression is a list of

  1. tests over working memory (WME tests), and/or
  2. arbitrary Java boolean expressions (Java tests).

A test expression either fails or succeeds; in the latter case, the test may also bind certain values examined during the test to variables which are then available for use in later parts of the code (see Scoping for a more precise description of test expressions and scoping). Test expressions are conjunctive; each test in the test expression must succeed for the entire expression to succeed.


Below is a list of things you can do with test expressions. We'll use ABL-Wargus as our example domain; the following code snippets are merely illustrative and may not actually reflect the current (or a previous!) ABL-Wargus implementation.


Testing for the presence of a WME

Suppose we were writing a behavior whose precondition needed to test if we had built any buildings at all:

sequential behavior TakeOverTheWorld() {
    precondition { (BuildingWME) }
    mental_act { System.out.println("I have a building."); }
}

This code snippet literally checks if there exists a BuildingWME in memory at all (presumably, if we had not built buildings yet, there would not exist WMEs for them).


Binding a WME

Instead, suppose we needed direct access to the WME:

sequential behavior TakeOverTheWorld() {
    precondition { w = (BuildingWME) }
    mental_act { System.out.println("I have a building: " + w); }
}
  • If multiple BuildingWMEs exist in working memory, one will be selected at random to be bound to w.
  • We did not need to declare w; it's type was inferred. Variables introduced (either by binding WMEs or their fields) in a test expression do not need to be declared.


Binding a WME field

Now suppose we only needed to know the type of such a building. We can bind fields of the WME as follows:

sequential behavior TakeOverTheWorld() {
    precondition { (BuildingWME type :: theType) } 
    mental_act { System.out.println("I have a building of type: " + theType); }
}
  • We are assuming BuildingWME has a field type. In general, a WME (which is just a Java class) is said to have a field foo if it contains a method getFoo().
  • The :: operator should be interpreted as assigning the value on the left into the name on the right.
  • Also, it is perfectly legal to bind to a local variable of the same name, i.e. type::type would have worked, too.


Logical tests on a WME field

sequential behavior TakeOverTheWorld() {
    precondition { (BuildingWME type == BARRACKS) }
    mental_act { System.out.println("I have a barracks."); }
}

Calling test functions inside a precondtion

sequential behavior TakeOverTheWorld() {
    precondition { (BuildingWME type==BARRACKS isIdle==true) }
    mental_act { System.out.println("I have an idle barracks."); }
}


Arbitrary logical tests

sequential behavior TakeOverTheWorld() {
    precondition { 
        (BuildingWME type::t health::h) 
        ((Utils.healthRatio(t, h) > 0.75) || (h > 100)) // arbitrary Java boolean expression
    }
    mental_act { System.out.println("I have a healthy building."); }
}


Debugging test expressions

Suppose the precondition was never getting met, eventhough you thought it should be. The problem might be that you have encoded the wrong number into the constant BARRACKS; you could do the following to see if the numbers actually match up.

sequential behavior TakeOverTheWorld() {
    precondition { 
        // (BuildingWME type == BARRACKS)
        (BuildingWME type :: type) 
        (BehavingEntity.getBehavingEntity().truePrintln("The building type == " + type 
                                                             + ", BARRACKS == " + BARRACKS)
        (type == BARRACKS)
    }
    mental_act { System.out.println("I have a barracks."); }
}

This is useful for testing out preconditions. You can put calls to objects in here (no behaviors) and use it to determine why your precondition isn't working as planned.