0
votes

I wrote a new JSR223 Listener to write out test results into an extentreports html report. This is working nicely but could be improved. I'm just not sure the best way to improve it. One specific issue I am seeing is the dashboard's Time Taken value. It's showing the start/end time for the last sampler run. It should be showing the time of the first sampler as the start time and the time of the end sampler as the end time and should get the Time Taken value from those 2 datetimes. Can you please have a look at my listener script and share any advice you might have?

Test Plan setup: Inside a thread group, I have HTTP Request samplers that log in, doing one action and log out. At the root of the thread group, I have this code in a BeanShell Assertion with this code:

//request data
String requestData = new String(prev.SamplerData);
//String requestData = new String(requestData);
props.put("propRequestData", requestData);
//response data
String respData = new String(prev.ResponseData);
//String respData = new String(prev.getResponseDataAsString());
props.put("propResponse", respData);
//response code
String respCode = new String(prev.ResponseCode);
props.put("propRespCode",respCode);
//response message
String respMessage = new String(prev.ResponseMessage);
props.put("propRespMessage",respMessage);

At the root of my Test Plan, I have this JSR223 Listener code:

import com.aventstack.extentreports.*;
import com.aventstack.extentreports.reporter.*;
import com.aventstack.extentreports.markuputils.*;

ExtentHtmlReporter htmlReporter;
ExtentReports extent;
ExtentTest test;

// create the HtmlReporter
htmlReporter = new ExtentHtmlReporter("C:/AUTO_Results/Results_${testApp}_${reportDate}_${currentTime}_${testenv}.html");

//configure report
htmlReporter.config().setCreateOfflineReport(true);
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setDocumentTitle("${testApp} Results");
htmlReporter.config().setEncoding("utf-8");
htmlReporter.config().setReportName("${testApp} Results ${reportDate}_${currentTime}_${testenv}");
htmlReporter.setAppendExisting(true);

// create ExtentReports
extent = new ExtentReports();

// attach reporter to ExtentReports
extent.attachReporter(htmlReporter);
extent.setReportUsesManualConfiguration(true); 

// Show Env section and set data on dashboard
extent.setSystemInfo("Tool","JMeter");
extent.setSystemInfo("Test Env","${testenv}");
extent.setSystemInfo("Test Date","${reportDate}");
extent.setSystemInfo("Test Time","${currentTime}");

//stringify test info
String threadName = sampler.getThreadName();
String samplerName = sampler.getName();
String requestData = props.get("propRequestData");
String respCode = props.get("propRespCode");
String respMessage = props.get("propRespMessage");
String responseData = props.get("propResponse");


// create test
test = extent.createTest(threadName+" - "+samplerName);
//test.assignCategory("API Testing");

// analyze sampler result
if (vars.get("JMeterThread.last_sample_ok") == "false") {
   log.error("FAILED: "+samplerName);
   print("FAILED: "+samplerName);
   test.fail(MarkupHelper.createLabel("FAILED:  "+sampler.getName(),ExtentColor.RED));

} else if (vars.get("JMeterThread.last_sample_ok") == "true") {
    if(responseData.contains("@error")) {
        log.info("FAILED: "+sampler.getName());
         print("FAILED: "+sampler.getName());
        test.fail(MarkupHelper.createLabel("FAILED:   "+sampler.getName(),ExtentColor.RED));

    } else if (responseData.contains("{")) {
            log.info("Passed: "+sampler.getName());
        print("Passed: "+sampler.getName());
            test.pass(MarkupHelper.createLabel("Passed:   "+sampler.getName(),ExtentColor.GREEN));
    }

} else {
    log.error("Something is really wonky");
    print("Something is really wonky");
    test.fatal("Something is really wonky");
}

//info messages
    test.info("RequestData:   "+requestData);
    test.info("Response Code and Message:    "+respCode+"   "+respMessage);
    test.info("ResponseData:    "+responseData);



//playing around
//markupify json into code blocks
//Markup m = MarkupHelper.createCodeBlock(requestData);
//test.info(MarkupHelper.createModal("Modal text"));
//Markup mCard = MarkupHelper.createCard(requestData, ExtentColor.CYAN);
//   test.info("Request  "+m);
//  test.info(mCard);
//     test.info("Response Data:     "+MarkupHelper.createCodeBlock(props.get("propResponse")));
//   test.info("ASSERTION MESSAGE:     "+props.get("propAssertion"));


