Need to form custom request in jmeter - jmeter

I am in need to create a custom request in jmeter which looks like the below format:
{
"items": [
{
"id": "1",
"productId": 1234
}
{
"id": "2",
"productId": 1218
}
....
}
Here I have to generate some random number in between 10-15 and create the id blocks(based on the random number).
Could someone please help how can I form the request accordingly and achieve this in jmeter.
Thanks in advance.

Add JSR223 PreProcessor as a child of the request which need to send this generated value
Put the following code into "Script" area
import groovy.json.JsonBuilder
import org.apache.commons.lang3.RandomUtils
def items = []
def itemsNo = RandomUtils.nextInt(10, 16)
1.upto(itemsNo) { id ->
def productId = RandomUtils.nextInt(1111, 10000)
def item = [:]
item.put('id', id as String)
item.put('productId', productId)
items.add(item)
}
def payload = new JsonBuilder([items: items]).toPrettyString()
vars.put('payload',payload)
Use ${payload} JMeter Variable where you need to refer the generated JSON
Demo:
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

Related

DjangoREST: Extracting value from POST request to use in overridden create method

I am trying to accomplish a simple task of extracting the value passed from the POST request and using it as a parameter inside the overridden create method.
This is the example POST request body JSON, and "documented" is the field I wish to extract.
### POST
{
"url": "aaaa",
"title": "bbbb",
"publisher": "bbbb",
"desc": "bbbb",
"summary": "bbbb",
"documentId": "onDKe6K"
}
Using validated_data.pop("documentId") was the most obvious choice. However, I need DocumentListingField set to read_only=False in order to use this method. And that option raised larger issues as my Document model has an Hashfield that is not easily serializable.
Is there any other way to accomplish what I want in this situation? I've tried all of these but they all failed with "KeyError: documented"
validated_data.get("documentId")
validated_data["documentId"]
serializers.py
from django.forms.models import model_to_dict
class DocumentListingField(serializers.RelatedField):
def to_representation(self, instance):
return model_to_dict(instance.document)
class MySourceSerializer(serializers.ModelSerializer):
Document = DocumentListingField(many=False, read_only=True)
class Meta:
model = MySource
fields = (
"id",
"url",
"title",
"publisher",
"desc",
"summary",
"Document",
)
def create(self, validated_data):
documentId = validated_data.get("documentId"). <========= LINE OF INTEREST
print(documentId)
source = MySource.objects.create(
document=Document.objects.get(id=documentId), **validated_data
)
print(validated_data)
source.save()
return source
I think you can set the documentId field in the serializer.
class MySourceSerializer(serializers.ModelSerializer):
Document = DocumentListingField(many=False, read_only=True)
documentId = serializers.CharField(write_only = True)
lass Meta:
model = MySource
fields = (
...
"documentId",
)

JMeter construct payload from csv file

I needed to construct an HTTP request body from a CSV file.
There are 3 columns (userID, SessionId, groupId) and 1000 userIDs in the CSV file.
The API I was testing had a requirement for bulk loading, and each bulk contains 200 userIDs.
Below is the sample of the payload:
{
"data": [
{
"username": "<userID>",
"remoteMeetingGroupName": "<groupID>"
},
{
"username": "<userID>",
"remoteMeetingGroupName": "<groupID>"
},
...
]
}
So based on the requirement of 200 users per bulk, I will need to create 5 concurrent users, each of while containing 200 users in the CSV file. Is ForEach controller able to do this? Could anyone gimme some hints? Thanks.
The request body can be constructed from the CSV file using JSR223 PreProcessor, something like:
def start = (vars.get('__jm__Thread Group__idx') as int)
def offset = (start + 1) * 200
def payload = [:]
def data = []
start.upto(offset, { index ->
def lineFromCsv = new File('test.csv').readLines().get(index)
data.add(['username': lineFromCsv.split(',')[0]])
data.add(['remoteMeetingGroupName': lineFromCsv.split(',')[1]])
})
payload.put('data', data)
vars.put('payload', new groovy.json.JsonBuilder(payload).toPrettyString())
Refer generated request body as ${payload} where required.
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

validate response using jsr223 assertion

I have passed chgId as parameter in the get HTTP request.
https://*****?chgId=405
My api response is coming as -
{
"response": {
"data": [
{
"tid": 3697,
"chgId": 405,
"amount": 8.5,
"Currency": "USD",
},
{
"tid": 3698,
"chgId": 405,
"amount": 3.33,
"Currency": "USD",
}
]
}
}
Now from the response I want to validate in JSR223 assertion that the response is correct based on the chgId field. That means in both 'data' array "chgId": 405 text should come.
Can anyone suggest?
You could do something like:
def params = org.apache.http.client.utils.URLEncodedUtils.parse(prev.getURL().toURI(), 'UTF-8')
def expected = params.find { 'chgId' }.value as int
def actual1 = new groovy.json.JsonSlurper().parse(prev.getResponseData()).response.data[0].chgId
def actual2 = new groovy.json.JsonSlurper().parse(prev.getResponseData()).response.data[1].chgId
def success = (expected == actual1 && expected == actual2)
if (!success) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('chgId mismatch')
}
where prev stands for previous SampleResult
More information:
URLEncodedUtils JavaDoc
JsonSlurper
Apache Groovy - Parsing and producing JSON
Scripting JMeter Assertions in Groovy - A Tutorial

How to return an jsonarray in BeanShell PostProcessor for next testcase in jmeter

