Gatling Scala - Replace substring in a array list of value - gatling

In Gatling (using Scala), I have extracted an array of value which I want to modify and use it in my subsequent request.
Post extraction, as part of modification, using .transform I tried replacing sub-string, but that doesn't work and throws an error 'not found: value transform'
Please see if you can look at the code below and suggest any fix.
1: foreach used to iterate through all array of value.
2: transform function is used to replace a substring with blank.
.exec(http("SC01_T03_Step2_Next")
.post("/function")
.headers(headers_9)
.check(
regex("[0-9]{2,3}</label></span></div>")
.findAll
.saveAs("c_LargeOrder"))
.formParam("utf8", "✓")
.formParam("authenticity_token", "#{c_AuthToken}")
.formParam("challenger[step_id]", "#{c_StepID2}")
.formParam("challenger[step_number]", "2")
.formParam("challenger[age]", "#{p_age}")
.formParam("commit", "Next")
.check(bodyString.saveAs("Trans3Body"))
)
.foreach("#{c_LargeOrder}", "c_LargeOrder1") // 1
{
exec(
session =>
{
transform(str => str.replace("</label></span></div>","")) // 2
}
)
}

Related

Google Script is returning the index of the array but I need the value

I have a google spreadsheet that gets data logged to it via a google form.
When the form is logged each time, it triggers a script that gets values from a certain section using:
var tabNumsVal = sheet.getSheetValues(lastRow, tabOneCol.getColumn(), 1, 6)[0];
When I check the array, I can see that the array has the values such as:
0: 12
1: 24
2: 26W
3: 0
4: 0
5: 0
However when I use the following command, it puts the index numbers (0 to 5) into the array instead of the values in the array.
var tabNumsFinal = [];
for (var tabard in tabNumsVal) {
if (tabard !== "") {
tabNumsFinal.push(tabard);
}
}
It used to work but I have had to upgrade my code to Google Script v8 and it seems that this has broken the code.
I had to alter the 'for each' code block to a 'for' code block and it seems this is handling the values differently.
I am quite sure this is simple for many people but I really only touch Google Script 1 time each year. I have tried using Logger.log(tabard) to output the data to the execution log, but it just traverses the code and doesn't output anything. I figured this might be because of the !== "" operator, so I placed it above the if statement but still inside the for statement and it still outputs nothing.
I tried using Logger.log(tabNumsVal) and Logger.log(tabNumsFinal) and again it output nothing.
To recap:
The data from the form is returning correctly into the columns of the spreadsheet, hence it is showing inside the array properly. It's just that the index numbers are being output instead of the values from the array.
Since you're using for in loop, tabard is the index here.
var tabNumsFinal = [];
for (var i in tabNumsVal) {
let val = tabNumsVal[i];
if (val !== "") {
tabNumsFinal.push(val);
}
}
For in loop

Summing the values of multiple Vectors in the session

