Substring variable and loop some of the checks

Hello!

I need help to create loop for my more complex tests.
I have account list, where every account have unique ID.
I want to collect it all in one list and then loop for each account.

All ID contains letters and numbers, like AZV9727. But I need cut from ID only digits.

The XML with data I receive looks like


AZV9727
5123


AFV9727
4123


DKF9727
5223

I wrote following code:
.check(
xpath("//account[starts-with(producttypeid/text(), ‘51’) or starts-with(producttypeid/text(), ‘52’)]/accountid")
.findAll
.saveAs(“loan_id”)
)

For each accountid selected by xpath I need to make get request to the url https://mysite/accounts/account_info?id={accountid.substring(3)}.
For example for the first account the url should be https://mysite/accounts/account_info?id=9727

So I have two questions:

  1. How to get a substring in Scala to exclude first letters and save as “loan_id” only numbers?

  2. Second question is, how to loop by received ID.
    I have three requests for each account. And for each of this requests I need to use one ID. Is it possible?
    Sorry for my question, but I still very newbie in scala…

val request_loans_info = execWithStdChecks(http(“Loans info”)
.get("/accounts/account_info")
.queryParam(""“id”"", “${loan_id}”)
)

val request_loans_payment_shedule = execWithStdChecks(http(“Payment Schedule for Loan”)

.get("/accounts/account_schedule")

.queryParam(""“id”"", “${loan_id}”)

)

val request_loans_collaterals = execWithStdChecks(http(“Loan collateral’s”)

.get("/accounts/account__collaterals")

.queryParam(""“id”"", “${loan_id}”)

)

Thank You in advance!
Natalja

  1. You probably want to add a transform step to your xpath check that does the substring: https://github.com/excilys/gatling/wiki/Checks#wiki-transforming

