BAEL-5990 is implemented to generate JMeter dashboard reports (#13345)

* BAEL-5990 is implemented to generate JMeter dashboard reports

* BAEL-5990 made a fix to use Random nextInt() method with single arg

* BAEL-5990 updated code to use Arrays.asList rather than List.of

* BAEL-5990 Replaced tabs with space

* BAEL-5990 Removed unnecessary exception in the method declaration

* BAEL-5990 Updated class name
This commit is contained in:
Muhammad Asif 2023-02-04 21:25:23 +05:00 committed by GitHub
parent 0e1a3beb99
commit 107232d079
10 changed files with 345 additions and 0 deletions

View File

@ -69,4 +69,90 @@
<jmeter.version>2.6.0</jmeter.version>
</properties>
<profiles>
<profile>
<id>dashboard</id>
<activation>
<property>
<name>env</name>
<value>dash</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>launch-web-app</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<mainClass>com.baeldung.dashboard.DashboardApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>3.7.0</version>
<executions>
<!-- Generate JMeter configuration -->
<execution>
<id>configuration</id>
<goals>
<goal>configure</goal>
</goals>
</execution>
<!-- Run JMeter tests -->
<execution>
<id>jmeter-tests</id>
<goals>
<goal>jmeter</goal>
<goal>results</goal>
</goals>
</execution>
</executions>
<configuration>
<testFilesDirectory>${project.basedir}/src/main/resources/dashboard</testFilesDirectory>
<resultsDirectory>${project.basedir}/src/main/resources/dashboard</resultsDirectory>
<generateReports>true</generateReports>
<ignoreResultFailures>true</ignoreResultFailures>
<testResultsTimestamp>false</testResultsTimestamp>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>stop-web-app</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<jmeter.version>5.5</jmeter.version>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,15 @@
package com.baeldung.dashboard;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, MongoAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class, MongoDataAutoConfiguration.class })
public class DashboardApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(DashboardApplication.class, args);
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.dashboard.controllers;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.baeldung.dashboard.models.Quotes;
@Controller
public class Dashboard {
@GetMapping("/greeting")
public String getGreeting(Model model) {
model.addAttribute("host", System.getProperty("os.name"));
return "greeting";
}
@GetMapping("/quote")
public String getQuote(Model model) throws InterruptedException {
Random r = new Random();
int day = r.nextInt(7);
String quote = Quotes.list.get(day);
int wait = r.nextInt(6);
Thread.currentThread().sleep(wait);
model.addAttribute("quote", quote);
return "quote";
}
@GetMapping("/time")
public String getTime(Model model) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("hh:mm:ss a");
LocalDateTime now = LocalDateTime.now();
model.addAttribute("time", fmt.format(now));
return "time";
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.dashboard.models;
import java.util.Arrays;
import java.util.List;
public class Quotes {
public static final List<String> list = Arrays.asList("The greatest glory in living lies not in never falling, but in rising every time we fall. -Nelson Mandela\r\n",
"The way to get started is to quit talking and begin doing. -Walt Disney\r\n",
"Your time is limited, so don't waste it living someone else's life. Don't be trapped by dogma which is living with the results of other people's thinking. -Steve Jobs\r\n",
"If life were predictable it would cease to be life, and be without flavor. -Eleanor Roosevelt\r\n",
"If you look at what you have in life, you'll always have more. If you look at what you don't have in life, you'll never have enough. -Oprah Winfrey\r\n",
"If you set your goals ridiculously high and it's a failure, you will fail above everyone else's success. -James Cameron\r\n", "Life is what happens when you're busy making other plans. -John Lennon");
}

View File

@ -0,0 +1,16 @@
timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
1674622105952,714,HTTP Request (/greeting),200,,Thread Group 1-4,text,true,,430,126,5,5,http://localhost:8080/greeting,705,0,7
1674622105450,1216,HTTP Request (/greeting),200,,Thread Group 1-1,text,true,,430,126,5,5,http://localhost:8080/greeting,1207,0,54
1674622105468,1198,HTTP Request (/greeting),200,,Thread Group 1-2,text,true,,430,126,5,5,http://localhost:8080/greeting,1189,0,36
1674622106064,602,HTTP Request (/greeting),200,,Thread Group 1-5,text,true,,430,126,5,5,http://localhost:8080/greeting,593,0,2
1674622105800,866,HTTP Request (/greeting),200,,Thread Group 1-3,text,true,,430,126,5,5,http://localhost:8080/greeting,857,0,1
1674622106669,13,HTTP Request (/quote),200,,Thread Group 1-4,text,true,,515,123,5,5,http://localhost:8080/quote,12,0,0
1674622106669,16,HTTP Request (/quote),200,,Thread Group 1-2,text,true,,548,123,5,5,http://localhost:8080/quote,16,0,0
1674622106671,18,HTTP Request (/quote),200,,Thread Group 1-1,text,true,,629,123,5,5,http://localhost:8080/quote,18,0,0
1674622106669,24,HTTP Request (/quote),200,,Thread Group 1-5,text,true,,602,123,5,5,http://localhost:8080/quote,24,0,0
1674622106669,29,HTTP Request (/quote),200,,Thread Group 1-3,text,true,,515,123,5,5,http://localhost:8080/quote,29,0,0
1674622106690,18,HTTP Request (/time),200,,Thread Group 1-1,text,true,,432,122,5,5,http://localhost:8080/time,18,0,0
1674622106699,9,HTTP Request (/time),200,,Thread Group 1-3,text,true,,432,122,5,5,http://localhost:8080/time,9,0,0
1674622106683,26,HTTP Request (/time),200,,Thread Group 1-4,text,true,,432,122,5,5,http://localhost:8080/time,25,0,0
1674622106688,25,HTTP Request (/time),200,,Thread Group 1-2,text,true,,432,122,2,2,http://localhost:8080/time,25,0,0
1674622106695,18,HTTP Request (/time),200,,Thread Group 1-5,text,true,,432,122,2,2,http://localhost:8080/time,17,0,0
1 timeStamp elapsed label responseCode responseMessage threadName dataType success failureMessage bytes sentBytes grpThreads allThreads URL Latency IdleTime Connect
2 1674622105952 714 HTTP Request (/greeting) 200 Thread Group 1-4 text true 430 126 5 5 http://localhost:8080/greeting 705 0 7
3 1674622105450 1216 HTTP Request (/greeting) 200 Thread Group 1-1 text true 430 126 5 5 http://localhost:8080/greeting 1207 0 54
4 1674622105468 1198 HTTP Request (/greeting) 200 Thread Group 1-2 text true 430 126 5 5 http://localhost:8080/greeting 1189 0 36
5 1674622106064 602 HTTP Request (/greeting) 200 Thread Group 1-5 text true 430 126 5 5 http://localhost:8080/greeting 593 0 2
6 1674622105800 866 HTTP Request (/greeting) 200 Thread Group 1-3 text true 430 126 5 5 http://localhost:8080/greeting 857 0 1
7 1674622106669 13 HTTP Request (/quote) 200 Thread Group 1-4 text true 515 123 5 5 http://localhost:8080/quote 12 0 0
8 1674622106669 16 HTTP Request (/quote) 200 Thread Group 1-2 text true 548 123 5 5 http://localhost:8080/quote 16 0 0
9 1674622106671 18 HTTP Request (/quote) 200 Thread Group 1-1 text true 629 123 5 5 http://localhost:8080/quote 18 0 0
10 1674622106669 24 HTTP Request (/quote) 200 Thread Group 1-5 text true 602 123 5 5 http://localhost:8080/quote 24 0 0
11 1674622106669 29 HTTP Request (/quote) 200 Thread Group 1-3 text true 515 123 5 5 http://localhost:8080/quote 29 0 0
12 1674622106690 18 HTTP Request (/time) 200 Thread Group 1-1 text true 432 122 5 5 http://localhost:8080/time 18 0 0
13 1674622106699 9 HTTP Request (/time) 200 Thread Group 1-3 text true 432 122 5 5 http://localhost:8080/time 9 0 0
14 1674622106683 26 HTTP Request (/time) 200 Thread Group 1-4 text true 432 122 5 5 http://localhost:8080/time 25 0 0
15 1674622106688 25 HTTP Request (/time) 200 Thread Group 1-2 text true 432 122 2 2 http://localhost:8080/time 25 0 0
16 1674622106695 18 HTTP Request (/time) 200 Thread Group 1-5 text true 432 122 2 2 http://localhost:8080/time 17 0 0

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="ReportsDashboard" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="TestPlan.comments">Test Greetings Page</stringProp>
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">5</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request (/greeting)" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/greeting</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request (/quote)" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/quote</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request (/time)" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/time</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename">dashapp</stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>

View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Jmeter Dashboard Test APP</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Get your Quote <a href="/quote">here</a></p>
<p>Get your Time <a href="/time">here</a></p>
<p>Get your greeting <a href="/greeting">here</a></p>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Jmeter Dashboard Test APP</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Hello from, ' + ${host} + '!'" />
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Jmeter Dashboard Test APP</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 th:text="'Quote of the day:'" />
<p th:text="${quote}" />
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Jmeter Dashboard Test APP</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Current Time: ' + ${time}" />
</body>
</html>