In my gatling scenario, I need to check the session for a few entries that will be Vectors of numbers. I can get the Vectors if present, but when I attempt to add them using .sum I get a ClassCastException stating that java.lang.String can't be cast to java.lang.Integer
I've debugged by printing out the value retrieved from the session (Vector(100,200,300)), and even confirmed that the individual elements are Ints. However when I try to add any of them, either with something like values.sum or values(0)+values(1) I get the class cast exception
I'm setting values in the session with checks like
.check(jsonPath("$..payments..paymentAmount").findAll.optional.saveAs("payments"))
.check(jsonPath("$..receipts..receiptAmount").findAll.optional.saveAs("receipts"))
in my app these will always result in things like Vector(100, 200, 300) if the path was there
then later I want to sum all the values in these lists so I have the action
.exec(session => {
def addAmounts(listNames: Array[String]): Int = {
listNames.foldLeft(0)((acc, listName) => {
session(listName).validate[Seq[Int]] match {
case Success(ints) => ints.sum + acc
case Failure(error) => acc
}})
}
val transactionsTotal = addAmounts(Array("payments", "receipts"))
session.set("total",transactionsTotal)
}
As mentioned, this fails on the listName.sum + acc statement - since they're both Ints I'd expect there'd be no need to cast from a string
The Failure case where nothing was stored from the check works fine
I think this is a scala type inference issue - I got it working by manually casting to Int before doing addition

Comparing array with array of hashes and outputing new array of hashes

I have an array of subscription instances #subscription_valids and an array of subscribed player that look like that :
array_subscribed_players = [{"name0" => "link1"}, {"name1"=>"link2"}, {"name2"=>"link3"}....]
What I need to do is : for each subscription in #subscription_valids :
#subscription_valids.each do |subscription|
I need to check if subscription.user.full_name or if subscription.user.full_name_inversed matches a key in one of the hashes of array_subscribed_player (in the exemple "name0", "name1" or "name2").
If it matches then I should store the relevant subscription as key in a hash in a new array and extract the relevant link as value of this hash. My final outpout should be an array that looks like this :
[{subscription1 => "link1"}, {subscription2 => "link2}, ...]
else if the subscription.user.full_name doesnt match i'll just store the subscription in a failure array.
How can I achieve this result ?
See http://ruby-doc.org/core-2.2.3/Hash.html
A user-defined class may be used as a hash key if the hash and eql?
methods are overridden to provide meaningful behavior. By default,
separate instances refer to separate hash keys.
so I think you should override your .eql? method in #subscription_valids to something meaningful (like a unique string)
I can't think for a Array method so you can go like:
demo
results = []
failures = []
#subscription_valids.each do |subscription|
array_subscribed_players.each do |player|
if player.keys.first == subscription.user.full_name || player.keys.first == subscription.user.full_name_inversed
results << { subscription => player[player.keys.first] }
else
failures << subscription
end
end
end
You can try the following:
valid = array_subscribed_players.select{|x| #subscription_valids.map(&:name).include?(x.keys.first)}
Demo
If you need to store both valid and invalid values somewhere:
valid, invalid = array_subscribed_players.partition{|x| #subscription_valids.map(&:name).include?(x.keys.first)}

How to increment a variable in Gatlling Loop

I am trying to write a Gatling script where I read a starting number from a CSV file and loop through, say 10 times. In each iteration, I want to increment the value of the parameter.
It looks like some Scala or Java math is needed but could not find information on how to do it or how and where to combine Gatling EL with Scala or Java.
Appreciate any help or direction.
var numloop = new java.util.concurrent.atomic.AtomicInteger(0)
val scn = scenario("Scenario Name")
.asLongAs(_=> numloop.getAndIncrement() <3, exitASAP = false){
feed(csv("ids.csv")) //read ${ID} from the file
.exec(http("request")
.get("""http://finance.yahoo.com/q?s=${ID}""")
.headers(headers_1))
.pause(284 milliseconds)
//How to increment ID for the next iteration and pass in the .get method?
}
You copy-pasted this code from Gatling's Google Group but this use case was very specific.
Did you first properly read the documentation regarding loops? What's your use case and how doesn't it fit with basic loops?
Edit: So the question is: how do I get a unique id per loop iteration and per virtual user?
You can compute one for the loop index and a virtual user id. Session already has a unique ID but it's a String UUID, so it's not very convenient for what you want to do.
// first, let's build a Feeder that set an numeric id:
val userIdFeeder = Iterator.from(0).map(i => Map("userId" -> i))
val iterations = 1000
// set this userId to every virtual user
feed(userIdFeeder)
// loop and define the loop index
.repeat(iterations, "index") {
// set an new attribute named "id"
exec{ session =>
val userId = session("userId").as[Int]
val index = session("index").as[Int]
val id = iterations * userId + index
session.set("id", id)
}
// use id attribute, for example with EL ${id}
}
Here is my answer to this:
Problem Statement: I had to repeat the gatling execution for configured set of times, and my step name has to be dynamic.
object UrlVerifier {
val count = new java.util.concurrent.atomic.AtomicInteger(0)
val baseUrl = Params.applicationBaseUrl
val accessUrl = repeat(Params.noOfPagesToBeVisited,"index") {
exec(session=> {
val randomUrls: List[String] = UrlFeeder.getUrlsToBeTested()
session.set("index", count.getAndIncrement).set("pageToTest", randomUrls(session("index").as[Int]))
}
).
exec(http("Accessing Page ${pageToTest}")
.get(baseUrl+"${pageToTest}")
.check(status.is(200))).pause(Params.timeToPauseInSeconds)
}
So basically UrlFeeder give me list of String (urls to be tested) and in the exec, we are using count (AtomicInteger), and using this we are populating a variable named 'index' whose value will start from 0 and will be getAndIncremented in each iteration. This 'index' variable is the one which will be used within repeat() loop as we are specifying the name of counterVariable to be used as 'index'
Hope it helps others as well.

Value is not an array ref error

I have a list of checkboxes. I am trying to pass the list of selected checkboxes to a perl script. I am obtaining the list of checkboxes using the folliwng code :
function exec(){
var checkedValue = "";
var inputElements = document.getElementsByTagName('input');
for(var i=0; inputElements[i]; i++){
if(inputElements[i].className==="chk" &&
inputElements[i].checked){
checkedValue += inputElements[i].value;
if (inputElements[i+1])
checkedValue += ", ";
else
checkedValue += "";
}
}
I am then passing "checkedValue" to a perl script as follows :
self.location='/cgi-bin/ATMRunJob.pl?tcs='+checkedValue;
In the perl script, I read the array as follows :
our #testCasesToRun = $var->param("tcs");
This is then assigned to a hash as follows :
my $runSpec = {
TestCasesToRun => #testCasesToRun
};
However, I get the following error when I load the page in the browser :
Failed TestLimits() with error: [hash: k=TestCasesToRun, v=1,]:[array]:Value is not an array ref
In check against following TLS:
[
'hr',
{
'OptDefaults' => {
'JobRunningGroupName' => 'astbluetooth',
'RunMode' => 'Queue',
'CountTowardsReporting' => 1,
'JobOwnerGroupName' => 'astbluetooth',
'SelectSetupTeardown' => 1
},
'Optional' => {
'TestCasesToRun' => [
'ar',
undef,
undef,
[
'r',
1,
undef
]
],
I am new to perl as well as CGI scripting. How could I get around this error?
NOTE : All the code snippets have been shortened for brevity, but still portray the essence of the problem.
EDIT : What I want to do is this. The user selects a list of test cases from a checkboxed list that he wants to execute. I take the test case ids of all the selected test cases and pass it to a perl script. In the perl script, I just need to assign these selected testcase ids to the TestCasesToRun element in the runspec hash.
What would be the correct way to do that?
You are assigning an array as a hashkey value. That doesn't work; you need to assign an array ref:
my $runSpec = {
TestCasesToRun => \#testCasesToRun
};
Given that the code compiles, I have a feeling you just messed up your examples in the Q - please fix them to accurately reflect your code, even if they will be slightly less brief.
Your 'tcs' parameter is a single string (assigned via JS). Why are you then assigning results of param('tcs') to an array in the first place? Do you have a split somewhere in your code that you didn't include into the example?
Your dump contains an array reference within an array reference. You need to elaborate on what the expected structure of TestCasesToRun arrayref is, and show the code which processes it in the test runner.
As per your last comment:
Change your JavaScript code to join using simple comma: checkedValue += ",";
Change your Perl assignment to: our #testCasesToRun = split(/,/, $var->param("tcs"));

Resources