Reading lines from CSV files to build body request - groovy

I'm creating a performance test with Jmeter and I need to create a body request like this:
{
[ "objectName1", "objectName2", ..., "objectNameN" ]
}
so need to create a Groovy script to build this request according to a certain .csv file with the objects names. And I have done something like this:
//Default separator
char SEPARATOR = ',';
String csvFile = props.get("csvPathAndName")
log.info('__________________________________________________________________________________________________________________________________________________________')
log.info(csvFile)
//function to read csv file
def readLines(String csvFile) {
File file = new File(csvFile);
List<String> objectNames = file.readLines();
// objectsNames.stream().forEach(e -> listOfString + ", " + e);
vars.put("listOfObjects", "'objectName1', 'objectName2', 'ObjectName3'");
}
readLines(csvFile)
Notice that in line
vars.put("listOfObjects", ...
I want to populate my listOfObjects with the values of my .csv file.
Someone can help me? I'm not really good at Groovy so I'm facing this problem now =//

I think you need to change this line:
vars.put("listOfObjects", "'objectName1', 'objectName2', 'ObjectName3'");
to this one:
vars.put("listOfObjects", '"' + objectNames.join('","') + '"');
and amend your request body to:
{
[ ${listOfObjects} ]
}
More information:
List.join() function
Apache Groovy: What Is Groovy Used For?

I've done this way. I've removed the last elements of the array to remove the end of file
, "
String csvFile = props.get("csvPathAndName")
log.info('__________________________________________________________________________________________________________________________________________________________')
log.info(csvFile)
//function to read csv file
def readLines(String csvFile) {
StringBuilder requestBody = new StringBuilder();
File file = new File(csvFile);
ArrayList<String> objectNames = file.readLines();
objectNames.eachWithIndex {
val, index ->
if (index == 0) {
requestBody.append(val + "\", ")
} else {
requestBody.append("\"" + val + "\", ")
}
}
requestBody.setLength(requestBody.length() -3)
vars.put("listOfObjects", requestBody.toString());
}
readLines(csvFile)
And my request body was just
[${listOfObjects}]

Related

groovy, ant.fileScanner, fileset, dir - how to use a String variable for the dir parameter in groovy using ant.fileScanner?

I am relatively new in groovy/java, and struggle with a simple task, to process all files following a given pattern in a given directory.
I tried this below, but as soon as try to use a variable instead of a fixed string for the directory of a fileset, it tells me that it doesn't find the directory - although it found it when entered as literal string.
My question, how to fix the error in line 34/32?
My code:
import groovy.ant.AntBuilder
String hotinfoNumber = new String('5152');
String unzipSpec = new String('*.zip')
String hotinfoDownloadDir = new String('.\\hotinfo_5125')
String[] hotinfoUnzips
hotinfoUnzips = [ '*.zip' , 'H*.zip']
println ('GO, hotinfoNumber=' + hotinfoNumber + ', unzipSpec=' + unzipSpec + ', hotinfoDownloadDir=' + hotinfoDownloadDir + ', hotinfoUnzips=' + hotinfoUnzips)
AntBuilder ant = new AntBuilder();
println 'c+c'
ant.fileScanner {
fileset(dir: '.\\hotinfo_5152', includes: '*.zip')
}.each { File f ->
println "c+c - Found file ${f.path}"
}
println ("c+v")
hotinfoUnzips.each { unzipFilespec ->
println 'c+v-unzipFilespec=' + unzipFilespec
ant.fileScanner {
fileset(dir: '.\\hotinfo_5152', includes: unzipFilespec.toString())
}.each { File f ->
println "c+v - Found file ${f.path}"
}
}
println ("v+v")
hotinfoUnzips.each { unzipFilespec -> // line 32
println 'v+v-unzipFilespec=' + unzipFilespec
ant.fileScanner { // line 34
fileset(dir: hotinfoDownloadDir.toString(), includes: unzipSpec.toString())
}.each { File f ->
println "v+v - unzips-Found file ${f.path}"
}
}
and the result:
c+v - Found file G:\TESTS_SAMPLES\GROOVY\test_misc\hotinfo_5152\HotInfo_5125.zip
c+v-unzipFilespec=H*.zip
c+v - Found file G:\TESTS_SAMPLES\GROOVY\test_misc\hotinfo_5152\HotInfo_5125.zip
v+v
v+v-unzipFilespec=*.zip
Caught: G:\TESTS_SAMPLES\GROOVY\test_misc\hotinfo_5125 does not exist.
G:\TESTS_SAMPLES\GROOVY\test_misc\hotinfo_5125 does not exist.
at org.apache.tools.ant.types.AbstractFileSet.getDirectoryScanner(AbstractFileSet.java:512)
at DirAndFile2$_run_closure4.doCall(DirAndFile2.groovy:34)
at DirAndFile2.run(DirAndFile2.groovy:32)
Disconnected from the target VM, address: '127.0.0.1:57397', transport: 'socket'
Process finished with exit code 1
Any hints and suggestions are highly appreciated.
Use new String('string') or directly 'string' are equivalent.
The problem in your case is the typo in the hotinfoDownloadDir definition.
Note that you change the order of the last two numbers in new String('.\\hotinfo_5125') definition compared with the '.\\hotinfo_5152'.
new String('.\\hotinfo_5125') must be new String('.\\hotinfo_5152'), if you change this, your code will work.

How do I download data trees to CSV?

How can I export nested tree data as a CSV file when using Tabulator? I tried using the table.download("csv","data.csv") function, however, only the top-level data rows are exported.
It looks like a custom file formatter or another option may be necessary to achieve this. It seems silly to re-write the CSV downloader, so while poking around the csv downloader in the download.js module, it looks like maybe adding a recursive function to the row parser upon finding a "_children" field might work.
I am having difficulty figuring out where to get started.
Ultimately, I need to have the parent-to-child relationship represented in the CSV data with a value in a parent ID field in the child rows (this field can be blank in the top-level parent rows because they have no parent). I think I would need to include an ID and ParentID in the data table to achieve this, and perhaps enforce the validation of that key using some additional functions as data is inserted into the table.
Below is currently how I am exporting nested data tables to CSV. This will insert a new column at the end to include a parent row identifier of your choice. It would be easy to take that out or make it conditional if you do not need it.
// Export CSV file to download
$("#export-csv").click(function(){
table.download(dataTreeCSVfileFormatter, "data.csv",{nested:true, nestedParentTitle:"Parent Name", nestedParentField:"name"});
});
// Modified CSV file formatter for nested data trees
// This is a copy of the CSV formatter in modules/download.js
// with additions to recursively loop through children arrays and add a Parent identifier column
// options: nested:true, nestedParentTitle:"Parent Name", nestedParentField:"name"
var dataTreeCSVfileFormatter = function(columns, data, options, setFileContents, config){
//columns - column definition array for table (with columns in current visible order);
//data - currently displayed table data
//options - the options object passed from the download function
//setFileContents - function to call to pass the formatted data to the downloader
var self = this,
titles = [],
fields = [],
delimiter = options && options.delimiter ? options.delimiter : ",",
nestedParentTitle = options && options.nestedParentTitle ? options.nestedParentTitle : "Parent",
nestedParentField = options && options.nestedParentField ? options.nestedParentField : "id",
fileContents,
output;
//build column headers
function parseSimpleTitles() {
columns.forEach(function (column) {
titles.push('"' + String(column.title).split('"').join('""') + '"');
fields.push(column.field);
});
if(options.nested) {
titles.push('"' + String(nestedParentTitle) + '"');
}
}
function parseColumnGroup(column, level) {
if (column.subGroups) {
column.subGroups.forEach(function (subGroup) {
parseColumnGroup(subGroup, level + 1);
});
} else {
titles.push('"' + String(column.title).split('"').join('""') + '"');
fields.push(column.definition.field);
}
}
if (config.columnGroups) {
console.warn("Download Warning - CSV downloader cannot process column groups");
columns.forEach(function (column) {
parseColumnGroup(column, 0);
});
} else {
parseSimpleTitles();
}
//generate header row
fileContents = [titles.join(delimiter)];
function parseRows(data,parentValue="") {
//generate each row of the table
data.forEach(function (row) {
var rowData = [];
fields.forEach(function (field) {
var value = self.getFieldValue(field, row);
switch (typeof value === "undefined" ? "undefined" : _typeof(value)) {
case "object":
value = JSON.stringify(value);
break;
case "undefined":
case "null":
value = "";
break;
default:
value = value;
}
//escape quotation marks
rowData.push('"' + String(value).split('"').join('""') + '"');
});
if(options.nested) {
rowData.push('"' + String(parentValue).split('"').join('""') + '"');
}
fileContents.push(rowData.join(delimiter));
if(options.nested) {
if(row._children) {
parseRows(row._children, self.getFieldValue(nestedParentField, row));
}
}
});
}
function parseGroup(group) {
if (group.subGroups) {
group.subGroups.forEach(function (subGroup) {
parseGroup(subGroup);
});
} else {
parseRows(group.rows);
}
}
if (config.columnCalcs) {
console.warn("Download Warning - CSV downloader cannot process column calculations");
data = data.data;
}
if (config.rowGroups) {
console.warn("Download Warning - CSV downloader cannot process row groups");
data.forEach(function (group) {
parseGroup(group);
});
} else {
parseRows(data);
}
output = fileContents.join("\n");
if (options.bom) {
output = "\uFEFF" + output;
}
setFileContents(output, "text/csv");
};
as of version 4.2 it is currently not possible to include tree data in downloads, this will be comming in a later release

Google Apps Script - remove spaces using .replace method

I'm trying to replace multiple whitespaces with single ones in a Google Doc with a script. But unfortunately the provided solution to this question isn't working for me. As you can see, I tried several alternatives but can not figure out how to do it right. Any ideas?
function searchAndReplace() {
var body = DocumentApp.getActiveDocument()
.getBody();
body.replaceText(/\s{2,}/,' ');
body.replaceText(/\s/g, " ") ;
body.replaceText("/\s/"," ");
body.replaceText('/\s{2,}/',' ');
}
Try:
function searchAndReplace() {
var body = DocumentApp.getActiveDocument().getBody();
body.editAsText().replaceText('\\s*', ' ');
}
UPDATE
One option is:
function getCorrections() {
var _getCorrections = 0,
text = DocumentApp.getActiveDocument().getBody().getText(),
regexp = /\s+/g,
matchesCorrections = text.match(regexp);
if (matchesCorrections) {
_getCorrections = matchesCorrections.reduce(function(previousValue,
currentValue) {
return previousValue + currentValue.length - 1;
}, 0);
}
return _getCorrections;
}

JSON format list in couchDB

I am writing a list for couchDB. All the documentation I have read assumes you would want to return data in html or plain text. I, however, need it to be returned in JSON format, in exactly the same way that a view would return (the application I am writing relies on this).
What is the correct way to have a list return its data in JSON format?
Try toJSON(), see the example.
You need to format your output with send to mimmic a JSON output. Here is an example of how we do that in a real case:
function(head, req) {
start({"headers": {"Content-Type": "application/json"}});
var keys = {};
while (row = getRow()) {
//Code goes here
send("{\"rows\":[");
var init = true;
for (var key in keys) {
if (init) {
send("\n");
init = false;
}
else send(",\n");
send("{\"key\": " + key + ",\"value\":");
send("{\"first_val\":" + val1);
send(", \"second_val\":" + val2);
send(", \"third_val\":" + val3 + "}}");
}
send("\n]}");
}
In this way, the output of the list has the same format as the underlying view.

How to generate requests and responses for all operations of a WSDL in soapUI using a groovy script?

I have a WSDL which has multiple operations. For each op i want a template .xml with its response and request.
I know how to do this manually in soapUI but I would like to generate them using a groovy script.
I googled a lot already, but seems I'm the only one who is looking for this.
My service has 16 Operations, so to do this manual would be too much time. Since the service gets updates every 2 months, an automation using a test step would be perfect.
I managed to do it for the requests already:
right-click on ´services´ in left tree, ´Generate Test Suite´, ´Single Test Case with one Request for each Operation´
then I loop through those Test Step Requests and store them on my disk.
import com.eviware.soapui.impl.wsdl.teststeps.*
for( testCase in testRunner.testCase.testSuite.getTestCaseList() )
{
for( testStep in testCase.getTestStepList() )
{
if( testStep instanceof WsdlTestRequestStep )
{
log.info "operation name: " +testStep.getName()
// create file name
Date startTime = new Date();
def cur_Time = startTime.getMonth() + "_" + startTime.getDate();
cur_Time = cur_Time + "_" + startTime.getHours() + startTime.getMinutes() +startTime.getSeconds()
def fileName = testStep.getName() + "_" + cur_Time
def inputFileRequest = new File("T:\\"+ "Request_" + fileName+".txt")
def inputFileResponse = new File("T:\\"+ "Response_" + fileName+".txt")
// write request to file
inputFileRequest.write(testStep.getProperty("request").value)
}
}
}
But I havent figured out a way to do this also for the resposes.
If i use getProperty("reponse") it's null of course.
Any hint? :)
and the winner is, I figured it out myself:
map = context.testCase.testSuite.project.interfaces["services"].operations
for (entry in map)
{
opName = entry.getKey()
inputFileRequest = new File("T:\\" + opName + "Request.xml")
inputFileResponse = new File("T:\\" + opName + "Response.xml")
inputFileRequest.write(entry.getValue().createRequest(true))
inputFileResponse.write(entry.getValue().createResponse(true))
}
This is great , even I am also working on the same. As of now I am taking xml request from a folder but I just want to get the Request from WSDL itself and want to get it's parameter.
try{
//Hitting the WSDLs one by one
wsdlList.each
{
wsdl ->
wsdlToHit=wsdl
log.info("WSDL To Hit :" + wsdlToHit)
// Creating an interface
log.info("Before Interface Creation")
iface= WsdlInterfaceFactory.importWsdl( project,wsdl, false )[0]
//iface= WsdlInterfaceFactory.importWsdl( project,WSDLFile, false )[0]
log.info("After Interface Creation")
if(Operation == "xyz")
{
requestXML= requestXML1
responseActual= responseActual1
expectedActual=expectedActual1
}
if(Operation == "abc")
{
requestXML= requestXML2
responseActual= responseActual2
expectedActual=expectedActual2
}
requestXML.each
{
request1 ->
def wsdlReqDir=request1
log.info("RequestLocation : " + wsdlReqDir)
File fl = new File(wsdlReqDir)
File[] wsdlDirFiles = fl.listFiles()
log.info("XML Files in Request Folder : " + wsdlDirFiles)
if(wsdlDirFiles.size()>0)
{
wsdlDirFiles.each
{
wsdlFile->
log.info("Request XML file to Send :" + wsdlFile)
//Calling the function to hit the service
sendRequest(wsdlFile,iface,Operation,Report_File_LOC,requestXML,responseActual,propData)
reportFilewriter.flush()
}
}
}
//removing Interface created
removeInterface(wsdl)
log.info("Removed iface : " + wsdl)
reportFilewriter.flush()
}
Thanks,
Hanumant

Resources