Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.
This blog post talks about measuring the execution time for each step and reporting it in Twist HTML reports. This is very helpful to analyze application performance and it also makes it easy to spot parts of the application that aren't performing well. This is the first part of a two-part blog series. The second part talks about consuming this data and drawing a little graph in the HTML report.
Twist provides two types of execution hooks. A global and a fixture level hook. In this blog post, we will be using a global hook to measure the execution time for each step in the scenario. We use the Twist data store to keep the measurements. Twist by default renders data store contents as HTML reports. Let us assume we have a scenario like the following:

We use the hooks defined in "ScenarioExecutionHooks" class.
public class ScenarioExecutionHooks {
@Autowired
private TwistScenarioDataStore scenarioStore;
private long startTime;
@BeforeEachStep
public void beforeEachStep() throws Exception {
startTime = System.nanoTime();
}
@AfterEachStep
public void afterEachStep() throws Exception {
double elapsedTimeInSec = (double)(System.nanoTime() - startTime) / 1000000000.0;
IScenarioInformation scenarioInformation = ScenarioInformationFactory.getScenarioInformation();
scenarioStore.put(scenarioInformation.getCurrentStep().getText(), elapsedTimeInSec);
}
}"beforeEachStep" method records the execution start time and "afterEachStep" method records the elapsed time. Finally we add the details into scenario store. Twist will put the scenario store into the HTML report. Below is a preview of the HTML report:

Measuring the elapsed time can also be used to detect performance regressions. If performance regressions are detected, you can fail the scenario if required. To do that, we will tag the scenario with a tag named "should_execute_within_10_secs" (tags are customizable, "should_execute_within_10_secs" is a just an example). In the "after" hook, we will check the elapsed time and fail if necessary. "should_execute_within_10_secs" tag can be used to detect the scenarios where this check is required.
@AfterEachStep
public void afterEachStep() throws Exception {
double elapsedTimeInSec = (double)(System.nanoTime() - startTime) / 1000000000.0;
IScenarioInformation scenarioInformation = ScenarioInformationFactory.getScenarioInformation();
scenarioStore.put(scenarioInformation.getCurrentStep().getText(), elapsedTimeInSec);
String[] tags = scenarioInformation.getTags();
for (String tag : tags) {
if ("should_execute_within_10_secs".equals(tag)
&& elapsedTimeInSec > 10.0) {
fail("Expected to execute within 10 seconds. But took "
+ elapsedTimeInSec + " seconds");
}
}
}The report will look like,

Check out our next post, where we explain how to consume this data and plot a little graph on the report.
Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.
Thoughtworks acknowledges the Traditional Owners of the land where we work and live, and their continued connection to Country. We pay our respects to Elders past and present. Aboriginal and Torres Strait Islander peoples were the world's first scientists, technologists, engineers and mathematicians. We celebrate the stories, culture and traditions of Aboriginal and Torres Strait Islander Elders of all communities who also work and live on this land.
As a company, we invite Thoughtworkers to be actively engaged in advancing reconciliation and strengthen their solidarity with the First Peoples of Australia. Since 2019, we have been working with Reconciliation Australia to formalize our commitment and take meaningful action to advance reconciliation. We invite you to review our Reconciliation Action Plan.