Skip to content

Commit

Permalink
External log integration in report (#987)
Browse files Browse the repository at this point in the history
* External log integration in report

* Make Customizer into biFunction and update readme

* Javadoc update for motivation
  • Loading branch information
vchaitanya authored Oct 30, 2024
1 parent e44dc9a commit f99e9d3
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ public enum State {
// no-op
};

private MotivationCustomizer motivationCustomizer = ( motivation, assrt ) -> motivation;

/**
* @param title The title of this test
* @param model The model to process
Expand Down Expand Up @@ -368,6 +370,20 @@ public T behaviour( Consumer<Assertion> t ) {
return self();
}

/**
* Configures the motivation customizer behavior. The `MotivationCustomizer`
* interface allows you to customize the motivation text in the report. This
* method sets the customizer that will be used to modify the motivation text
* based on the original motivation and the test results.
*
* @param customizer The custom `MotivationCustomizer` implementation.
* @return <code>this</code> for method chaining.
*/
public T motivation( MotivationCustomizer customizer ) {
motivationCustomizer = customizer;
return self();
}

/**
* @return The {@link Flow}s to process, in order
*/
Expand Down Expand Up @@ -547,6 +563,7 @@ private int processInteraction( Flow flow, Interaction ntr, List<Assertion> actu
reportUpdates.add( d -> logCapture.end( flow ).forEach( d.logs::add ) );
reportUpdates.add( d -> d.logs.add( error(
"Encountered error: " + LogEvent.stackTrace( e ) ) ) );
reportUpdates.add( d -> d.motivation = motivationCustomizer.apply( d.motivation, assrt ) );
report( w -> w.with( flow, reportUpdates.stream()
.reduce( d -> {
// no-op
Expand Down Expand Up @@ -612,6 +629,10 @@ private int processMessage( Flow flow, Assertion assertion,
// (which populates the report) before failing
parseFailures.add( e );
}
finally {
reportUpdates
.add( d -> d.motivation = motivationCustomizer.apply( d.motivation, assertion ) );
}
return 1;
}
return 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mastercard.test.flow.assrt;

import java.util.function.BiFunction;

/**
* Customizes the motivation text in the report.
*/
public interface MotivationCustomizer extends BiFunction<String, Assertion, String> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void fluency() {
assertSame( tf, tf.checkers() );
assertSame( tf, tf.logs( null ) );
assertSame( tf, tf.autonomous() );
assertSame( tf, tf.motivation( null ) );
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.mastercard.test.flow.assrt;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

import com.mastercard.test.flow.report.Reader;
import com.mastercard.test.flow.report.data.Entry;
import com.mastercard.test.flow.report.data.FlowData;
import com.mastercard.test.flow.report.data.Index;

/**
* Demonstrates the execution {@link MotivationCustomizer}
*/
class MotivationCustomizerTest {

/**
* Update motivation in the report even when flow is not processed due to some
* exception
*/
@Test
void motivationNoBehaviour() {
TestFlocessor tf = new TestFlocessor( "motivation without behaviour", TestModel.abc() )
.motivation( ( motivation, assertion ) -> motivation + "Common motivation" )
.reporting( Reporting.QUIETLY )
.system( AbstractFlocessor.State.LESS, TestModel.Actors.B );

tf.execute();

assertEquals( "abc [] error No test behaviour specified", tf.events() );

// This is also recorded to the report
Reader r = new Reader( tf.report() );
Index index = r.read();
Entry ie = index.entries.get( 0 );
FlowData fd = r.detail( ie );
assertEquals( "Common motivation", fd.motivation );
}

/**
* Motivation can be updated in the report after the flow is processed
*/
@Test
void motivation() {
TestFlocessor tf = new TestFlocessor( "motivation", TestModel.abc() )
.motivation( ( motivation, assertion ) -> {
String baseUrl = "https://www.google.com/search?q=";
String queryToken = new String( assertion.expected().request().content() ).substring( 0,
1 );
queryToken += new String( assertion.actual().response() ).substring( 0, 1 );
String logLink = baseUrl + queryToken;
return motivation + "\n\n[View Logs](" + logLink + ")";
} )
.behaviour( assrt -> {
assrt.actual().response( assrt.expected().response().content() );
} )
.reporting( Reporting.QUIETLY )
.system( AbstractFlocessor.State.LESS, TestModel.Actors.B );

tf.execute();

// This is also recorded to the report
Reader r = new Reader( tf.report() );
Index index = r.read();
Entry ie = index.entries.get( 0 );
FlowData fd = r.detail( ie );
assertEquals( "\n\n[View Logs](https://www.google.com/search?q=AB)", fd.motivation );
}

}
25 changes: 17 additions & 8 deletions doc/src/main/markdown/further.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The execution report includes tooling to aid in change review. If the reports ge

<!-- code_link_start -->

[AbstractFlocessor.reporting(Reporting,String...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L195-L204,195-204
[AbstractFlocessor.reporting(Reporting,String...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L197-L206,197-206
[Reporting]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/Reporting.java

<!-- code_link_end -->
Expand Down Expand Up @@ -80,8 +80,8 @@ Note that only the tag/index-based filtering can be used to avoid flow construct

<!-- code_link_start -->

[AbstractFlocessor.filtering(Consumer)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L316-L324,316-324
[AbstractFlocessor.exercising(Predicate,Consumer)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L329-L354,329-354
[AbstractFlocessor.filtering(Consumer)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L318-L326,318-326
[AbstractFlocessor.exercising(Predicate,Consumer)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L331-L356,331-356

<!-- code_link_end -->

Expand Down Expand Up @@ -125,10 +125,19 @@ Note that the assertion components will not make any assumptions about the forma
[LogCapture]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/LogCapture.java
[Tail]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/log/Tail.java
[Merge]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/log/Merge.java
[AbstractFlocessor.logs(LogCapture)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L284-L291,284-291
[AbstractFlocessor.logs(LogCapture)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L286-L293,286-293

<!-- code_link_end -->

## Motivation Customizer
The motivation text in the report can be enhanced with additional information such as providing links to external systems such as splunk, datadog, aws etc. by implementing the [`MotivationCustomizer`][MotivationCustomizer] interface when you build the `Flocessor` object via the [`motivation()`][AbstractFlocessor.motivation(MotivationCustomizer)] method.

<!-- code_link_start -->

[MotivationCustomizer]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/MotivationCustomizer.java
[AbstractFlocessor.motivation(MotivationCustomizer)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L373-L382,373-382

<!--code_link_end-->
## Interaction structure

The system in the [quickstart guide](quickstart.md) was extremely simple, and hence the flows that model it also had the simplest possible structure: two actors and a single request/response pair between them.
Expand Down Expand Up @@ -248,7 +257,7 @@ Consider the following worked example:

[flow.Unpredictable]: ../../../../api/src/main/java/com/mastercard/test/flow/Unpredictable.java
[AbstractMessage.masking(Unpredictable,UnaryOperator)]: ../../../../message/message-core/src/main/java/com/mastercard/test/flow/msg/AbstractMessage.java#L50-L57,50-57
[AbstractFlocessor.masking(Unpredictable...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L212-L219,212-219
[AbstractFlocessor.masking(Unpredictable...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L214-L221,214-221
[mask.BenSys]: ../../test/java/com/mastercard/test/flow/doc/mask/BenSys.java
[mask.DieSys]: ../../test/java/com/mastercard/test/flow/doc/mask/DieSys.java
[mask.Unpredictables]: ../../test/java/com/mastercard/test/flow/doc/mask/Unpredictables.java
Expand All @@ -258,7 +267,7 @@ Consider the following worked example:
[msg.Mask.andThen(Consumer)]: ../../../../message/message-core/src/main/java/com/mastercard/test/flow/msg/Mask.java#L290-L292,290-292
[BenDiceTest?masking]: ../../test/java/com/mastercard/test/flow/doc/mask/BenDiceTest.java#L31,31
[BenTest]: ../../test/java/com/mastercard/test/flow/doc/mask/BenTest.java
[AbstractFlocessor.masking(Unpredictable...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L212-L219,212-219
[AbstractFlocessor.masking(Unpredictable...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L214-L221,214-221

<!-- code_link_end -->

Expand All @@ -278,7 +287,7 @@ You can see usage of these types in the example system:
[flow.Context]: ../../../../api/src/main/java/com/mastercard/test/flow/Context.java
[Builder.context(Context)]: ../../../../builder/src/main/java/com/mastercard/test/flow/builder/Builder.java#L225-L232,225-232
[assrt.Applicator]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/Applicator.java
[AbstractFlocessor.applicators(Applicator...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L258-L264,258-264
[AbstractFlocessor.applicators(Applicator...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L260-L266,260-266
[model.ctx.QueueProcessing]: ../../../../example/app-model/src/main/java/com/mastercard/test/flow/example/app/model/ctx/QueueProcessing.java
[QueueProcessingApplicator]: ../../../../example/app-assert/src/main/java/com/mastercard/test/flow/example/app/assrt/ctx/QueueProcessingApplicator.java

Expand All @@ -301,7 +310,7 @@ You can see usage of these types in the example system:

[flow.Residue]: ../../../../api/src/main/java/com/mastercard/test/flow/Residue.java
[assrt.Checker]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/Checker.java
[AbstractFlocessor.checkers(Checker...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L271-L277,271-277
[AbstractFlocessor.checkers(Checker...)]: ../../../../assert/assert-core/src/main/java/com/mastercard/test/flow/assrt/AbstractFlocessor.java#L273-L279,273-279
[model.rsd.DBItems]: ../../../../example/app-model/src/main/java/com/mastercard/test/flow/example/app/model/rsd/DBItems.java
[DBItemsChecker]: ../../../../example/app-assert/src/main/java/com/mastercard/test/flow/example/app/assrt/rsd/DBItemsChecker.java

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ public class FlowData {
@JsonProperty("tags")
public final Set<String> tags;
/**
* public access to allow for enhancing the report with additional information
* using {@link com.mastercard.test.flow.assrt.MotivationCustomizer}
*
* @see Metadata#motivation()
*/
@JsonProperty("motivation")
public final String motivation;
public String motivation;
/**
* @see Metadata#tags()
*/
Expand Down

0 comments on commit f99e9d3

Please sign in to comment.