How to implement multithreading in groovy? - multithreading

I want to create 10 million customers for performance testing. I am running a basic groovy script for creating a customer with only mandatory attributes. Then I am running the script inside a loop.
How can I improve the performance of this groovy script?
I can't find the corresponding multi-threading options that are available in impex import.
Is there a better way of creating 10 million customers in Hybris?
Edit 1:
Sample groovy script for generating customers with different id's.
import com.google.common.collect.ImmutableSet
import de.hybris.platform.core.model.user.AddressModel
import de.hybris.platform.core.model.user.CustomerModel
//Setting only mandatory attributes
for(int i=0; i<100000; i++) {
customerModel = new CustomerModel()
id = new Random().nextInt(100000000)
uid = 'TestCustomer_'+id
customerModel.setUid(uid)
name = 'Test Customer Name_'+id
customerModel.setName(name)
addressModel = new AddressModel()
addressModel.setOwner(customerModel)
customerModel.setDefaultPaymentAddress(addressModel)
customerModel.setDefaultShipmentAddress(addressModel)
try{
modelService.save(customerModel)
}catch(Exception e){
println('Creation of customer with id = '+uid+' and amway account = '+code+' failed with error : '+e.getMessage())
}
}

I would say the logical answer is to use Impex files. This allows creation bulk and has support for multithreading: https://help.hybris.com/1811/hcd/44f79c4e604a4bff8456a852e617d261.html
basically you can configure the number of workers or threads:
impex.import.workers=4
You would be responsible for converting your input format to either *.csv or *.impex
addition:
Regarding the Groovy script, you can set the uid and name with impex, only you would have to provide the random numbers in advance. You could do this in Excel or in some scripting language.
You could even do it in the impex itself with code execution.
But if you just want a lot of random customers: you could also just spin up 10 browser windows with /hac and run the script ten times.

I created multiple ScriptingJob with the above groovy script and attached them to 30 different Cronjobs. Executing all of them in parallel achieved the same result.

Related

Jmeter tearDown Thread Group can't access previous thread group used file

I have a Test plan with several thread groups that write summary report results in the same csv file hosted in a server, this works fine using a networkdrive (z:) and changing jmeter.properties -> resultcollector.action_if_file_exists=APPEND.
Finally I have a tearDown Thread Group that insert the csv data into a sql server (the previous used networkdrive is hosted in this server in c:\jmeter\results.csv) and then it deletes the csv.
The case is when I run the test plan full I always have this error: "Cannot bulk load because the file "c:\jmeter\results.csv" could not be opened. Operating system error code 32"
The strange thing is that if I start the tearDown Thread Group alone it works fine, it makes the bulk insert in sql server and then it deletes de csv.
I started 2 days ago with Jmeter, so I'm sure I am misunderstanding something :S
Summary Report Config
JDBC Request
BeanShell PostProcessor that deletes csv
Test plan Structure
It happens because Summary Report (as well as other listeners) keep the file(s) open until test ends so you need to trigger this "close" event somehow.
Since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting therefore replace this Beanshell PostProcessor with the JSR223 PostProcessor and use the following code:
import org.apache.jmeter.reporters.ResultCollector
import org.apache.jorphan.collections.SearchByClass
def engine = engine = ctx.getEngine()
def test = engine.getClass().getDeclaredField('test')
test.setAccessible(true)
def testPlanTree = test.get(engine)
SearchByClass<ResultCollector> listenerSearch = new SearchByClass<>(ResultCollector.class)
testPlanTree.traverse(listenerSearch)
Collection<ResultCollector> listeners = listenerSearch.getSearchResults()
listeners.each { listener ->
def files = listener.files
files.each { file ->
file.value.pw.close()
}
}
new File('z:/result.csv').delete()
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It

What is the use of the 'Parameters' tab in the script record?

I have a scheduled script (running from a Suitelet script) that is getting parameters from a Suitelet. What do the parameters in the Parameter tab do?
my suitelet code chunk:
var params = [];
params['custscript_emp_accrual'] = empreq_id;
params['custscript_emp_months'] = rowCount;
nlapiLogExecution('debug', 'empreq_id:rowCount', empreq_id + ':' + rowCount);
nlapiScheduleScript('customscript_emp_accrual_sched', 'customdeploy_emp_accrual_sched', params);
my scheduled code chunk:
var empreq_Id = nlapiGetContext().getSetting('SCRIPT', 'custscript_emp_accrual');
var month = nlapiGetContext().getSetting('SCRIPT', 'custscript_emp_months');
var dateNow = nlapiLookupField('customrecord_payroll_period', month, 'custrecord_payperiod_enddate');
They're ways to setup script deployments. Check out the help doc "Creating Script Parameters Overview" for more information.
The Parameters allow you to pass data from the Suitelet to the Scheduled Script. If you don't set up the script parameters then the data won't be passed to the Scheduled Script.
You might want to focus your learning on SuiteScript 2.0, this is most widely used in industry and has more support online.
Script parameters are very useful for variables that could either change over time or be different between script deployments.
This is just a simple example of how you could use parameters:
You could have a script that could be deployed to more than one record type and on each record type you certain code to be executed for a different user.
Now you can add a script parameter called USER, which is a select/multi-select field. This means that on each script deployment, you can specify a different user for which your code should run.
Now you could have the following code to read your parameter and restrict editing:
var allowedUser= runtime.getCurrentScript().getParameter('custscript_user');
var currentUser= runtime.getCurrentUser();
if(currentUser == allowedUser){
//do something
}
You can now select a different user on each of your script deployments.
Hope this helps!
For more info, have a look at page 110 of this document from Oracle: SuiteScript Developer Guide

