How to get random row from file in JMeter - groovy

I'm looking for way how to get random row from file in JMeter.
I would be appreciate for any suggestions.

Not sure regarding groovy, maybe there is an easier way, but for instance you can do it with Beanshell Sampler using the following code:
import org.apache.commons.io.FileUtils; //necessary import
List lines = FileUtils.readLines(new File("/path/to/your/file")); // read file into lines array
int random = new Random().nextInt(lines.size()); // get random line number
String randomLine = lines.get(random); // get random line
vars.put("randomLine", randomLine); // store the random line into ${randomLine} variable
substitute /path/to/your/file with relative or absolute path to the file you want the random line from
you will be able to access the random line as ${randomLine} where required
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using JMeter and Java APIs from Beanshell test elements in your JMeter test
N.B. The above code is valid groovy code as well

This should be possible using a bean shell controller. Here you will need to do bit of programming to achieve the desired behaviour.
There is an easy way to achieve the desired outcome.
Introduce a ransom timer into your thread group.
The timer will ensure the randomness of the threads.
Configure a CSV confit element to read data from a file.
Ensure the file is shared with all the threads.

you can get a random var
random__Random(1,9)
//syntax: __Random(start,end)
Then you can pull out
File fileInstance = new File("path/yourfile.txt");
readerInstance = new IndexedFileReader(fileInstance);
lines = readerInstance.readLines(randomIdx, randomIdx+1);
readLines takes a start and an end line number..
However if you are using anything other then very small files, with low iterations I really suggest you read the entire file into a buffer, and use the random var to pull lines from that

You can also use the Random CSV Data Set Config Plugin Jmeter plugin by Blazemeter. It has all the randomising a regualr user will want on top of the conventional JMeters CSV Data Set Config.

Related

Does pytest provide a way of automatically reading properties for a test from a yml or conf file?

I'm using Python 3.8 and pytest for unit testing. I have tests similar to the following
def test_insert_record(az_sql_db_inst):
    """."""
    foreign_key_id = 10
I don't like hard-coding "10" in the file, and would prefer this be stored in some external configuration file where other tests can also access the value. Does pytest provide a way to do this (to load the values from a properties or yml file)? I could just open a file on my own, e.g.
def test_insert_record(az_sql_db_inst):
    """."""
file = open('test.txt')
for line in file:
fields = line.strip().split()
foreign_key_id = fields[0]
but it seems like there is something that can automatically do that for me.
If you simply want to initialize some constants, a separated config.py would do the trick.
from config import foreign_key_id
And PyYAML package would be good if you prefer general-purpose text files.
However, if you want to specify expected test results or even different results depending on scenarios, #pytest.mark.parametrize may be a good option.

Why is the same function in python-chess returning different results?

