Jmeter - can't pass property to JDBC connector - properties

I have a setUp thread Group and a normal thread Group. Jmeter runs the thread groups consecutively.
Into the setup group I select a username from a database and I put that into a property with a JSR223 sampler like this:
import org.apache.jmeter.util.JMeterUtils;
JMeterUtils.setProperty("schemaProp", vars.get("schemaVar_1"));
Into the second thread I have a JDBC Connector which access the property like this:
${__property(sshUserProp,)}
But It doesn't work.
LOG:
2021-12-16 08:54:58,802 DEBUG o.a.j.p.j.c.DataSourceElement: Driver: org.postgresql.Driver DbUrl: jdbc:postgresql://127.0.0.1:50539/JB7 User: sshUserProp
The JDBC Connector doesn't really see the property, although it is actually set, cause I can access it with another JSR223 sampler:
import org.apache.jmeter.util.JMeterUtils;
log.info ("------------------------- MESSAGE: " + JMeterUtils.getProperty("sshUserProp"))
LOG:
2021-12-16 08:54:58,961 INFO o.a.j.p.j.s.J.JSR223 Sampler: ------------------------- MESSAGE: 160116

I'm afraid it's not possible, at least not with JMeter 5.4.1, looking into JDBC Connection Configuration source code the element is being set up in the testStarted() function and according to the JavaDoc
Called just before the start of the test from the main engine thread. This is before the test elements are cloned. Note that not all the test variables will have been set up at this point.
So you need to determine the user name beforehand somewhere somehow, i.e. by running another JMeter test and saving the username(s) into a file via Flexible File Writer and then readine the username from the file using __StringFromFile() function or pass the username via -J command-line argument - this way your current approach with __property() function will work.

Related

Jmeter Beanshell: Accessing global lists of data