After I get a list like this:
[{
"id": "55af0d89ba411ff8b8000680",
},{
"id": "55af0d89ba411ff8b80006bc",
"object": {
"id": "55af0d89ba411ff8b80006bd",
}
}]
In the BeanShell PostProcessor I have code to return an list Id like this:
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import java.util.*;
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
Iterator i = GroupList.iterator;
JSONArray GroupIds = new JSONArray();
while (i.hasNext())
{
JSONObject objGroup = (JSONObject) i.next();
GroupIds.push(objGroup.get("id"));
}
vars.putObject("GroupIds",GroupIds);
For the next test element, I create the foreach Loop controller to loop the GroupIds, but I see in the log, it has error like this:
jmeter.util.BeanShellInterpreter: Error invoking bsh method:
eval Sourced file: inline evaluation of: ``import
org.json.simple.JSONObject; import org.json.simple.JSONArray; import
org. . . . '' : Typed variable declaration : Cannot access field:
iterator, on object:[{
"id": "55af0d89ba411ff8b8000680",
"name": "Companies",
"description": "Contacts of companies",
"type": "Group",
"created_at": "2015-07-22T03:27:05Z",
"updated_at": "2015-07-23T02:45:02Z",
"dominant_gender": "unknown",
"average_age": "?" }, {
"id": "55af0d89ba411ff8b80006bc",
"name": "Subscription",
"description": "Subscription",
"type": "Subscriptions::SubscriptionList",
"average_age": "?",
"subscription": {
"id": "55af0d89ba411ff8b80006bd",
"name": "Subcription 1",
"form_ids": ["5526430cba411ff8c30001cd"]
} }]
jmeter.extractor.BeanShellPostProcessor: Problem in BeanShell script
org.apache.jorphan.util.JMeterException: Error invoking bsh method:
eval Sourced file: inline evaluation of: ``import
org.json.simple.JSONObject; import org.json.simple.JSONArray; import
org. . . . '' : Typed variable declaration : Cannot access field:
iterator, on object:[{
"id": "55af0d89ba411ff8b8000680",
"name": "Companies",
"description": "Contacts of companies",
"type": "Group",
"created_at": "2015-07-22T03:27:05Z",
"updated_at": "2015-07-23T02:45:02Z",
"dominant_gender": "unknown",
"average_age": "?" }, {
"id": "55af0d89ba411ff8b80006bc",
"name": "Subscription",
"description": "Subscription",
"type": "Subscriptions::SubscriptionList",
"average_age": "?",
"subscription": {
"id": "55af0d89ba411ff8b80006bd",
"name": "Subcription 1",
"form_ids": ["5526430cba411ff8c30001cd"]
} }]
What is the problem?
There are few issues with your code:
Iterator i = GroupList.iterator; - parentheses are required as iterator is a method, not field.
GroupIds.push(objGroup.get("id")); - change push to add, there is no push method
Full working code:
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
Iterator i = GroupList.iterator();
JSONArray GroupIds = new JSONArray();
while (i.hasNext()) {
JSONObject objGroup = (JSONObject) i.next();
GroupIds.add(objGroup.get("id"));
}
vars.putObject("GroupIds", GroupIds);
By the way, it isn't very recommended to use Beanshell for under high load as it is not very efficient. For one thread it is OK, but when it comes to immense load - it may become performance bottleneck and may ruin your test. If it is the case - consider switching to JSR223 PostProcessor and "groovy" language instead.
A very little change will be required:
adding groovy-all.jar to JMeter's /lib folder
substitute all Beanshell test elements to JSR223 with "groovy" engine
See Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! article for detailed installation instructions, scripting tips and tricks and different scripting engines performance benchmark.
UPDATE - generate variables for ForEach Controller:
import org.json.simple.parser.JSONParser;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
for (int i = 0; i < GroupList.size(); i++) {
JSONObject objGroup = (JSONObject) GroupList.get(i);
vars.put("Group_" + i, objGroup.get("id"));
}
Then add a ForEach Controller and configure it as follows:
Input variable prefix: Group
Start index: -1
Output variable name: CURRENT_GROUP
Add "_" before number - check the box
Use ${CURRENT_GROUP} where required

django: Testing POST-based views with json objects

I have a django application with several views that accept json objects via POST requests. The json objects are medium-complex with a few layers of nesting, so I'm using the json library to parse raw_post_data, as shown here:
def handle_ajax_call(request):
post_json = json.loads(request.raw_post_data)
... (do stuff with json query)
Next, I want to write tests for these views. Unfortunately, I can't figure out how to pass the json object to the Client. Here's a simplest-case version of my code:
def test_ajax_call(self):
c = Client()
call_command('loadfixtures', 'temp-fixtures-1') #Custom command to populate the DB
J = {
some_info : {
attr1 : "AAAA",
attr2 : "BBBB",
list_attr : [ "x", "y", "z" ]
},
more_info : { ... },
info_list : [ 1, 22, 23, 24, 5, 26, 7 ]
}
J_string = json.dumps(J)
response = c.post('/ajax/call/', data=J_string )
When I run the test, it fails with:
AttributeError: 'str' object has no attribute 'items'
How can I pass the JSON object in the Client.post method?
The documentation seems to imply that if you pass a content_type parameter to client.post, it will treat the data value as a document and POST it directly. So try this:
response = c.post('/ajax/call/', content_type='application/json', data=J_string)

Resources