Here, you have a findAll that returns a Seq[String], so you want .tranform(.map(.substring(3))

  1. You need the foreach loop: https://github.com/excilys/gatling/wiki/Structure-Elements#wiki-foreach

Basically:

.repeat(“loan_ids”, “loan_id”) { // assuming the xpath check output has been saved as loan_ids, expose in the session the current element as loan_id


}

Cheers,

Stéphane

Thank You for really quick answer!

I rewright the code, as You suggested, but when I try to compile it I receive:

AccountsCheck.scala:110: value tranform is not a member of io.gatling.core.check.MatcherCheckBuilder[io.gatling.http.check.HttpCheck,io.gatling.http.response.Response,Option[org.w3c.dom.Document],String,Seq[String]]
possible cause: maybe a semicolon is missing before `value tranform’?

14:49:57.677 [ERROR] i.g.a.ZincCompiler$ - .tranform(.map(.substring(3)))

14:49:57.679 [ERROR] i.g.a.ZincCompiler$ - ^

14:49:58.628 [ERROR] i.g.a.ZincCompiler$ - one error found

my new code is:

val request_loans_list = execWithStdChecks(http(“Loans list”)
.post("/accounts/accounts-list")
.check(
xpath("//account[starts-with(producttypeid/text(), ‘51’) or starts-with(producttypeid/text(), ‘52’)]/accountid")
.findAll
.tranform(.map(.substring(3)))
.saveAs(“loan_ids”)
)

typo: transform

Sorry, IDEA didn’t properly work with Scala
I correct mistake, but still receive an error…

15:31:10.757 [ERROR] i.g.a.ZincCompiler$ - value substring is not a member of Seq[String]
15:31:10.759 [ERROR] i.g.a.ZincCompiler$ - .transform(.map(.substring(3)))
15:31:10.759 [ERROR] i.g.a.ZincCompiler$ - ^
15:31:11.268 [ERROR] i.g.a.ZincCompiler$ - one errors found
Press any key to continue . . .

Ah, you’re using Gatling 2! The transform signature has changed.

transform(.map(.map(_.substring(3))))

which is a shortcut for:

transform(optionalSeq => optionalSeq.map(seq => seq.map(id => id.substring(3))))

Sorry! I have to mention it

So, my code compile, but I receive error when on the step, whereon i try to collect ID’s
My code for this step is:
val request_loans_list = execWithStdChecks(http(“Loans list”)
.post(“/accounts/accounts-list.xml”)
.check(
xpath(“//account[starts-with(producttypeid/text(), ‘51’) or starts-with(producttypeid/text(), ‘52’)]/accountid”)
.findAll
.transform(.map(.map(_.substring(3))))
.saveAs(“loan_ids”)
)
)

<<<<<<<<<<<<<<<<<<<<<<<<<
15:52:35.646 [INFO ] i.g.h.a.HttpRequestAction - Sending request ‘Loans list’: scenario ‘Loans Check’, userId #0
15:52:36.381 [TRACE] i.g.h.a.GatlingAsyncHandlerActor -

request was:
POST http://mysite/accounts/accounts-list.xml
headers=
Connection: [Keep-Alive]
Content-Length: [0]
Accept: [/]
Accept-Language: [en-us]
Accept-Encoding: [gzip, deflate]
User-Agent: [Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)]
cookies=

response was:
status=
200 OK
headers=
Cache-Control: [no-cache]
Connection: [close]
Content-Type: [text/html;charset=UTF-8]
Date: [Tue, 14 May 2013 12:52:37 GMT]
Expires: [Mon, 14 Feb 1998 14:25:59 GMT]
Server: [Microsoft-IIS/7.5]

body=

[all accounts info]

15:52:36.391 [ERROR] i.g.c.a.InnerWhile - While condition evaluation failed: Can’t cast value loan_ids of type class java.lang.String into int, exiting loop
15:52:36.889 [INFO ] i.g.h.a.HttpRequestAction - Sending request ‘Logout request’: scenario ‘Loans Check’, userId #0

Can I have a look at your loop?

My code for loop is:

val request_loans_list = execWithStdChecks(http(“Loans list”)
.post("/accounts/accounts-list.xml")
.headers(headers_Content_Length_0)
.check(
xpath("//account[starts-with(producttypeid/text(), ‘51’) or starts-with(producttypeid/text(), ‘52’)]/accountid")
.findAll
.transform(.map(.map(_.substring(3))))
.saveAs(“loan_ids”)
)
)

val request_loans_info = execWithStdChecks(http(“Loans info”)
.get("/accounts/accounts_xml.xml")
.queryParam(""“id”"", “${loan_id}”)
)

val request_loans_payment_schedule = execWithStdChecks(http(“Payment Schedule for Loan”)
.get("/accounts/accounts_schedule.xml")
.queryParam(""“id”"", “${loan_id}”)
)

val request_loans_collaterals = execWithStdChecks(http(“Loan collateral’s”)
.get("/accounts/accounts_collaterals.xml")
.queryParam(""“id”"", “${loan_id}”)
)

val request_all_loan_info = repeat(“loan_ids”, “loan_id”){
exec(request_loans_info)
.pause(150 milliseconds)
.exec(request_loans_payment_schedule)
.pause(150 milliseconds)
.exec(request_loans_collaterals)
}

val chain_loans = exec(request_loans_list)
.pause(300 milliseconds)
.exec(request_all_loan_info)

Ah, sorry, typo again:

  1. You need the foreach loop: https://github.com/excilys/gatling/wiki/Structure-Elements#wiki-foreach

Basically:

. foreach(“loan_ids”, “loan_id”) { // assuming the xpath check output has been saved as loan_ids, expose in the session the current element as loan_id


}

Sorry, same error…
May this error appear because IDs i receive as node, not a string?

<<<<<<<<<<<<<<<<<<<<<<<<<
17:16:00.224 [ERROR] i.g.c.a.InnerWhile - While condition evaluation failed: Can’t cast value loan_ids of type class java.lang.String into interface scala.collection.Seq, exiting loop
17:16:00.754 [INFO ] i.g.h.a.HttpRequestAction - Sending request ‘Logout request’: scenario ‘Loans Check’, userId #0
17:16:01.014 [TRACE] i.g.h.a.GatlingAsyncHandlerActor -

Sorry again, I keep on forgetting that you use Gatling 2.
In Gatling 2, we have made things more homogeneous, so foreach first parameter is an Expression, not the name of the attribute, meaning that you have to write “${loan_ids}” instead of “loan_ids”.

Note that this is mentioned in the Gatling 2 WIP guide: https://github.com/excilys/gatling/wiki/Gatling-2#wiki-core-misc

Thank a lot!
Now loop work perfectly!

Natalja

Sorry it took so long…

Stéphane, You help me a lot…