I'm using Jmeter to design a test that requires data to be randomly read from text files. To save memory, I have set up a "setUp Thread Group" with a BeanShell PreProcessor with the following:
//Imports
import org.apache.commons.io.FileUtils;
//Read data files
List items = FileUtils.readLines(new File(vars.get("DataFolder") + "/items.txt"));
//Store for future use
props.put("items", items);
I then attempt to read this in my other thread groups and am trying to access a random line in my text files with something like this:
(props.get("items")).get(new Random().nextInt((props.get("items")).size()))
However, this throws a "Typed variable declaration" error and I think it's because the get() method returns an object and I'm trying to invoke size() on it, since it's really a List. I'm not sure what to do here. My ultimate goal is to define some lists of data once to be used globally in my test so my tests don't have to store this data themselves.
Does anyone have any thoughts as to what might be wrong?
EDIT
I've also tried defining the variables in the setUp thread group as follows:
bsh.shared.items = items;
And then using them as this:
(bsh.shared.items).get(new Random().nextInt((bsh.shared.items).size()))
But that fails with the error "Method size() not found in class'bsh.Primitive'".
You were very close, just add casting to List so the interpreter will know what's the expected object:
log.info(((List)props.get("items")).get(new Random().nextInt((props.get("items")).size())));
Be aware that since JMeter 3.1 it is recommended to use Groovy for any form of scripting as:
Groovy performance is much better
Groovy supports more modern Java features while with Beanshell you're stuck at Java 5 level
Groovy has a plenty of JDK enhancements, i.e. File.readLines() function
So kindly find Groovy solution below:
In the first Thread Group:
props.put('items', new File(vars.get('DataFolder') + '/items.txt').readLines()
In the second Thread Group:
def items = props.get('items')
def randomLine = items.get(new Random().nextInt(items.size))

rundeck config value in one of the options inside job using api

I have rundeck 2.6.11 and I'm trying to config value in one of the options inside job using api
I already have valit token and I can perform get uri requests
for example:
curl --noproxy -x GET http://rundeck.domain.com:4440/api/18/projects?authtoken=##########
And I can get the data
But I couldn't find any option to set the value to one of the options in a job
I also tried this kb http://rundeck.org/docs/api/ but I didn't find a solution for my case
any idea?
Rundeck API doesn't have direct implementation for update job options, but you can update a job by updating the job definition file.
Export the job definition via
GET /api/1/job/[ID]
You can specify format=xml or format=yaml
Rundeck - Exporting Jobs
Update the option in the job definition using your preferred programming language.
Import the job definition you've updated via
POST /api/1/project/[PROJECT]/jobs/import
By default the uuidOption is set to preserve, which means you are updating an existing with same UUID
Rundeck - Importing Jobs

Saving a max value of counter to file in JMeter

I'm using a SOAP/XML-RPC Request to test a WSDL. Additionally I created a Counter element for this request. Each call of one of the functions has to contain other value in one of parameters.
Is there any possibility to save the maximum counter value to the file?
So when I start test, the value will be loaded from the file and increase by the counter.
At the end, this max value will be again saved to this file. And so on, so on...
Let's drop the built-in Counter and pass around the thread safe AtomicInteger.
Add a setUp Thread Group with a JSR223 Sampler (choose groovy as a scripting language) to your test plan. We will use it to read the value from the file. This thread group will be executed before all other thread groups and will provide us with the initial value.
Add the following code to the sampler:
import java.util.concurrent.atomic.AtomicInteger
counter = new File($/C:\Path\ToFile\fileName.txt/$).text
ai = new AtomicInteger(Integer.valueOf(counter))
props.put("sharedAtomicInteger", ai)
Then add another JSR223 Sampler after SOAP/XML-RPC Request in your regular Thread Group.
Add the following code to the sampler:
ai = props.get("sharedAtomicInteger")
variable = ai.incrementAndGet()
vars.put("variable", Integer.toString(variable))
Now the value of the improvised counter is stored in a variable and can be used in other requests issued by this thread.
Add a tearDown Thread Group with a JSR223 Sampler to your test plan. This thread group will be executed after all other thread groups and will write the maximum value to the file.
Add the following code to the sampler:
ai = props.get("sharedAtomicInteger")
new File($/C:\Path\ToFile\fileName.txt/$).write(ai.toString())
Finally, your test plan should look like this:
setUp Thread Group
JSR223 Sampler
Regular Thread Group
SOAP/XML-RPC Request
JSR223 Sampler
tearDown Thread Group
JSR223 Sampler
P.S.
Bear in mind that for brevity's sake I used the put() method of java.util.Properties class which is discouraged in the documentation.
To save value into a file (assumes a JSR223 Element and Groovy language)
new File("value.txt").text = vars.get("foo")
To read the value from file (assumes __FileToString() function)
${__FileToString(value.txt,,)}
I used tips from the first comment and do it in the following way:
transfer - Simple Controller
reading transactionId - JSR223 PreProcessor
transfer - SOAPXML-RPC Request
saving transactionId - JSR223 PostProcessor
JSR223 PreProcessor
Script language: groovy
import java.util.concurrent.atomic.AtomicInteger;
initial = new File("${absolute_path}transactionid.txt").text;
initial = initial.trim();
ai = new AtomicInteger(Integer.valueOf(initial));
transactionId = ai.incrementAndGet();
vars.put("transactionId", Integer.toString(transactionId));
SOAPXML-RPC Request
Here I'm using transactionId as one of the parameters in the SOAP Request.
JSR223 PostProcessor
Script language: groovy
transactionId = vars.get("transactionId");
new File("${absolute_path}transactionid.txt").write(transactionId.toString());
${absolute_path} is a variable defined in test plan as:
${__BeanShell(import org.apache.jmeter.services.FileServer; FileServer.getFileServer().getBaseDir();)}${__BeanShell(File.separator,)}
It is a path to folder with this JMeter project. This folder also contains file which is read to this test case.

How to apply connection settings to all JDBC test steps in SoapUI?

tl;dr
After (manually) having updated the JDBC connection properties of a single SoapUI test step,
how can I copy them to the other test steps in the project (without resorting to ${property} expansion)?
I suppose Groovy is the key?
Background
I have a SoapUI Project containing many JDBC test steps pointing to my development database like that:
The Open source version of JDBC TestStep has fields for setting the
connection properties and the SQL query manually.
Getting Started | JDBC (SoapUI.org)
Constraint: I am currently working without having the Connections feature from Smartbear's Pro version available.
Goal
Before deploying, I want to run the same tests in our staging environment i.e. I have to change JDBC connection settings throughout the test suite(s).
Preliminary considerations:
In order to re-direct all JDBC steps to the staging database I could edit my tests to connection string and driver fields relying on property expansion like described in SOAPUI ability to switch between database connections for test suite.
Specific approach:
However in this case here, I need to see the connection strings and drivers directly on the test steps (in contrast to seeing just the ${expansion} variables) – Rationale: it gives more useful screenshots with the real values ...
The connection properties can be copied from one test step to other JDBC test steps in the project using the following Groovy script:
// Select "correctly configured" JDBC TestStep/Case/Suite to be used as reference
def s = testRunner.testCase
.testSuite
.project
.testSuites["Reference TestSuite"]
.testCases["Reference TestCase"].getTestStepAt(1)
log.info "${s.getConnectionString()}, ${s.getDriver()}"
// Use s to configure all JDBC TestSteps in current TestSuite
testRunner.testCase
.testSuite
.testCases
.each{iTC, testCase ->
//log.debug "${iTC}: ${testCase}"
testCase.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.JdbcRequestTestStep)
.each{testStep ->
testStep.setConnectionString(s.getConnectionString())
testStep.setDriver(s.getDriver())
log.info "${testStep.getConnectionString()}, ${testStep.getDriver()}"
}
}
To run this, I have introduced an additional test suite internal TS and test case internal TC, respectively. I have added a Groovy TestStep copyJdbcSettings with above script to internal TC and executed it once.
I have then disabled internal TS until I need it again someday.

