I'm using JMeter 3.2 to create some performance tests.
I have a set up where a thread group has multiple threads (users) which perform multiple loops requesting a resource, form a server, every time.
Each of the threads go through an once only controller which retrieves a token from a server, which identifies the user, and is required on all subsequent requests. The token is different every time it is generated, I cannot store it in a data set (csv) as it would later be invalid.
I have a data set (.csv file) containing username and password of my test users.
So far so good.. Now the threads need to request a resource on the server requiring the token to be sent. It goes well the first time, but the second time it starts messing up. It seems like each iteration uses data from the next row in the dataset, but the token retrieved (from the once only controller) is not linked to row of data (username and password) used, so something like this happens:
thread1: data1/token1 - good
thread2: data2/token2 - good
Perhaps thread2 finishes first and starts the new iteration:
thread2: data1/token2 - error
thread1: data2/token1 - error
So my question is: how can I link the token retrieved to a row in data set (as a variable), so that the correct token will be sent every time that piece of data is used for a request?
Edit
I have an idea. Creating a Hashtable with some data, from the data set, as key and the token as value, but I have some issue. I've created the following code:
import java.util.Hashtable;
map = new Hashtable();
vars.putObject("map", map);
but it cast the following error:
java.util.Hashtable cannot be cast to java.lang.String
I finally figured it out, though it might not be the most optimal solution. What I did is to create a property (variables won't work), which is a JSONObject. In this I can store an id (for my data) and the token linked to it. I transform it to a string and store it in the property.
In a preprocessor to the http request requiring the token I retrieve the property and parses it back to a JSONObject and can look up the token using the id.
Related
The documentation (https://hexdocs.pm/plug/Plug.Conn.html) names two functions that allow for storing a key-value pair in a conn
assign(conn, key, value)
Assigns a value to a key in the connection
put_session(conn, key, value)
Puts the specified value in the session for the given key
What is the difference between these two functions?
Basically assign works only for particular connection - Plug.Conn structure - which means that this value would be gone with the end of the request - as conn will also dies - at the end of the request / response cycle.
Session lives longer and it's stored in cookies or in ets. Thanks to that you keep eg. data about the successfully logged in user across the requests.
TL;DR:
assign works for each request and it's wipe out after the end of the request cycle.
put_session inserts a value in the session and it's available until the session is cleared / expired.
We have a service that works the following way:
First, a request with search parameters is sent, for which we get back a searchId. This searchId is then used to continue fetching information until service response it has no more data left (hasMore parameter becomes "false").
The question is this - I have set up jMeter to send first requests, but not certain how then to keep sending requests in parallel for each response in the Thread Group, and need your advice on it. My thought was to set up another Thread Group since I cannot set it inside the first one, but then how do I get access to responses and process them in parallel?
EDITED:
This is what I ended up with. First Beanshell Sampler extracts searchId and hasMore and puts it into vars. Second Sampler extracts hasMore and again puts it into vars, overwriting the first. At the end, the While loop worked as intended, using ${__javaScript("${hasMore}" == "1",)}.
I would recommend designing your test as follows:
Request to get searchId
While Controller with condition like ${__javaScript("${hasMore}" != "false",)}
Request to continue to fetch information
PostProcessor to extract hasMore parameter and store it into the relevant JMeter Variable
This way "fetch information" requests will be executing until hasMore parameter becomes false. See Using the While Controller in JMeter article for more details.
I suggest 2 Thread group
First Thread group:
Save searchIds in file (JSR223 Sampler) or database (JDBC Sampler) with key as counter (1,2,...) and value as the searchId value
Save a number of IDs in property ${__setProperty(threadCount,${counter})}.
Second Thread group:
In definition - Number of thread use ${__P(threadCount)}
Read from file (JSR223 Sampler) or database (JDBC Sampler)
using ${__threadNum} as key get the relevant searchId you need
I've got a jmeter script to test a user journey through a number of forms.
Ideally the email address for each journey would be unique but it's proven difficult to achieve this.
I have a user defined variable for email;
${__V(${__UUID()}${__RandomString(20,abcdefghijklmnopqrstuvwxyz,)}_jmeter#my-co.com)}
Then a BeanShell PreProcessor to create a uniqueID;
int threadNo = ctx.getThreadNum()+1; //to get the thread number in beanshell
int base = 35000;
int uniqueId = threadNo + base;
vars.put("uniqueId", Integer.toString(uniqueId));
Finally, in the POST data I've been defining;
_${__threadNum}.${uniqueId}.${Email}
However if I want to run a long test, the threads loop so I believe the thread number is the same, so the email doesn't change. Or at least the 403 errors seen during longer tests suggest that.
Can the loop count or some other identifier be used on the uniqueId or in the data for the POST perhaps?
You can use the following:
vars.getIteration() - to get current loop number (on Thread Group level)
Counter element or even better ${__counter(FALSE,)} function which will generate incremented number each time being called. See How to Use a Counter in a JMeter Test for details.
However HTTP Status Code 403 stands for "Forbidden"
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
If the request method was not HEAD and the server wishes to make
public why the request has not been fulfilled, it SHOULD describe the
reason for the refusal in the entity. If the server does not wish to
make this information available to the client, the status code 404
(Not Found) can be used instead.
so your problem seems to be connected with something else
I'm having a problem associating a browser_id to a session when using Products.BeakerSessionDataManager. I'm working on Plone 5.
As far as I understand Zope sessions, as soon as .getSessionData() is called on a session data manager, a session data container is created if it did not exist. Furthermore, this data will contain a token, which is the same as the browser_id associated with the browser making the request. And finally, a cookie is set on the response with the name _ZopeId (and the value is the same as the token). Thus, when I use the default session data manager that come with Zope, I get this:
ipdb> context.session_data_manager.getSessionData()
id: 14737473151418102847, token: 38878600A7nh90DE9ao, content keys: []
However, when I use Products.BeakerSessionDataManager, the same call gives me this:
ipdb> context.session_data_manager.getSessionData()
{'_accessed_time': 1473745441.437582, '_creation_time': 1473745441.437582}
Moreover, no cookie is set.
Perusing some old Zope docs, I found a reference to getContainerKey(), so I thought that might get me the browser_id. However, the returned value is different on every request, so that does not work. Also, calling .getBrowserIdManager().getBrowserId() on the session_data_manager throws an error, because Beaker does not support browser id managers.
I want to set a cookie, and I want a token. I'm doing this so that I can identify anonymous clients in a voting application, so that they will not cast multiple votes (at least not in the same session - there are other mechanisms to allow voting only when certain other conditions are met).
Am I misunderstanding the machinery, or am I missing something?
I am having a problem with my application. I am creating two session variables on a button click event, and then re-directing to another page and executing a method that selects data from a database (using the two session variables as parameters), and then displaying the results in a grid.
All works fine until I have two users (or more), who access the application, set their own session values, execute the data retrieval method, and of course they expect to see their own data.
What ends up occurring, is that both users see the same data, not their own specific data. Essentially, User A sees his data fine, but User B ends up seeing User A's data - not his own.
Note: this only occurs when they attempt to access their specific data 20 seconds apart
Here is my code sample:
//The user control that sets the session variables and redirects
Session.Clear();
Session.["ID"] = TxtPatientIDCode.Text.ToString());
Session["DOB"] = Convert.ToDateTime(TxtDateOfBirth.SelectedDate.Value.ToShortDateString());
Response.Redirect("mypage");
// the user control that gets the session variable values and executes //the data method
if (Session["ID"].ToString() != null)
{
SelectData();
}
Ammended
This is what occurs on the SelectData() method:
private void SelectData()
{
DataSet ds = Data.GetData(Session["ID"].ToString(),Session["DOB"].ToString());
gv.DataSource = ds;
gv.DataBind();
}
Also I did log this to a database table and it is inserting just fine, as it shows who and what times the data is accessed, as well as the session values that are being used.
Thanks again for the help
technooblet