Test Rules
A test may contain two types of rules: eligibility rules and allocation rules.
Rule Format
All rules must be written in Unified Expression Language, and must return a boolean value.
Test rules may be set to null
or literal values. Test rules that are set to null
, an empty rule "${}"
, "${true}"
, or "${TRUE}"
will evaluate to true
.
Test rules that are set to "${false}"
or "${FALSE}"
will evaluate to false
.
Variables
Test rules can use any variables in the specification’s providedContext, test constants, or special constants.
Special constants set in a test definition can modify a test rule in the test-matrix. For example, if __COUNTRIES
is set in specialConstants
, the test-matrix will add proctor:contains(__COUNTRIES, country)
to the rule for that test.
The following two JSON files show the change made from the test definition to the test-matrix.
Example Test Definition:
{ | |
"testType" : "USER", | |
"description" : "Example basic rule format", | |
"version" : 0, | |
"specialConstants" : { | |
"__COUNTRIES" : ["AR", "AU", "BR", "CA", "CL", "CO", "NZ", "PE", "PT", "US", "VE", "ZA"] | |
}, | |
"rule" : "${lang == 'en' && country =='US'}", | |
"salt" : "asampletst", | |
"buckets" : [ { | |
"name" : "inactive", | |
"value" : -1, | |
"description" : "Inactive" | |
}, { | |
"name" : "altcolor1", | |
"value" : 0, | |
"description" : "Background color 1" | |
}], | |
"allocations" : [ { | |
"rule" : null, | |
"ranges" : [ { | |
"length" : 0.5, | |
"bucketValue" : -1 | |
}, { | |
"length" : 0.50, | |
"bucketValue" : 0 | |
} ] | |
} ] | |
} |
Example Test Matrix With Modified Rule:
{ | |
"tests": { | |
"asampletst" : { | |
"testType" : "USER", | |
"description" : "Example basic rule format", | |
"version" : 0, | |
"constants" : { | |
"__COUNTRIES" : ["AR", "AU", "BR", "CA", "CL", "CO", "NZ", "PE", "PT", "US", "VE", "ZA"] | |
}, | |
"rule" : "${proctor:contains(__COUNTRIES, country) && ${lang == 'en' && country =='US'}", | |
"salt" : "asampletst", | |
"buckets" : [ { | |
"name" : "inactive", | |
"value" : -1, | |
"description" : "Inactive" | |
}, { | |
"name" : "altcolor1", | |
"value" : 0, | |
"description" : "Background color 1" | |
}], | |
"allocations" : [ { | |
"rule" : null, | |
"ranges" : [ { | |
"length" : 0.5, | |
"bucketValue" : -1 | |
}, { | |
"length" : 0.50, | |
"bucketValue" : 0 | |
} ] | |
} ] | |
} | |
} | |
} |
Rules Using Variables
The following example shows a rule that indicates a test should only be applied when the language is English, the country is US, and the test constant variable id
is greater than 1000.
{ | |
"testType" : "USER", | |
"description" : "Example basic rule format", | |
"version" : 0, | |
"constants" : { | |
"id" : 456 | |
}, | |
"rule" : "${lang == 'en' && country =='US' && id > 1000}", | |
"salt" : "asampletst", | |
"buckets" : [ { | |
"name" : "inactive", | |
"value" : -1, | |
"description" : "Inactive" | |
}, { | |
"name" : "altcolor1", | |
"value" : 0, | |
"description" : "Background color 1" | |
}], | |
"allocations" : [ { | |
"rule" : null, | |
"ranges" : [ { | |
"length" : 0.5, | |
"bucketValue" : -1 | |
}, { | |
"length" : 0.50, | |
"bucketValue" : 0 | |
} ] | |
} ] | |
} |
Namespace Function Libraries
Test rules have two namespace function libraries available to them by default:
Namespace | Implementation Class | Notes |
---|---|---|
fn | org.apache.taglibs.standard.functions.Functions |
JSP EL functions from the standard tag library |
proctor | com.indeed.proctor.common.ProctorRuleFunctions |
Proctor-specific functions for rules |
Rules Containing Namespace Functions
Test rules may take advantage of the two namespace function libraries available to them. In the following example, the eligibility rule uses the “contains” function from the “proctor” namespace.
{ | |
"constants" : { | |
"EXAMPLE_COUNTRIES" : [ "AU", "BE", "BR", "CA", "CH", "DE", "ES", "FR", "GB", "IE", "IN", "IT" ] | |
}, | |
"rule" : "${proctor:contains(EXAMPLE_COUNTRIES, country)}" | |
} |
Extending Default Namespace Function Libraries
To add to the default namespace function libraries, Proctor provides users with a static function that generates a LibraryFunctionMapperBuilder
that contains the default fn
and proctor
namespaces. Add the namespace and class to this builder and build.
Building will return a FunctionMapper containing the default namespaces as well as any that were added, as shown in the following code example.
final JsonProctorLoaderFactory factory = new JsonProctorLoaderFactory();
// Loads the specification from the classpath resource
factory.setSpecificationResource("classpath:/org/your/company/app/ExampleGroups.json");
// Loads the test matrix from a file
factory.setFilePath("/var/local/proctor/test-matrix.json");
// A custom FunctionMapper without the default namespaces fn and proctor
final FunctionMapper myFunctionMapper = new LibraryFunctionMapperBuilder()
.add("namespace1", Class1.class)
.add("namespace2", Class2.class)
.build();
// A custom FunctionMapper WITH the default namespaces fn and proctor
final FunctionMapper extendedFunctionMapper = RuleEvaluator.defaultFunctionMapperBuilder()
.add("namespace1", Class1.class)
.add("Namespace2", Class2.class)
.build();
factory.setFunctionMapper(myFunctionMapper); // or pass extendedFunctionMapper
final AbstractJsonProctorLoader loader = factory.getLoader();