I'm new to working with python-chess and I was perusing the official documentation. I noticed this very weird thing I just can't make sense of. This is from the documentation:
import chess.pgn
pgn = open("data/pgn/kasparov-deep-blue-1997.pgn")
first_game = chess.pgn.read_game(pgn)
second_game = chess.pgn.read_game(pgn)
So as you can see the exact same function pgn.read_game() results in two different games to show up. I tried with my own pgn file and sure enough first_game == second_game resulted in False. I also tried third_game = chess.pgn.read_game() and sure enough that gave me the (presumably) third game from the pgn file. How is this possible? If I'm using the same function shouldn't it return the same result every time for the same file? Why should the variable name matter(I'm assuming it does) unless programming languages changed overnight or there's a random function built-in somewhere?
The only way that this can be possible is if some data is changing. This could be data that chess.pgn.read_game reads from elsewhere, or could be something to do with the object you're passing in.
In Python, file-like objects store where they are in the file. If they didn't, then this code:
with open("/home/wizzwizz4/Documents/TOPSECRET/diary.txt") as f:
line = f.readline()
while line:
print(line, end="")
line = f.readline()
would just print the first line over and over again. When data's read from a file, Python won't give you that data again unless you specifically ask for it.
There are multiple games in this file, stored one after each other. You're passing in the same file each time, but you're not resetting the read cursor to the beginning of the file (f.seek(0)) or closing and reopening the file, so it's going to read the next data available – i.e., the next game.

Somtime issues when Read csv data config from jmeter

I have an issue when creating a performance script, which has related to reading data from csv data config.
My script has a structure below:
setup Thread
Create csv Thread. After view dashboard, using Json extractor to get list of data and put it to csv file
Create csv file - After this thread, i will have a lot of csv file base on number of center. For example: 4 files with different names
String[] attempt = (vars.get("ListAttemptId_ALL")).split(",");
int length = attempt.length;
String dir = props.get("UserFilePath").toString();
String center = vars.get("Center");
File csvFile = new File(dir, center + ".csv");
if(!csvFile.exists()){
FileWriter fstream = new FileWriter(csvFile);
BufferedWriter out = new BufferedWriter(fstream);
for(int i = 1; i <= length; i++){
out.write(attempt[i-1]);
out.write(System.getProperty("line.separator"));
}
out.close();
fstream.close();
}
Next thread gets the name of the file and using CSV file to loop over
all line
String center = vars.get("Center");
String fileName = center + ".csv";
props.put("path_${__threadNum}", String.valueOf(fileName));
Because i have alot of threads will run the same file, so i just check __threadNum of to find the name of the file this thread need to use.
I'm using loop Controller to go over CSV file, run to the end of the file will stop thread. Here is inside this loop
CSV data Set config:
Filename: ${__property(UserFilePath)}\\${__P(path_${__threadNum})}
where ${__property(UserFilePath)} = path of the folder and
${__P(path_${__threadNum})} is name of the csv file were extracted
My issue is this code is not stable, sometimes threads can read file normally, sometimes it's show error that file does not exist (actually it did) so it's hard to chase that where issue from. Can anyone suggest a solution to my issue? Or suggest any idea better than my solution to read csv file in thread group?
I have answer for this issue:
- I add all data AttemptId, Center to one file csv and read from beginning to and end. Using If controller to verify data before action.
This statement can be problematic:
props.put("path_${__threadNum}", String.valueOf(fileName));
as per JSR223 Sampler documentation
JMeter processes function and variable references before passing the script field to the interpreter, so the references will only be resolved once. Variable and function references in script files will be passed verbatim to the interpreter, which is likely to cause a syntax error. In order to use runtime variables, please use the appropriate props
methods, e.g.
props.get("START.HMS");
props.put("PROP1","1234");
So I would recommend replacing ${__threadNum} with ctx.getThreadNum() where ctx is a shorthand for JMeterContext class
According to Execution Order chapter of JMeter Documentation:
0. Configuration elements
1. Pre-Processors
2. Timers
3. Sampler
4. Post-Processors (unless SampleResult is null)
5. Assertions (unless SampleResult is null)
6. Listeners (unless SampleResult is null)
your CSV Data Set Config is executed at the first place, before any other scripting test elements. So the times when it "works" IMO are being caused by "false positive" situation as JMeter Properties are global and "live" while JMeter (and underlying JVM) is running. When you launch JMeter next time the properties will be null and your CSV Data Set Config will fail. So my expectation is that you should consider using __CSVRead() function instead which is evaluated in the runtime exactly in the place where it's being called. Check out Apache JMeter Functions - An Introduction article to learn more about JMeter Functions concept.

How to get the result values appended to an CSV file in jmeter(groovy)

I am getting a value from HTTP request which I am writing it into a CSV file, each and every time when the program is executed, the new values are overwritten and not appended to the CSV. I would like to append the values instead of overwriting. I am using Regex and XPath extractor to get the values from the HTTP requests and writing it an CSV file.
new File('/Users/ddd/testgui/queueId1.csv').newWriter().withWriter { w ->
w << vars.get('queueid')
}
So this works for me, on groovysh 2.5.3 :
new File('/Users/ddd/testgui/queueId1.csv').newWriter(true).withWriter { w ->
w << vars.get('queueid')
}
The true in the newWriter is for append == true.
You can do just:
new File('/Users/ddd/testgui/queueId1.csv') << vars.get('queueid')
Be aware that your code is going to work fine only when you have 1 thread, if there will be more - you may suffer from a race condition when 2 threads will be simultaneously writing into a file.
If you're going to execute this code with > 1 virtual user I would rather recommend going for Sample Variables functionality.
If you add the next line to user.properties file:
sample_variables=queueid
and restart JMeter to pick the property up next time you run your test the .jtl results file will have an extra column with queueid variable value for each thread/request.
If you want to store it into a separate file - go for Flexible File Writer

Overwriting specific lines in Python

I have a simple program that manipulates some stored data on some text files. However I have to store the name and the password on different files for python to read.
I was wondering if I could get these two words (The name and the password) on two separate lines on one file and get python to overwrite just one of the lines based on what I choose to overwrite (either the password or the name).
I can get python to read specific lines with:
linenumber=linecache.getline("example.txt",4)
Ideally id like something like this:
linenumber=linecache.writeline("example.txt","Hello",4)
So this would just write "Hello" in "example.txt" only on line 4.
But unfortunately it doesn't seem to be as simple as that, I can get the words to be stored on separate files but overall doing this on a larger scale, I'm going to have a lot of text files all named differently and with different words on them.
If anyone would be able to help, it would be much appreciated!
Thanks, James.
You can try with built in open() function:
def overwrite(filename,newline,linenumber):
try:
with open(filename,'r') as reading:
lines = reading.readlines()
lines[linenumber]=newline+'\n'
with open(filename,'w') as writing:
for i in lines:
writing.write(i)
return 0
except:
return 1 #when reading/writing gone wrong, eg. no such a file
Be careful! It is writing all the lines all over again in a loop and when it comes to exception example.txt may already be blank. You may want to store all the lines in list all the time to write them back to file in exception. Or keep backup of your old files.

Resources