BeanShell PreProcessor updates User define variables

I'm very new at JMeter issues.
In a test script i have a BeanShell PreProcessor element that updates some variables previously defined at a "User Defined Variables" element.
Latter those variables are used in "Http Requests". However, the value that is used in the http request is the default one.
The scripts seems to be working due to some debug print();
My question is if it's necessary to delay the script to be sure that the BeanShell finishes?
Thanks a lot for your attention
There is no need to put any delay to Beanshell Pre-Processor as it's being executed before request. I'd recommend to check your jmeter.log file to see if there are any scripting issues as Beanshell Pre-Processor does not report errors anywhere including View Results Tree listener.
There are at least 2 ways to assure that everything is fine with your Beanshell script:
Put your debug print code after variables replace logic to see if it fires
Use JMeter __Beahshell function right in your HTTP request. If it's ok - View Results Tree will demonstrate beanshell-generated value. If not - the field will be blank and relevant error will be displayed in the log.
Example test case:
Given following Test Plan structure:
Thread Group with 1 user and 1 loop
HTTP GET Request to google.com with path of / and parameter q
If you provide as parameter "q" following beanshell function:
${__BeanShell(System.currentTimeMillis())}
and look into View Results Tree "Request" tab you should see something like:
GET http://www.google.com/?q=1385206045832
and if you change function to something incorrect like:
${__BeanShell(Something.incorrect())}
you'll see a blank request.
The correct way of changing existing variable (or creating new if variable doesn't exist) looks like
vars.put("variablename", "variablevalue");
*Important: * JMeter Variables are Java Strings, if you're trying to set something else (date, integer, whatever) to JMeter Variable you need to cast it to String somehow.
Example:
int i = 5;
vars.put("int_i", String.valueOf(i));
Hope this helps.
You can update the vale of a "user defined variable".
You have to create a bean shell sampler
vars.put("user_defined_variable", "newvalue");
#theINtoy got it right.
http://www.blazemeter.com/blog/queen-jmeters-built-componentshow-use-beanshell
I'm new to jmeter too but as I know variables defined in "User defined variables" are constants, so you can't change them. I recommend to use "User Parameters" in preprocessors or CSV Data Set Config.