In JMeter I'm doing a get request to check activeMQ queue size.
This request is made inside a Loop Controller that runs lets say 4 times.
In each iteration I'm extracting the value of outQueueCount into a JMeter variable.
How to do an assertion to verify that the current count value is greater than the previous iteration?
if you have 2 JMeter variables with numbers you can check the difference between them with __intSum function
${__intSum(${outQueueCount},-${currentCount},difference)}
difference will be a new JMeter variable with the result, then you can check if difference is 1 for example:
${__jexl3("${difference}" == "1")}
Add JSR223 Assertion as a child of the request which returns this outQueueCount
Put the following code into "Script" area:
def previousValue = vars.get('previousValue')
if (previousValue == null) {
vars.put('previousValue', vars.get('outQueueCount'))
}
else {
long previous = previousValue as long
long current = vars.get('outQueueCount') as long
if (previous >= current) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Queue size not incremented: previous value: ' + previous + ', current value: ' + current)
}
}
If previous value will be greater than or equal to the new one - you will get an error message and the sampler will get failed:
More information: Scripting JMeter Assertions in Groovy - A Tutorial
1) Add a Counter as a child of your loop controller just before your request with the below configurations:
Start: 1
Increment: 1
Reference Name: Counter
2) Add a BeanShell PostProcessor as a child of your request after your regular expression extractor with the below script in the script area:
String Counter = vars.get("Counter");
vars.put("MyVar_" + Counter, vars.get("MyVar"));// MyVar is the name of your regular expression extractor.
3) Add a BeanShell Assertion after the above BeanShell PostProcessor with the below script in the script area:
int Counter = Integer.parseInt(vars.get("Counter"));
if(Counter > 1){
int Prev = Counter - 1;
int CurrentCount = Integer.parseInt(vars.get("MyVar_" + Counter));
int PrevCount = Integer.parseInt(vars.get("MyVar_" + Prev));
if(CurrentCount < PrevCount){
Failure = true;
FailureMessage = "CurrentCount = " + CurrentCount + " is less than " + "PrevCount = " + PrevCount;}}
Related
I want a function which takes thread name and returns if it is running or not. I have tried isAlive function of java but it did not work.
As an exception I can give you a hint: if you look into ThreadGroup class source code you will see something like:
// List of active threads
private final ConcurrentHashMap<JMeterThread, Thread> allThreads = new ConcurrentHashMap<>();
So all active threads live in allThreads map of the ThreadGroup.
Knowing this you can attempt to find the thread by name in this map, if it is not null - the thread is running and vice versa.
Example code:
def threadName = 'Thread Group 1-1'
def threadGroup = ctx.getThreadGroup()
def field = org.apache.commons.lang3.reflect.FieldUtils.getDeclaredField(threadGroup.getClass(), 'allThreads', true)
def allThreads = field.get(threadGroup)
def thread1 = allThreads.keySet().find { key -> key.getThreadName().equals(threadName) }
if (thread1 != null) {
log.info('Thread ' + threadName + ' is running')
} else {
log.info('Thread ' + threadName + ' is not running')
}
Demo:
More information: Apache Groovy - Why and How You Should Use It
sometime based on some condition it may want to jump (or move forward) a few steps inside the for loop,
how to do it is kolin?
a simplified use case:
val datArray = arrayOf(1, 2, 3......)
/**
* start from the index to process some data, return how many data has been
consumed
*/
fun processData_1(startIndex: Int) : Int {
// process dataArray starting from the index of startIndex
// return the data it has processed
}
fun processData_2(startIndex: Int) : Int {
// process dataArray starting from the index of startIndex
// return the data it has processed
}
in Java it could be:
for (int i=0; i<datArray.lenght-1; i++) {
int processed = processData_1(i);
i += processed; // jump a few steps for those have been processed, then start 2nd process
if (i<datArray.lenght-1) {
processed = processData_2(i);
i += processed;
}
}
How to do it in kotlin?
for(i in array.indices){
val processed = processData(i);
// todo
}
With while:
var i = 0
while (i < datArray.length - 1) {
var processed = processData_1(i)
i += processed // jump a few steps for those have been processed, then start 2nd process
if (i < datArray.length - 1) {
processed = processData_2(i)
i += processed
}
i++
}
You can do that with continue as stated in the Kotlin docs here: https://kotlinlang.org/docs/reference/returns.html
Example:
val names = arrayOf("james", "john", "jim", "jacob", "johan")
for (name in names) {
if(name.length <= 4) continue
println(name)
}
This would only print names longer than 4 characters (as it skips names with a length of 4 and below)
Edit: this only skips one iteration at a time. So if you want to skip multiple, you could store the process state somewhere else and check the status for each iteration.
I am using Jmeter for API automation, I am writing result pass or fail in CSV file.
I am unable to overwrite old result data, Every time I run the test cases it's appending with old result data.
I use Beanshell Post processor for writing in CSV file.
import java.io.file;
import org.apache.jmeter.services.FileServer;
ActualResponseCode = prev.getResponseCode();
if (vars.get("ExpectedResponse").equals(vars.get("ActualResponse")))
{
if(vars.get("ExpectedResponseCode").equals(prev.getResponseCode()))
{
prev.setSuccessful(true);
Result = "Pass";
ErrorMessage = "No Error";
}
else
{
Result = "Fail";
ErrorMessage = "ResponseCode not matching";
}
}
else
{
prev.setSuccessful(false);
Result = "Fail";
ErrorMessage = "ResponseData is not matching";
}
f = new FileOutputStream("C://Users//a622821//Desktop//apache-jmeter-3.2//API_AUTOMATION//TestResult_Post.csv", true);
p = new PrintStream(f);
p.println(vars.get("TestCase") + "," + vars.get("API_Endpoint") + "," + vars.get("ExpectedResponseCode") + "," + ActualResponseCode + "," + Result + "," + ErrorMessage);
p.close();
f.close();
Basically when you write to file you can overrid file by using boolean false as second parameter to FileWriter constructor
File file = ....
new FileWriter(file, false);
If you have several calls for beanshell I suggest create Beanshell sampler which will be called in start of the test and will override the file (create empty file):
import java.io.file;
f = new FileOutputStream("C://Users//a622821//Desktop//apache-jmeter-3.2//API_AUTOMATION//TestResult_Post.csv", false);
p = new PrintStream(f);
p.close();
f.close();
If you must use same beanshell you need a variable flag, so add variable firstTime with value true
In Beanshell use it to set the flag by firstTime variable:
import java.io.file;
import org.apache.jmeter.services.FileServer;
ActualResponseCode = prev.getResponseCode();
if (vars.get("ExpectedResponse").equals(vars.get("ActualResponse")))
{
if(vars.get("ExpectedResponseCode").equals(prev.getResponseCode()))
{
prev.setSuccessful(true);
Result = "Pass";
ErrorMessage = "No Error";
}
else
{
Result = "Fail";
ErrorMessage = "ResponseCode not matching";
}
}
else
{
prev.setSuccessful(false);
Result = "Fail";
ErrorMessage = "ResponseData is not matching";
}
firstTime = vars.get("firstTime");
flag = true;
if ("true".equals(firstTime)) {
flag = false;
vars.put("firstTime", "false");
}
f = new FileOutputStream("C://Users//a622821//Desktop//apache-jmeter-3.2//API_AUTOMATION//TestResult_Post.csv", flag);
p = new PrintStream(f);
p.println(vars.get("TestCase") + "," + vars.get("API_Endpoint") + "," + vars.get("ExpectedResponseCode") + "," + ActualResponseCode + "," + Result + "," + ErrorMessage);
p.close();
f.close();
Test Plan variable:
Don't use scripting to write anything to files, JMeter is able to store literally anything into its .jtl results file so I would recommend rather configuring it to store what you need there rather than trying to create an extra results file in such a weird manner as:
Beanshell is not the best scripting option, if you need to go for scripting consider using JSR223 Test Elements and Groovy language instead
If you are writing something into a file make sure you put aforementioned JSR223 Elements under the Critical Section Controller
So I would suggest switching to either Response Assertion or JSR223 Assertion instead of the PostProcessor. If required you can tell JMeter to store assertion failure message by adding the next line to user.properties file (located in the "bin" folder of JMeter installation, however I think it defaults to true in any case)
jmeter.save.saveservice.assertion_results_failure_message=true
Check out Scripting JMeter Assertions in Groovy - A Tutorial for more details.
I am having problem that the sendInterval I am setting is exceeding the limit I set for it.
Below I just added two lines that I am commenting
void EtherTrafGen::scheduleNextPacket(simtime_t previous)
{
simtime_t next;
if (previous == -1) {
next = simTime() <= startTime ? startTime : simTime();
timerMsg->setKind(START);
}
else {
next = previous + sendInterval->doubleValue();
EV << "THE PREVIOUS TIME IS " << previous << " THE SEND INTERVAL IS " << sendInterval->doubleValue() << endl; // Testing
timerMsg->setKind(NEXT);
}
if (stopTime < SIMTIME_ZERO || next < stopTime)
{
scheduleAt(next, timerMsg);
emit(sigSendInterval,sendInterval->doubleValue()); // Vector collect Send Interval Time
}
}
I tested first with fixed sendInterval value
**.Host5.app.sendInterval = 1ms
THE PREVIOUS TIME IS 0.001 THE SEND INTERVAL IS 0.001
THE PREVIOUS TIME IS 0.002 THE SEND INTERVAL IS 0.001
THE PREVIOUS TIME IS 0.003 THE SEND INTERVAL IS 0.001
From that I assumed Previous Time 2 = Previous Time 1 + Send Interval
Second I assumed The interval time is the same as the one in table under Value (The line shown in code)
Then with random sendInterval value
**.Host5.app.sendInterval = uniform(0.99ms,1.01ms)
THE PREVIOUS TIME IS 0.001001856892 THE SEND INTERVAL IS 0.000998752
THE PREVIOUS TIME IS 0.001999544526 THE SEND INTERVAL IS 0.00100136
THE PREVIOUS TIME IS 0.002999144069 THE SEND INTERVAL IS 0.000997365
Previous Time 2 not equal Previous Time 1 + Send Interval
0.001001856892 + 0.000998752 = 0.002000608892
0.002000608892 - 0.001999544526 = 1.064366 usec
The interval time is not the same as the one under Value as shown in the below table
This is causing that the Host is sending out of the range 0.99ms,1.01ms
The parameter sendInterval is declared in EtherTrafGen.ned as:
volatile double sendInterval #unit(s);
According to the OMNeT++ Simulation Manual:
The volatile modifier indicates that a parameter is re-read every time
a value is needed during simulation.
The variable sendInterval is declared as a pointer to the object which has access to the sendInterval parameter. As a consequence, each time one reads the value of sendInterval, a new random value is returned.
In order to control the current value of sendInterval I suggest reading it only once and storing the result in temporary variable, for example:
void EtherTrafGen::scheduleNextPacket(simtime_t previous)
{
simtime_t next;
double sendIntervalTemp = sendInterval->doubleValue(); // one time read
if (previous == -1) {
next = simTime() <= startTime ? startTime : simTime();
timerMsg->setKind(START);
}
else {
next = previous + sendIntervalTemp ;
EV << "THE PREVIOUS TIME IS " << previous <<
" THE SEND INTERVAL IS " << sendIntervalTemp << endl; // Testing
timerMsg->setKind(NEXT);
}
if (stopTime < SIMTIME_ZERO || next < stopTime)
{
scheduleAt(next, timerMsg);
emit(sigSendInterval, sendIntervalTemp); // Vector collect Send Interval Time
}
}
I'm trying to compare int (parse from string) to counter in BeanShell assertion.
my code:
int i = Integer.parseInt(vars.get("count_2"));
counter = vars.get("counter");
if (i != counter)
{
Failure = true;
FailureMessage = "failed";
} else {
Failure = false;
}
On debug sampler I can see that both "count_2" and "counter" have the same values in all loop runs, but the assertion fails.
What went wrong?
Option 1: use integers everywhere
Change this line:
counter = vars.get("counter");
To:
int counter = Integer.parseInt(vars.get("counter"));
Option 2: use strings everywhere
String i = vars.get("count_2");
String counter = vars.get("counter");
if (!i.equals(counter))
...
JMeterVariables can be either Strings or Objects, so you need to cast them to the types you need to work with.
See How to use BeanShell: JMeter's favorite built-in component guide for essential information on scripting in JMeter and some form of cookbook.