The new API is a single method: facet_data(). This method must return a hashref where each key is
specific to a facet type, and the value is either a facet hashref, or an array of hashrefs. Some facets
"MUST" be lone hashrefs, others "MUST" be hashrefs inside an arrayref.
The standard facet types are as follows:
assert => {details => $name, pass => $bool, no_debug => $bool, number => $maybe_int}
Documented in Test2::EventFacet::Assert. An event may only have one.
The 'details' key is the name of the assertion.
The 'pass' key denotes a passing or failing assertion.
The 'no_debug' key tells any harness or formatter that diagnostics should not be added automatically
to a failing assertion (used when there are custom diagnostics instead).
The 'number' key is for harness use, never set it yourself.
about => {details => $string, no_display => $bool, package => $pkg}
Documented in Test2::EventFacet::About. An event may only have one.
'details' is a human readable string describing the overall event.
'no_display' means that a formatter/harness should hide the event.
'package' is the package of the event the facet describes (IE: Test2::Event::Ok)
amnesty => [{details => $string, tag => $short_string, inherited => $bool}]
Documented in Test2::EventFacet::Amnesty. An event may have multiple.
This event is how things like 'todo' are implemented. Amnesty prevents a failing assertion from
causing a global test failure.
'details' is a human readable description of why the failure is being granted amnesty (IE The 'todo'
reason)
'tag' is a short human readable string, or category for the amnesty. This is typically 'TODO' or
'SKIP'.
'inherited' is true if the amnesty was applied in a parent context (true if this test is run in a
subtest that is marked todo).
control => {details => $string, global => $bool, terminate => $maybe_int, halt => $bool, has_callback =>
$bool, encoding => $enc}
Documented in Test2::EventFacet::Control. An event may have one.
This facet is used to apply extra behavior when the event is processed.
'details' is a human readable explanation for the behavior.
'global' true if this event should be forwarded to, and processed by, all hubs everywhere. (bail-out
uses this)
'terminate' this should either be undef, or an integer. When defined this will cause the test to exit
with the specific exit code.
'halt' is used to signal any harness that no further test files should be run (bail-out uses this).
'has_callback' is set to true if the event has a callback sub defined.
'encoding' used to tell the formatter what encoding to use.
errors => [{details => $string, tag => $short_string, fail => $bool}]
Documented in Test2::EventFacet::Error. An event may have multiple.
'details' is a human readable explanation of the error.
'tag' is a short human readable category for the error.
'fail' is true if the error should cause test failure. If this is false the error is simply
informative, but not fatal.
info => [{details => $string, tag => $short_string, debug => $bool, important => $bool}]
Documented in Test2::EventFacet::Info. An event may have multiple.
This is how diag and note are implemented.
'details' human readable message.
'tag' short category for the message, such as 'diag' or 'note'.
'debug' is true if the message is diagnostics in nature, this is the main difference between a note
and a diag.
'important' is true if the message is not diagnostics, but is important to have it shown anyway. This
is primarily used to communicate with a harness.
parent => {details => $string, hid => $hid, children => [...], buffered => 1}
Documented in Test2::EventFacet::Parent. An event may have one.
This is used by subtests.
'details' human readable name of the subtest.
'hid' subtest hub id.
'children' an arrayref containing facet_data instances from all child events.
'buffered' true if it was a buffered subtest.
plan => {details => $string, count => $int, skip => $bool, none => $bool}
Documented in Test2::EventFacet::Plan. An event may have one.
'details' is a human readable string describing the plan (for instance, why a test is skipped)
'count' is the number of expected assertions (0 for skip)
'skip' is true if the plan is to skip the test.
'none' used for Test::More's 'no_plan' plan.
trace => {details => $string, frame => [$pkg, $file, $line, $sub], pid => $int, tid => $int, cid => $cid,
hid => $hid, nested => $int, buffered => $bool}
Documented in Test2::EventFacet::Trace. An event may have one.
This is how debugging information is tracked. This is taken from the context object at event
creation.
'details' human readable debug message (otherwise generated from frame)
'frame' first 4 fields returned by caller: "[$package, $file, $line, $subname]".
'pid' the process id in which the event was created.
'tid' the thread is in which the event was created.
'cid' the id of the context used to create the event.
'hid' the id of the hub to which the event was sent.
'nest' subtest nesting depth of the event.
'buffered' is true if the event was generated inside a buffered subtest.
Note that ALL facet types have a 'details' key that may have a string. This string should always be human
readable, and should be an explanation for the facet. For an assertion this is the test name. For a plan
this is the reason for the plan (such as skip reason). For info it is the human readable diagnostics
message.
CUSTOMFACETS
You can write custom facet types as well, simply add a new key to the hash and populated it. The general
rule is that any code looking at the facets should ignore any it does not understand.
Optionally you can also create a package to document your custom facet. The package should be proper
object, and may have additional methods to help work with your facet.
package Test2::EventFacet::MyFacet;
use parent 'Test2::EventFacet';
sub facet_key { 'myfacet' }
sub is_list { 0 }
1;
Your facet package should always be under the Test2::EventFacet:: namespace if you want any tools to
automatically find it. The last part of the namespace should be the non-plural name of your facet with
only the first word capitalized.
$string = $facet_class->facet_key
The key for your facet should be the same as the last section of the namespace, but all lowercase.
You may append 's' to the key if your facet is a list type.
$bool = $facet_class->is_list
True if an event should put these facets in a list:
{ myfacet => [{}, {}] }
False if an event may only have one of this type of facet at a time:
{ myfacet => {} }
EXAMPLES
The assert facet is not a list type, so its implementation would look like this:
package Test2::EventFacet::Assert;
sub facet_key { 'assert' }
sub is_list { 0 }
The amnesty facet is a list type, but amnesty does not need 's' appended to make it plural:
package Test2::EventFacet::Amnesty;
sub facet_key { 'amnesty' }
sub is_list { 1 }
The error facet is a list type, and appending 's' makes error plural as errors. This means the package
name is '::Error', but the key is 'errors'.
package Test2::EventFacet::Error;
sub facet_key { 'errors' }
sub is_list { 1 }
Note2: In practice most tools completely ignore the facet packages, and work with the facet data directly
in its raw structure. This is by design and recommended. The facet data is intended to be serialized
frequently and passed around. When facets are concerned, data is important, classes and methods are not.