Discussion:
Sharing arrays between threads.
Eric Olson
2012-02-10 03:07:51 UTC
Permalink
Hi,

I'm having a terrible time figuring out how to share an array of strings
between different parts of my test plan. The problem I'm trying to solve
is that i want to "log in" all of my users up front to get a big list of
tokens (using OAuth 2.0), and then when I move on to the actual load
testing section of my test plan, I can just have it randomly pick a token
from my array.

The way I've been trying to do it is:

-Define an array using a BSF preprocessor (via javascript) and add it to
vars (vars.putObject("myArray",
myArray);)
-In the auth thread group, parse the response using regular expressions
putting it into a temporary variable
-In the auth thread group, use a BSF postprocessor retrieve my previously
created array and add the temporary variable from the step above to the
array, and put it back in vars
-In my test thread group, which does not start running until my auth step
is completed, each thread randomly picks from the array defined at the test
plan level.

The problem I'm running into seems to be that there is some sort of scope
issue where the data added during the auth step is not available to the
test step - only what was predefined in the top-level preprocessor. Am I
doing this completely wrong, or what? Can Arrays not be shared? If so,
how do you use data gathered from one step in the next step?

Thanks,

Eric
Deepak Shetty
2012-02-10 03:13:29 UTC
Permalink
Hi
variables are scoped to the thread.
a. Use properties (but you'd have to represent the array as a delimited
string (also described in same link s step c)
b. Do you need randomness (or will sequential work) - if sequential works
then in a setup threadgroup write these values to a CSV , which is then
picked up by the next thread group using CSV data set config
c. use BSH shared namespace --
http://jmeter.apache.org/usermanual/best-practices - sharing variables

regards
deepak
Post by Eric Olson
Hi,
I'm having a terrible time figuring out how to share an array of strings
between different parts of my test plan. The problem I'm trying to solve
is that i want to "log in" all of my users up front to get a big list of
tokens (using OAuth 2.0), and then when I move on to the actual load
testing section of my test plan, I can just have it randomly pick a token
from my array.
-Define an array using a BSF preprocessor (via javascript) and add it to
vars (vars.putObject("myArray",
myArray);)
-In the auth thread group, parse the response using regular expressions
putting it into a temporary variable
-In the auth thread group, use a BSF postprocessor retrieve my previously
created array and add the temporary variable from the step above to the
array, and put it back in vars
-In my test thread group, which does not start running until my auth step
is completed, each thread randomly picks from the array defined at the test
plan level.
The problem I'm running into seems to be that there is some sort of scope
issue where the data added during the auth step is not available to the
test step - only what was predefined in the top-level preprocessor. Am I
doing this completely wrong, or what? Can Arrays not be shared? If so,
how do you use data gathered from one step in the next step?
Thanks,
Eric
Eric Olson
2012-02-10 03:50:39 UTC
Permalink
Thanks for the swift reply, Deepak.

I had a similar thought about the CSV thing, but I'm still running into the
issue of not being able to store the tokens long enough to even put them in
a CSV. I hadn't considered serializing the array into a string - that may
work for me as well.

As for the CSV thing, how would I store the values long enough to get them
into a CSV in the first place? It seems like solving that problem is the
same as solving my first problem, which is that I can't write multiple
values to the same shared place. Is there some sort of streaming CSV
writer that can append the values as I go? I think I may just be having a
hard time grasping the scopes here.

-Eric
Post by Deepak Shetty
Hi
variables are scoped to the thread.
a. Use properties (but you'd have to represent the array as a delimited
string (also described in same link s step c)
b. Do you need randomness (or will sequential work) - if sequential works
then in a setup threadgroup write these values to a CSV , which is then
picked up by the next thread group using CSV data set config
c. use BSH shared namespace --
http://jmeter.apache.org/usermanual/best-practices - sharing variables
regards
deepak
Post by Eric Olson
Hi,
I'm having a terrible time figuring out how to share an array of strings
between different parts of my test plan. The problem I'm trying to solve
is that i want to "log in" all of my users up front to get a big list of
tokens (using OAuth 2.0), and then when I move on to the actual load
testing section of my test plan, I can just have it randomly pick a token
from my array.
-Define an array using a BSF preprocessor (via javascript) and add it to
vars (vars.putObject("myArray",
myArray);)
-In the auth thread group, parse the response using regular expressions
putting it into a temporary variable
-In the auth thread group, use a BSF postprocessor retrieve my previously
created array and add the temporary variable from the step above to the
array, and put it back in vars
-In my test thread group, which does not start running until my auth step
is completed, each thread randomly picks from the array defined at the
test
Post by Eric Olson
plan level.
The problem I'm running into seems to be that there is some sort of scope
issue where the data added during the auth step is not available to the
test step - only what was predefined in the top-level preprocessor. Am I
doing this completely wrong, or what? Can Arrays not be shared? If so,
how do you use data gathered from one step in the next step?
Thanks,
Eric
Flavio Cysne
2012-02-10 10:50:30 UTC
Permalink
Eric,

Write a customized function to JMeter and manipulate a map of values inside
it.
Store it in JMeter properties scope.

Regards.
Flavio Cysne
Post by Eric Olson
Thanks for the swift reply, Deepak.
I had a similar thought about the CSV thing, but I'm still running into the
issue of not being able to store the tokens long enough to even put them in
a CSV. I hadn't considered serializing the array into a string - that may
work for me as well.
As for the CSV thing, how would I store the values long enough to get them
into a CSV in the first place? It seems like solving that problem is the
same as solving my first problem, which is that I can't write multiple
values to the same shared place. Is there some sort of streaming CSV
writer that can append the values as I go? I think I may just be having a
hard time grasping the scopes here.
-Eric
Post by Deepak Shetty
Hi
variables are scoped to the thread.
a. Use properties (but you'd have to represent the array as a delimited
string (also described in same link s step c)
b. Do you need randomness (or will sequential work) - if sequential works
then in a setup threadgroup write these values to a CSV , which is then
picked up by the next thread group using CSV data set config
c. use BSH shared namespace --
http://jmeter.apache.org/usermanual/best-practices - sharing variables
regards
deepak
Post by Eric Olson
Hi,
I'm having a terrible time figuring out how to share an array of
strings
Post by Deepak Shetty
Post by Eric Olson
between different parts of my test plan. The problem I'm trying to
solve
Post by Deepak Shetty
Post by Eric Olson
is that i want to "log in" all of my users up front to get a big list
of
Post by Deepak Shetty
Post by Eric Olson
tokens (using OAuth 2.0), and then when I move on to the actual load
testing section of my test plan, I can just have it randomly pick a
token
Post by Deepak Shetty
Post by Eric Olson
from my array.
-Define an array using a BSF preprocessor (via javascript) and add it
to
Post by Deepak Shetty
Post by Eric Olson
vars (vars.putObject("myArray",
myArray);)
-In the auth thread group, parse the response using regular expressions
putting it into a temporary variable
-In the auth thread group, use a BSF postprocessor retrieve my
previously
Post by Deepak Shetty
Post by Eric Olson
created array and add the temporary variable from the step above to the
array, and put it back in vars
-In my test thread group, which does not start running until my auth
step
Post by Deepak Shetty
Post by Eric Olson
is completed, each thread randomly picks from the array defined at the
test
Post by Eric Olson
plan level.
The problem I'm running into seems to be that there is some sort of
scope
Post by Deepak Shetty
Post by Eric Olson
issue where the data added during the auth step is not available to the
test step - only what was predefined in the top-level preprocessor.
Am I
Post by Deepak Shetty
Post by Eric Olson
doing this completely wrong, or what? Can Arrays not be shared? If
so,
Post by Deepak Shetty
Post by Eric Olson
how do you use data gathered from one step in the next step?
Thanks,
Eric
Bruce Ide
2012-02-10 16:26:16 UTC
Permalink
In the same thread you can use vars.putObject in a bsf or beanshell sampler
to store an array in a variable. Or you can just iteratively create a
jmeter array.

I wrote an addon to allow sharing across threads, see
https://github.com/FlyingRhenquest/JmeterThreadGlobal. It's a pretty simple
addon and isn't currently set up to share arbitrary objects, but it should
be easy to modify to do that.

If you used the new setup things you shouldn't have to synchronize between
the threads. If it turns out you need to, you can use a synchronizing timer
or my thread synchronization sampler (Which is also on github.)

All this does add quite a bit of complexity to the test though, so if
you're ever going to need to explain it to another tester you might want to
simplify your test design.
--
Bruce Ide
***@gmail.com
sebb
2012-02-10 16:50:52 UTC
Permalink
Post by Bruce Ide
In the same thread you can use vars.putObject in a bsf or beanshell sampler
to store an array in a variable. Or you can just iteratively create a
jmeter array.
I wrote an addon to allow sharing across threads, see
https://github.com/FlyingRhenquest/JmeterThreadGlobal. It's a pretty simple
addon and isn't currently set up to share arbitrary objects, but it should
be easy to modify to do that.
If you used the new setup things you shouldn't have to synchronize between
the threads. If it turns out you need to, you can use a synchronizing timer
or my thread synchronization sampler (Which is also on github.)
All this does add quite a bit of complexity to the test though, so if
you're ever going to need to explain it to another tester you might want to
simplify your test design.
Very good point.

Why not create CSV data files containing the tokens in a separate test phase?
You can then randomise the data file if you want.

By the way, you say each thread picks a random token.
If you have multiple threads, a simple random choice will sometimes
result in two threads having the same token.
Is that allowed? If not, the token entries will have to be marked as
used; this will necessarily entail synchronising across threads.

The CSV data file can be set to only be used once; threads cannot then
get the same token (unless it is duplicated in the file).

If you have hundreds or thousands of tokens, using a data file is the way to go.
Post by Bruce Ide
--
Bruce Ide
Eric Olson
2012-02-10 17:09:12 UTC
Permalink
It's alright if two threads share a token, in fact it's probably preferable
for that to be part of my test since I'd expect to see that from real users.

I still don't see how I can write to a CSV, however. I was able to get it
to write 1 CSV file per token, but I'm not really interested in having my
folder get filled up with numbered csv files. I was hoping to have it all
in one CSV.

As for sharing within a thread, this still isn't working for me, so I guess
that's what I need help with. Here's how my setup looks.

ThreadGroup
-BSF PreProcessor or Sampler (javascript) -> var myArray = new Array();
vars.putObject("myArray",myArray);
-Loop Controller -> 5 loops
--HTTP Sampler
---Regex postprocessor -> Reference Name = myToken
---BSF postprocessor - > var myArray = vars.getOject("myArray");
myArray.push(myToken); vars.putObject("myArray",myArray);
-BSF Sampler -> var myArray = vars.getObject("myArray"); //At this point,
I expect myArray.length to be 5. Instead it is 0.

Right now I'm taking the approach of serializing into a comma
delimitted string and storing it in props, but that just feels wrong to me.

Sebb, when you say "iteratively create a jmeter array", what do you mean?
Is there some other data structure that I'm completely missing? I thought
the only way you could get a jmeter array was if your single regular
expression returned multiple matching groups... rather than having multiple
runs of a thread or a loop add on to an existing array. If there's some
way to do that, I would love to know.

-Eric
Post by Bruce Ide
Post by Bruce Ide
In the same thread you can use vars.putObject in a bsf or beanshell
sampler
Post by Bruce Ide
to store an array in a variable. Or you can just iteratively create a
jmeter array.
I wrote an addon to allow sharing across threads, see
https://github.com/FlyingRhenquest/JmeterThreadGlobal. It's a pretty
simple
Post by Bruce Ide
addon and isn't currently set up to share arbitrary objects, but it
should
Post by Bruce Ide
be easy to modify to do that.
If you used the new setup things you shouldn't have to synchronize
between
Post by Bruce Ide
the threads. If it turns out you need to, you can use a synchronizing
timer
Post by Bruce Ide
or my thread synchronization sampler (Which is also on github.)
All this does add quite a bit of complexity to the test though, so if
you're ever going to need to explain it to another tester you might want
to
Post by Bruce Ide
simplify your test design.
Very good point.
Why not create CSV data files containing the tokens in a separate test phase?
You can then randomise the data file if you want.
By the way, you say each thread picks a random token.
If you have multiple threads, a simple random choice will sometimes
result in two threads having the same token.
Is that allowed? If not, the token entries will have to be marked as
used; this will necessarily entail synchronising across threads.
The CSV data file can be set to only be used once; threads cannot then
get the same token (unless it is duplicated in the file).
If you have hundreds or thousands of tokens, using a data file is the way to go.
Post by Bruce Ide
--
Bruce Ide
---------------------------------------------------------------------
Bruce Ide
2012-02-10 17:42:07 UTC
Permalink
Jmeter variables are essentially just key/value pairs stored in a big hash
table. There's nothing magical about arrays in jmeter, they just get a
_number extension on them. You can very easily write one of these with a
BSF sampler You just need to keep in mind that they start at one.

int i;
for(i = 1; i < 42; ++i) {
vars.put("myarray_" + Integer.toString(i), Integer.toString(i));
}
vars.put("myArray_#", Integer.toString(i));

That's off the top of my head so please forgive me if it has syntax errors.
You can read them in the same way.

Since Jmeter variables are this way, the Object you stored in the Jmeter
variable is a reference. Therefore, you should not ever need to put it
again after you store it the first time. Just get the object in your BSF
sampler and push values into it and the array in vars will change.

That being said, I honestly don't see why your test doesn't work. It looks
to me like it should. There' s no harm in re-putting the array reference.

You can also open a File and write a comma delimited file from within the
BSF sampler. I prefer to use groovy in my BSF samplers, but I write my
files like a Java programmer because I'm not entirely comfortable with
everything that Groovy does. It's atrocious (my code, not groovy.) Just
google on opening and writing files with whatever language you're using. It
should put the file in your current test directory, if I recall correctly.
--
Bruce Ide
***@gmail.com
sebb
2012-02-10 17:50:16 UTC
Permalink
Post by Eric Olson
It's alright if two threads share a token, in fact it's probably preferable
for that to be part of my test since I'd expect to see that from real users.
If you say so - seems odd to me.
How can you tell the sessions apart?

Would a real user login to the service through two separate browsers at once?
Post by Eric Olson
I still don't see how I can write to a CSV, however.  I was able to get it
to write 1 CSV file per token, but I'm not really interested in having my
folder get filled up with numbered csv files.  I was hoping to have it all
in one CSV.
Use RE extractor (or similar) to put the token in a fixed named
variable, and save it to the CSV file:

http://jakarta.apache.org/jmeter/usermanual/listeners.html#sample_variables

You can configure the listener to skip just about everything else in
the sample result.

You may need to run this as a separate test in order to ensure that
the file is closed.
Post by Eric Olson
As for sharing within a thread, this still isn't working for me, so I guess
that's what I need help with.  Here's how my setup looks.
ThreadGroup
-BSF PreProcessor or Sampler (javascript) -> var myArray = new Array();
vars.putObject("myArray",myArray);
-Loop Controller -> 5 loops
--HTTP Sampler
---Regex postprocessor -> Reference Name = myToken
---BSF postprocessor - > var myArray = vars.getOject("myArray");
myArray.push(myToken);  vars.putObject("myArray",myArray);
-BSF Sampler -> var myArray = vars.getObject("myArray");  //At this point,
I expect myArray.length to be 5.  Instead it is 0.
BSF interpreters are not shared between samplers (or threads), but
they should be able to see a variable created earlier in the same
thread.
Post by Eric Olson
Right now I'm taking the approach of serializing into a comma
delimitted string and storing it in props, but that just feels wrong to me.
OK to use properties if you want to share read-only information across
threads; props are not really suitable for frequently updated values.
Post by Eric Olson
Sebb, when you say "iteratively create a jmeter array", what do you mean?
Not guilty.
Post by Eric Olson
Is there some other data structure that I'm completely missing?  I thought
the only way you could get a jmeter array was if your single regular
expression returned multiple matching groups...
That does not generate an array; just lots of variables with numeric suffixes.
Post by Eric Olson
rather than having multiple
runs of a thread or a loop add on to an existing array.  If there's some
way to do that, I would love to know.
Use a pre-populated CSV data set.
Post by Eric Olson
-Eric
Post by Bruce Ide
Post by Bruce Ide
In the same thread you can use vars.putObject in a bsf or beanshell
sampler
Post by Bruce Ide
to store an array in a variable. Or you can just iteratively create a
jmeter array.
I wrote an addon to allow sharing across threads, see
https://github.com/FlyingRhenquest/JmeterThreadGlobal. It's a pretty
simple
Post by Bruce Ide
addon and isn't currently set up to share arbitrary objects, but it
should
Post by Bruce Ide
be easy to modify to do that.
If you used the new setup things you shouldn't have to synchronize
between
Post by Bruce Ide
the threads. If it turns out you need to, you can use a synchronizing
timer
Post by Bruce Ide
or my thread synchronization sampler (Which is also on github.)
All this does add quite a bit of complexity to the test though, so if
you're ever going to need to explain it to another tester you might want
to
Post by Bruce Ide
simplify your test design.
Very good point.
Why not create CSV data files containing the tokens in a separate test phase?
You can then randomise the data file if you want.
By the way, you say each thread picks a random token.
If you have multiple threads, a simple random choice will sometimes
result in two threads having the same token.
Is that allowed? If not, the token entries will have to be marked as
used; this will necessarily entail synchronising across threads.
The CSV data file can be set to only be used once; threads cannot then
get the same token (unless it is duplicated in the file).
If you have hundreds or thousands of tokens, using a data file is the way to go.
Post by Bruce Ide
--
Bruce Ide
---------------------------------------------------------------------
Loading...