// end the reporting and save the file
extent.flush();

The ${variables} you see listed in the JSR223 Listener are defined in a User Defined Variable element. I am using: jmeter-3.2 extentreports-pro-3.0.5.jar in my lib folder

Here is a screenshot of the dashboard enter image description here

2
I think asking for code review is too broad for SO. You can post it on codereview.stackexchange.com though. - Kiril S.
@KirilS. Not in it's current form. It's asking for a new feature (start time from first sampler instead of start time of last sampler). - Zeta
Thanky you Zeta, yes the issue I'm having is the Time Taken is not correct. I did a bit of a wonky workaround. It will show the actual Time taken in the Environment card on the dashboard. I hope there's a solution but this will do for now. Here's the workaround: - joCha
Thanky you Zeta, yes the issue I'm having is the Time Taken is not correct. I did a workaround. It will show the actual Time taken in the Environment dashboard card. Here's the workaround: (1) add a setUp threat to capture the start time in a property. (2) add a tearDown thread group to capture the end time. Get the difference between the 2 times (I used java.time.Duration and Instance) (3) in the listener code where I am setting the Env info, I added these: extent.setSystemInfo("Actual Test Duration(ms)",props.get("varTimeTakenMS")+" millis"); - joCha

2 Answers

0
votes

Your end time is fine (end sampler), what you need is start of first sampler

I think you can use START predefined property:

START properties are also copied to variables with the same names.

  • START.MS - JMeter start time in milliseconds
  • START.YMD - JMeter start time as yyyyMMdd
  • START.HMS - JMeter start time as HHmmss
  • TESTSTART.MS - test start time in milliseconds

Another option to add JSR223 PostProcessor to first sampler and add to variable the start time:

log.info("start time is " + prev.getStartTime() );
vars.put("startTimeFirstSample", "" + prev.getStartTime() );
0
votes

enter image description here

I ended up with the following workaround for the test duration. 1. in a setup Thread Group, I added a JSR223 Sampler with this code:

log.info("--------------Initialize");
import java.time.Duration;
import java.time.Instant;

Instant myStart = Instant.now();
props.put("varmyStart",myStart);
log.info("Test Start time: ----  "+props.get("varmyStart"));

//response
props.put("propResponse","Test Start time { "+props.get("varmyStart")+" }");
SampleResult.setResponseData(props.get("propResponse"));
  1. in a teardown Thread group, I added a JSR223 Sampler with this code:

    log.info("---------------End Test JSR223Sampler");
    //props.put("varEndTest","Yes"); 
    import java.time.Duration;
    import java.time.Instant;
    Instant myEnd = Instant.now();
    props.put("varmyEnd",myEnd);
    log.info("varmyEnd----  "+props.get("varmyEnd"));
    Duration timeElapsed = Duration.between(props.get("varmyStart"), 
    props.get("varmyEnd"));
    //millis
    props.put("varTimeTakenMS",timeElapsed.toMillis().toString());
    log.info("prop varTimeTaken(MS): --"+props.get("varTimeTakenMS"));
    //seconds
    props.put("varTimeTakenSEC",timeElapsed.getSeconds());
    log.info("prop varTimeTaken(SEC): --"+props.get("varTimeTakenSEC"));
    //minutes
    props.put("varTimeTakenMINS",timeElapsed.toMinutes().toString());
    log.info("prop varTimeTaken(MINS): --"+props.get("varTimeTakenMINS"));
    //response
    props.put("propResponse","Test End time { "+props.get("varmyEnd")+" }.  
    Test Duration: "+props.get("varTimeTakenMINS")+" Minutes");
    SampleResult.setResponseData(props.get("propResponse"));
    
  2. in the listener code, under the // Show Env section and set data on dashboard, I added these lines:

    //extent.setSystemInfo("Actual Test Duration(ms)",props.get("varTimeTakenMS")+" milliseconds");
    extent.setSystemInfo("Actual Test Duration(seconds)",props.get("varTimeTakenSEC")+" seconds");
    extent.setSystemInfo("Actual Test Duration(mins)",props.get("varTimeTakenMINS")+" minutes");
    

It's not pretty but it's giving me what I need.