Hybris -> how to create cronjob with execute beanshell script?

I have a beanshell script and I would like it to automate.
I need to create cronjob and add my beanshell code to it.
Maybe someone do that think?
Is anyone know how to do this?
or how to match my script with cronjob?
The answer is actually given in Cronjob scripting documentation.
In a nutshell, you will use dynamic scripting to create the cronjob instead of using the slow old-fashioned way.
Concept
There are three new objects used (quoted from doc):
Script - the item type where the script content is stored (a separate deployment table)
ScriptingJob - a new ServicelayerJob item, which contains additionally the scriptURI (consequently, the stored script can be
found at runtime from different locations (classpath, db, etc..)
ScriptingJobPerformable - the spring bean assigned to every ScriptingJob instance; it implements the usual perform() method (like
for any other cronjob). This is where the "scripted" cronjob logic is
executed
How to use Cronjob scripting
First step - save your Script instance in the database. For this example I've used a code from http://www.beanshell.org/manual/quickstart.html
Note: you can create script with Groovy, BeanShell ad JavaScript
INSERT_UPDATE Script; code[unique=true];content;scriptType(code)
;myBshScript;"foo = ""Foo"";
four = (2 + 2)*2/2;
print( foo + "" = "" + four ); // print() is a BeanShell command
// Do a loop
for (i=0; i<5; i++)
print(i);
// Pop up a frame with a button in it
button = new JButton( ""My Button"" );
frame = new JFrame( ""My Frame"" );
frame.getContentPane().add( button, ""Center"" );
frame.pack();
frame.setVisible(true);";BEANSHELL
Don't forget to escape " in the script with an other " (Impex restriction).
Second step - create a ScriptingJob that use the previously created Script
INSERT_UPDATE ScriptingJob; code[unique=true];scriptURI
;myBshDynamicJob;model://myBshScript
model://myBshScript is used to retrieve a Script stored in the DB
Third step - create the CronJob
INSERT_UPDATE CronJob; code[unique=true];job(code);singleExecutable;sessionLanguage(isocode)
;myBshDynamicCronJob;myBshDynamicJob;true;en
Optional step - create a trigger for the CronJob
INSERT_UPDATE Trigger;cronjob(code)[unique=true];cronExpression
;myBshDynamicCronJob;0 0 0/1 1/1 * ? *
This executes the cronjob every hour.
Execute the CronJob by script
In the hac scripting tab, choose Groovy and run this in commit mode.
def dynamicCJ = cronJobService.getCronJob("myBshDynamicCronJob")
cronJobService.performCronJob(dynamicCJ,true)
After running the Script you should have this displayed
And in the console
INFO [hybrisHTTP27] (myBshDynamicCronJob) [ScriptingJobPerformable] Foo = 4
0
1
2
3
4
In Hybris, go to HMC> System> CronJobs> Search your created cronjob or create a new cronjob> Time Schedule tab> Trigger> Create Trigger.
From this Trigger tab window, you can schedule the interval eg. daily, weekly, etc. Also you can set the start time and frequency.
You can also do this trigger setting via impex as below:
INSERT_UPDATE Trigger;cronJob(code)[unique=true];second;minute;hour;day;month;year;relative;active;maxAcceptableDelay
;CartRemovalJob;0;5;4;-1;-1;-1;false;true;-1
For more detailed information, have a look at this, in case you have access to Hybris Wiki.
If you have access to hybris wiki, here you can find how to create and execute a cronjob.
In order to execute bean shell, in the cronjob "perform" method you should do this:
SimpleScriptContent content = new SimpleScriptContent("beanshell", "here your beanshell script code as string");
ScriptExecutable script = scriptingLanguagesService.getExecutableByContent(content);
ScriptExecutionResult result = script.execute();
...
Here the import section:
import de.hybris.platform.scripting.engine.content.impl.SimpleScriptContent;
import de.hybris.platform.scripting.engine.ScriptExecutionResult;
import de.hybris.platform.scripting.engine.ScriptExecutable;
You should access to scriptingLanguagesService with annotation:
#Autowired
ScriptingLanguagesService scriptingLanguagesService;
I have tried below steps for the groovy script. You can try the same for the beanshell.
You have to create an instance of
Script - the item type where the script content is going to store.
ScriptingJob - a new ServicelayerJob item, which contains additionally the scriptURI
CronJob - This is where the "scripted" cronjob logic is executed
1. Create a Script
Script code: HelloScript
Script engine type: beanshell
Content: log.info("Hello");
2. Create the Scripting Job
Again from HMC/Backoffice, find ScriptinJobs and create the new instance of it. Here you have to define Code and ScriptURI like
Code: HelloScriptJob
ScriptURI: model://HelloScript
You can access this job in the next step to create the CronJob
3. Create a CronJob
From HMC/BackOffice, create an instance of cronJob. Select above-created job(HelloScriptJob) in
Job definition drops down and save the changes. Now you good to schedule/run this cronJob.
Refer detailed post cronjob-using-groovy-script-hybris

Test JSF application on multiple servers with same JMeter test script

At the moment we are developing an application and deploying it in my local machine. And now I'm doing a load test using jmeter and it runs without a issue. The problem I'm getting is when I try to run the same test on a different machine with a different server it doesn't work.
And I observed that html element id's are different on different servers with JSF.(Issue is form submissions are not working). Is there a way to overcome this issue with jmeter since I want to run the same test scripts on different servers.
The process of extracting dynamic values from previous response and adding them to next request is called correlation. JMeter provides variety of Pre Processors and Post Processors to allow modification of requests on-the-fly.
Example use case:
Send a GET request a JSP page which contains a number of inputs
Extract all the inputs names and populate values where required
Populate dynamic fields of next request with values extracted in point 2
Send a POST request
Point 1: No changes to your script required
Point 2:
Add XPath Extractor as a child of GET Request and populate it as follows:
Reference Name: INPUT
XPath Query: //input/#name | //input[#type='hidden']
This extractor will fetch all <input> HTML elements and store it to JMeter Variables as
INPUT_1=javax.faces.ViewState
INPUT_2=loginForm_SUBMIT
INPUT3=...
...
Add a Beanshell Pre Processor as a child of next request with the following code
import java.util.Iterator;
import java.util.Map;
Iterator iter = vars.getIterator();
while (iter.hasNext())
{
Map.Entry e = (Map.Entry)iter.next();
if (e.getValue() != null)
{
if (e.getKey().toString().startsWith("INPUT_") && e.getValue().toString().length() >0)
{
sampler.addArgument(e.getValue().toString(),"VALUE OF YOUR INPUT");
}
}
}
The code above will fetch all variables prefixed with INPUT_ and add it as parameters to your next request.
See How to use BeanShell: JMeter's favorite built-in component guide for more information on Beanshell scripting in Apache JMeter to see what else can be done using Beanshell scripting and using of JMeter objects exposed to Beanshell test elements.

Passing list of values to Cucumber scenario outline

I have a scenario to validate 100 employee names, The QueryString will return them in xml format.All I want to do is to validate all the employee names in an Assertion statement like given below. Instead of adding each name in the Scenario Outline Example, Is it possible to send a list of 100 employee names as input so that I can Iterate through them in java and could easily validate in Assertion condition. Please advice.
Scenario Outline: When the User queries for employee information, the correct records are returned
Given the webservice is running
When the User queries for employee information "<QueryString>"
Then the User receives correct data "<Name>"
Examples:
|QueryString|Name|
|Some localhost url|Peter|
|Some localhost url|Sam|
.
.
#Then("^the User receives correct data\"([^\"]*)\"$")
public void the_user_receives_correct_data(String arg1) throws Throwable {
queryResultPage = selenium.getPageSource();
assertTrue(queryResultPage.contains(arg1));
}
so i will answere here to LINGS comment
What you can do, is use these filenames in your step definition to load the files in your code. Cucumber doesnt support direct file loading as far as i know.
i use something like this to locate full ressource pathes for my relative path file names:
public static String getAbsoluteResourcePath(String resourcePath) {
if (SystemUtils.IS_OS_WINDOWS) {
return Utils.class.getResource(resourcePath).getPath().substring(1).replace("/", File.separator);
} else {
return Utils.class.getResource(resourcePath).getPath().replace("/", File.separator);
}
}
The resourcePath should then be your relative file path
What you are looking for is external test data support, which is supported with QAF. You can use any inbuilt data provider with interceptor to modify data set or custom data provider.
If you are using cucumber version 5+ you can use qaf-cucumber that will give you all qaf features with cucumber. For lower version you can run your existing feature files with QAF runner.

Resources