ContributionsMost RecentMost LikesSolutionsRe: I have a groovy script that parses a complex json and throws the desired values in loop Hi Ilario72 , Firstly thanks for your response, So as you can see there are 2 for loops . so do you think i can utilize this approach to get data from the both loops or maybe if possible you can suggest a decision statement to get the values i basically need startdate, endate and qty for a query and another groovy attaching my project for your reference . Can you tell me accordingly . I am really new to groovy and ReadyAPI I have a groovy script that parses a complex json and throws the desired values in loop Hi team I have a groovy script that parses a complex json and throws the desired values in loop, My question is How do i use these values in the other test steps .. There are to sets of data that i have tried to get from the json and i have to pass it to another groovy script and sql query and also loop it so that one data is passed after the other now i want to be able to fetch the grantDetailId and so on so forth in the scripts . Kindly Help Thanks In Advance import groovy.json.* import groovy.util.* def response = context.expand( '${REST Request#Response}' ) def parsedJson = new JsonSlurper().parseText(response) //parsedJson.each {log.info it} //parsedJson[0].each{k,v->log.info " key : $k,value:$v"} //parsedJson[0].Grant.each{k,v->log.info "Grant key : $k,value:$v"} //def GrantDetailId = parsedJson[0].Grant.GrantDetails[1].GrantDetailId.toString() //log.info GrantDetailId def cnt =parsedJson[0].Grant.GrantDetails.size log.info cnt if (cnt=='1'){//Initial Request details def request = parsedJson[0].findAll{k,v -> v} log.info request def id = request.$id def grantDetailId = request.GrantDetailId def grantId = request.GrantId def startDate = request.StartDate def endDate = request.EndDate def qty = request.Quantity def leaseRate = request.LeaseRate def IsAmortized = request.IsAmortized def LicenseTypeId = request.LicenseTypeId log.info ("id=$id") log.info("GrantDetailId = $grantDetailId") log.info("GrantId = $grantId") log.info ("StartDate=$startDate") log.info ("EndDate=$endDate") log.info ("Quantity=$qty") log.info("LeaseRate=$leaseRate") log.info ("IsAmortized=$IsAmortized") log.info ("LicenseTypeId=$LicenseTypeId") } for(i=0;i<cnt;i++){ if (cnt<1){} if (i = cnt-1){//Grant/GrantDetail def grantDetailId = parsedJson[0].Grant.GrantDetails[i].GrantDetailId.toString() def qty = parsedJson[0].Grant.GrantDetails[i].Quantity.toInteger() //Grant/GrantDetail def grantId = parsedJson[0].Grant.GrantId.toInteger() def startDate = parsedJson[0].Grant.StartDate.toString() def endDate = parsedJson[0].Grant.EndDate.toString() def leaseRate = parsedJson[0].Grant.LeaseRate.toString() //Grant/project def projectId = parsedJson[0].Grant.Project.ProjectId.toString() def projectName = parsedJson[0].Grant.Project.ProjectName.toString() log.info grantDetailId + ' '+ qty.toString()+' '+startDate+' '+endDate+' '+grantId+' '+projectId assert qty == 3 break } } //if more grant records are present //reading grants length def grantscnt=parsedJson[0].Grant.Project.Grants.size log.info grantscnt for(i=0;i<grantscnt;i++){ if (grantscnt<=1){log.info("There are no grants") break } if (i=grantscnt -1){ def request2 = parsedJson[0].Grant.Project.Grants[i] log.info request2 //Grants def id = parsedJson[0].Grant.Project.Grants[i].$id def grantId = parsedJson[0].Grant.Project.Grants[i].GrantId.toInteger() def startDate = parsedJson[0].Grant.Project.Grants[i].StartDate.toString() def endDate = parsedJson[0].Grant.Project.Grants[i].EndDate.toString() def catalogId = parsedJson[0].Grant.Project.Grants[i].CatalogId.toString() //log.info id+' '+grantId+' '+startDate+' '+endDate+' '+catalogId def grantDetailcnt = parsedJson[0].Grant.Project.Grants[i].GrantDetails.size() log.info(grantDetailcnt) for(j=0;j<grantDetailcnt;j++){ if (j=grantDetailcnt -1){ def grantDetaiIs = parsedJson[0].Grant.Project.Grants[i].GrantDetails[j] def grantDetailId = grantDetaiIs.GrantDetailId.toString() def qty = grantDetaiIs.Quantity.toInteger() log.info grantDetailId+' '+qty+' '+id+' '+grantId+' '+startDate+' '+endDate+' '+catalogId break } break } }} //parsedJson[0].Grant.Project.each{k,v->log.info "Project key : $k,value:$v"} How to query circular json to get desired values which are present deep in sub nodes using groovy ? Hi , Given is a below json object which basically grows based on the data provided in the ui in a circular json way . I am trying to fetch the latest grant details based on the grantdetailId in the id's . My groovy scripting isn't so good after scouring the internet i am posting the question here . Kindly suggest a solution for the same {"$id":"1","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298033,"GrantId":279167,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":2,"LeaseRate":null,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-06T13:41:40.110","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":498,"MetadataList":null,"Grant":{"$id":"2","$type":"Elm7.Data.Model.Grant, Elm7.Data.Model","GrantId":279167,"Type":"P","PendingGrantId":null,"PendingGrantType":"P","ProjectId":802,"CatalogId":17940,"ForecastId":null,"StartDate":"2022-04-06T00:00:00.000","EndDate":"2022-06-29T00:00:00.000","IsCentralBudget":null,"CreatedDate":"2022-04-06T13:41:40.110","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantId":null,"Project":{"$id":"3","$type":"Elm7.Data.Model.Project, Elm7.Data.Model","ProjectId":802,"ProjectName":"DAES-US","CostCenter":"74290","ParentProjectId":null,"ProjectTypeId":488,"IsActive":true,"Description":null,"LockIdsid":null,"InheritorProjectId":null,"LockDate":null,"LegalEntityCode":"100","LacIdsid":"krehkopf","LacIdsid2":"","LacManagerIdsid":"jtwalsh","OpsManagerIdsid":"jcarlos","Approvals":[],"MetadataList":null,"Heir":[],"Inheritor":null,"ProjectDetails":[{"$id":"4","$type":"Elm7.Data.Model.ProjectDetail, Elm7.Data.Model","ProjectDetailId":4162,"ProjectId":802,"ProjectMetaDataId":1,"Value":"1","IsActive":null,"CreatedDate":"2018-10-16T03:36:34.713","CreatedBy":"wtan23","ModifiedDate":null,"ModifiedBy":null,"ProjectMetaData":null,"Project":{"$ref":"3"}},{"$id":"5","$type":"Elm7.Data.Model.ProjectDetail, Elm7.Data.Model","ProjectDetailId":4161,"ProjectId":802,"ProjectMetaDataId":2,"Value":"0","IsActive":null,"CreatedDate":"2018-10-16T03:36:34.713","CreatedBy":"wtan23","ModifiedDate":null,"ModifiedBy":null,"ProjectMetaData":null,"Project":{"$ref":"3"}},{"$id":"6","$type":"Elm7.Data.Model.ProjectDetail, Elm7.Data.Model","ProjectDetailId":4163,"ProjectId":802,"ProjectMetaDataId":3,"Value":"0","IsActive":null,"CreatedDate":"2018-10-16T03:36:34.713","CreatedBy":"wtan23","ModifiedDate":null,"ModifiedBy":null,"ProjectMetaData":null,"Project":{"$ref":"3"}},{"$id":"7","$type":"Elm7.Data.Model.ProjectDetail, Elm7.Data.Model","ProjectDetailId":5806,"ProjectId":802,"ProjectMetaDataId":4,"Value":"DAES-US","IsActive":true,"CreatedDate":"2021-05-08T06:40:18.753","CreatedBy":"Devaragudi, Prakruthi","ModifiedDate":null,"ModifiedBy":null,"ProjectMetaData":null,"Project":{"$ref":"3"}}],"DivisionBuFADB":null,"ChildProjects":[],"ParentProject":null,"Approver":null,"Approver2":null,"ApproverManager":null,"LockUser":null,"Grants":[{"$ref":"2"},{"$id":"8","$type":"Elm7.Data.Model.Grant, Elm7.Data.Model","GrantId":279168,"Type":"P","PendingGrantId":null,"PendingGrantType":"P","ProjectId":802,"CatalogId":17934,"ForecastId":null,"StartDate":"2022-04-07T00:00:00.000","EndDate":"2023-04-27T00:00:00.000","IsCentralBudget":null,"CreatedDate":"2022-04-06T22:40:37.573","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantId":null,"Project":{"$ref":"3"},"GrantDetails":[{"$id":"9","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298035,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":2,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-06T22:40:37.573","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]},{"$id":"10","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298036,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":5,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-07T00:29:35.937","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]},{"$id":"11","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298037,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":10,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-07T00:34:09.757","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]}],"IssueFlaggings":[],"Billbacks":[],"DiscountAssociations":[],"GrantOverrides":[],"Forecast":null,"Catalog":{"$id":"12","$type":"Elm7.Data.Model.Catalog, Elm7.Data.Model","CatalogId":17934,"SupplierId":275,"ProductCode":"GX9006-SF-TBL","ProductName":"GX9006-SF-TBL","Description":"License","CreatedDate":"2018-10-16T03:36:31.777","CreatedBy":"wtan23","ModifiedDate":"2020-08-19T16:51:57.807","ModifiedBy":"ariding","Billbacks":[],"Supplier":{"$id":"13","$type":"Elm7.Data.Model.Supplier, Elm7.Data.Model","SupplierId":275,"SupplierName":"Zuken","IsActive":true,"ShowPrice":true,"LeaseRate":0.18000000,"Description":null,"ParentSupplierId":null,"SupplierNotes":null,"LockIdsid":null,"LockDate":null,"StartDate":null,"EndDate":null,"CreatedDate":"2018-10-16T03:36:31.667","ModifiedDate":null,"CmOwner":null,"LmOwner":"ariding","SmOwner":null,"Commodity":null,"RenewalQuarter":"Q3","Supplier1":[],"Supplier2":null,"SupplierDaemons":[],"SupplierDetails":[],"SupplierInventories":[],"PoolTables":[],"ProductGroups":[],"FixedLicenseInventories":[],"UserInfo":null,"Discounts":[],"Billbacks":[],"CalculationHistories":[],"Catalogs":[{"$id":"14","$type":"Elm7.Data.Model.Catalog, Elm7.Data.Model","CatalogId":17940,"SupplierId":275,"ProductCode":"PC-Z1601-SF-TBL","ProductName":"PC-Z1601-SF-TBL","Description":"Design Gateway TBL no remix floating","CreatedDate":"2018-10-16T03:36:31.777","CreatedBy":"wtan23","ModifiedDate":null,"ModifiedBy":null,"Billbacks":[],"Supplier":{"$ref":"13"},"Forecasts":[],"Grants":[{"$ref":"2"}],"ProductGroupProducts":[],"CatalogYears":[],"UserInfo":null,"UserInfo1":null,"OtherLicenses":[]},{"$ref":"12"}],"OtherLicenses":[]},"Forecasts":[],"Grants":[{"$ref":"8"}],"ProductGroupProducts":[],"CatalogYears":[],"UserInfo":null,"UserInfo1":null,"OtherLicenses":[]}}],"Billbacks":[],"ForecastControls":[],"OpsManagerName":null,"OtherLicenses":[]},"GrantDetails":[{"$ref":"1"},{"$id":"15","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298034,"GrantId":279167,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":3,"LeaseRate":null,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-06T22:35:31.670","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":498,"MetadataList":null,"Grant":{"$ref":"2"},"GrantServers":[]}],"IssueFlaggings":[],"Billbacks":[],"DiscountAssociations":[],"GrantOverrides":[],"Forecast":null,"Catalog":{"$ref":"14"}},"GrantServers":[]} An idea that i am applying is present below but that is only to search with hard coded way i want a more dynamic approach to get the required details from the above json into a data source that i could use further . Thanks in Advance import groovy.json.* import groovy.util.* def request = '[{"$ref":"2"},{"$id":"8","$type":"Elm7.Data.Model.Grant, Elm7.Data.Model","GrantId":279168,"Type":"P","PendingGrantId":null,"PendingGrantType":"P","ProjectId":802,"CatalogId":17934,"ForecastId":null,"StartDate":"2022-04-07T00:00:00.000","EndDate":"2023-04-27T00:00:00.000","IsCentralBudget":null,"CreatedDate":"2022-04-06T22:40:37.573","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantId":null,"Project":{"$ref":"3"},"GrantDetails":[{"$id":"9","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298035,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":2,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-06T22:40:37.573","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]},{"$id":"10","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298036,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":5,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-07T00:29:35.937","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]},{"$id":"11","$type":"Elm7.Data.Model.GrantDetail, Elm7.Data.Model","GrantDetailId":298037,"GrantId":279168,"StartDate":"2022-03-31T16:00:00.000","ToolVersion":null,"HSDNumber":"","PONumber":"","Quantity":10,"LeaseRate":0.800000000,"Price":null,"Formula":null,"IsAmortized":false,"CreatedDate":"2022-04-07T00:34:09.757","CreatedBy":"kpokkulx","ModifiedDate":null,"ModifiedBy":null,"Elm6GrantDetailId":null,"LicenseTypeId":494,"MetadataList":null,"Grant":{"$ref":"8"},"GrantServers":[]}],"IssueFlaggings":[],"Billbacks":[],"DiscountAssociations":[],"GrantOverrides":[],"Forecast":null,"Catalog":{"$id":"12","$type":"Elm7.Data.Model.Catalog, Elm7.Data.Model","CatalogId":17934,"SupplierId":275,"ProductCode":"GX9006-SF-TBL","ProductName":"GX9006-SF-TBL","Description":"License","CreatedDate":"2018-10-16T03:36:31.777","CreatedBy":"wtan23","ModifiedDate":"2020-08-19T16:51:57.807","ModifiedBy":"ariding","Billbacks":[],"Supplier":{"$id":"13","$type":"Elm7.Data.Model.Supplier, Elm7.Data.Model","SupplierId":275,"SupplierName":"Zuken","IsActive":true,"ShowPrice":true,"LeaseRate":0.18000000,"Description":null,"ParentSupplierId":null,"SupplierNotes":null,"LockIdsid":null,"LockDate":null,"StartDate":null,"EndDate":null,"CreatedDate":"2018-10-16T03:36:31.667","ModifiedDate":null,"CmOwner":null,"LmOwner":"ariding","SmOwner":null,"Commodity":null,"RenewalQuarter":"Q3","Supplier1":[],"Supplier2":null,"SupplierDaemons":[],"SupplierDetails":[],"SupplierInventories":[],"PoolTables":[],"ProductGroups":[],"FixedLicenseInventories":[],"UserInfo":null,"Discounts":[],"Billbacks":[],"CalculationHistories":[],"Catalogs":[{"$id":"14","$type":"Elm7.Data.Model.Catalog, Elm7.Data.Model","CatalogId":17940,"SupplierId":275,"ProductCode":"PC-Z1601-SF-TBL","ProductName":"PC-Z1601-SF-TBL","Description":"Design Gateway TBL no remix floating","CreatedDate":"2018-10-16T03:36:31.777","CreatedBy":"wtan23","ModifiedDate":null,"ModifiedBy":null,"Billbacks":[],"Supplier":{"$ref":"13"},"Forecasts":[],"Grants":[{"$ref":"2"}],"ProductGroupProducts":[],"CatalogYears":[],"UserInfo":null,"UserInfo1":null,"OtherLicenses":[]},{"$ref":"12"}],"OtherLicenses":[]},"Forecasts":[],"Grants":[{"$ref":"8"}],"ProductGroupProducts":[],"CatalogYears":[],"UserInfo":null,"UserInfo1":null,"OtherLicenses":[]}}]' def response = context.expand( '${REST Request#Response#$[0]}' ) //def grant = context.expand( '${REST Request#Response#$[0][\'Grant\']') //def grantDetail1 = context.expand( '${REST Request#Response#$[0][\'Grant\'][\'GrantDetails\']}' ) //def grants = context.expand( '${REST Request#Response#$[0][\'Grant\'][\'Project\'][\'Grants\']}' ) //log.info(grants) //def grantdetailsforthegrants = context.expand( '${REST Request#Response#$[0][\'Grant\'][\'GrantDetails\']}' ) def parsedJson = new JsonSlurper().parseText(request) //def parsedJson = new JsonSlurper().parseText(response) log.info(parsedJson) def cnt = parsedJson.Grants.GrantDetailIs.size() log.info(cnt) for (i=0; i < cnt;) { def grantDetailId = parsedJson.Grants.GrantDetailIs[1].toString() log.info grantDetailId // int qty = parsedJson.Grants.GrantDetailIs[i].Quantity.toInteger() /* if (grantDetailId == "298037") { log.info grantDetailId + ' '+ qty.toString() // log.info parsedJson.shareInfo[i].Grant assert qty == 10 break } ++i;*/ } /*for(json in parsedJson){ log.info json }*/ //log.info parsedJson.keySet() //log.info(parsedJson.Grant) //log.info(parsedJson.Grant.Project) //log.info(parsedJson.Grant.GrantDetails) //log.info(parsedJson.Grant.Project.Grants) //log.info(parsedJson.Grant.Project.Grants.1.GrantDetails) //def test2 = new JsonSlurper().parseText(grantDetail1) //log.info(test2 ) //log.info test2.keySet() //def parseresponse2 = new JsonSlurper().parseText(grants) //log.info(parseresponse2) /* //def parseresponse3 = new JsonSlurper().parseText(grantdetailsforthegrants) //log.info(parseresponse3) def cnt = parsedJson.size() log.info(cnt) def grantDetailId = parsedJson.Grant.GrantDetails log.info(grantDetailId) for (i=0; i < cnt;) { def grantDetailId = parsedJson.Grant.GrantDetails log.info(grantDetailId) int qty = parsedJson.Quantity.toInteger() if (grantDetailId == "298033") { log.info grantDetailId + ' '+ qty.toString() // log.info parsedJson.Grant assert qty == 2 break } ++i; } */ The above solution is just an attempt and not the actual required need . I want to query the json to get data from sub nodes in ready api details liek quantity startand end date so on and so forth kindly help Re: How do we handle empty string dynamically in assertions in ReadyAPI I want to assert that the values are empty from the script but i want say log only the values that are empty and assert it so the script doesn't fail as it is a valid scenario I was thinking to check post the assert if it is an empty string it gives me a chance to assert if empty but not sure how to do that or if that makes any sense at all. P.S : I am pretty new to coding and readyapi as on whole so i would be really grateful if you could just give an idea on how i could do this . Re: How do we handle empty string dynamically in assertions in ReadyAPI Hi ChrisAdams , The above code snippet worked like a charm but i am not so good at coding do you mind helping me modify it to the above logic that i mentioned below kindly help def tierPriceQ1 = context.expand( '${plantestautomation source#Q1TierPriceScallingFactor}' ) def tierPriceQ2 = context.expand( '${plantestautomation source#Q2TierPriceScallingFactor}' ) def tierPriceQ3 = context.expand( '${plantestautomation source#Q3TierPriceScallingFactor}' ) def tierPriceQ4 = context.expand( '${plantestautomation source#Q4TierPriceScallingFactor}' ) def intelPrice = context.expand( '${plantestautomation source#PlanQ1HistoricalFormula#$[\'FinalPrice\'][\'IntelPrice\']}' ) //log.info(intelPrice ) //scaling factor def contractDomainQ1 = context.expand( '${plantestautomation source#Q1CD}' ) def contractDomainQ2 = context.expand( '${plantestautomation source#Q2CD}' ) def contractDomainQ3 = context.expand( '${plantestautomation source#Q3CD}' ) def contractDomainQ4 = context.expand( '${plantestautomation source#Q4CD}' ) //scaling factor for commitmentment def commitmentQ1 = context.expand( '${plantestautomation source#Q1Commitment}' ) def commitmentQ2 = context.expand( '${plantestautomation source#Q2Commitment}' ) def commitmentQ3 = context.expand( '${plantestautomation source#Q3Commitment}' ) def commitmentQ4 = context.expand( '${plantestautomation source#Q4Commitment}' ) //prorated for Quarters def proratedQ1 = context.expand( '${prorated jdbc#ResponseAsXml#//Results[1]/ResultSet[1]/Row[1]/PRORATED[1]}' ) def proratedQ2 = context.expand( '${prorated jdbc#ResponseAsXml#//Results[1]/ResultSet[1]/Row[2]/PRORATED[1]}' ) def proratedQ3 = context.expand( '${prorated jdbc#ResponseAsXml#//Results[1]/ResultSet[1]/Row[3]/PRORATED[1]}' ) def proratedQ4 = context.expand( '${prorated jdbc#ResponseAsXml#//Results[1]/ResultSet[1]/Row[4]/PRORATED[1]}' ) //plan cost derived from query for validation def queryplancostQ1 = context.expand( '${plantestjdbc#Q1Cost}' ) def queryplancostQ2 = context.expand( '${plantestjdbc#Q2Cost}' ) def queryplancostQ3 = context.expand( '${plantestjdbc#Q3Cost}' ) def queryplancostQ4 = context.expand( '${plantestjdbc#Q4Cost}' ) //plan quantity derived from JSON response def planqtyQ1 = context.expand( '${plantestautomation source#PlanQ1Qty}' ) def planqtyQ2 = context.expand( '${plantestautomation source#PlanQ2Qty}' ) def planqtyQ3 = context.expand( '${plantestautomation source#PlanQ3Qty}' ) def planqtyQ4 = context.expand( '${plantestautomation source#PlanQ4Qty}' ) /* //Tier Group Formula def Q1TierGroupFormula = context.expand( '${plancostcalculation#ResponseAsXml#//Response[1]/e[*]/Q1TierGroupFormula[1]}' ) def Q2TierGroupFormula = context.expand( '${plancostcalculation#ResponseAsXml#//Response[1]/e[*]/Q2TierGroupFormula[1]}' ) def Q3TierGroupFormula = context.expand( '${plancostcalculation#ResponseAsXml#//Response[1]/e[*]/Q3TierGroupFormula[1]}' ) def Q4TierGroupFormula = context.expand( '${plancostcalculation#ResponseAsXml#//Response[1]/e[*]/Q4TierGroupFormula[1]}' ) */ //First check for commitment /*String [] Quater = new String[5]; //Quater[0] = "Q1"; //Quater[1] = "Q2"; //Quater[2] = "Q3"; Quater[3] = "Q4"; for (int i=0; i<5; i++) { log.info("Quater :" + Quater[i]); }*/ //log.info(commitmentQ1); //log.info(tierPriceQ1) double commitmentqauterQ1 = commitmentQ1 ? commitmentQ1.toDouble() :1 ; double ContractDomainqauterQ1 = contractDomainQ1 ? contractDomainQ1.toDouble() : 1 ; double tierPriceqauterQ1 = tierPriceQ1 ? tierPriceQ1.toDouble() : 1 ; int prorateddaysQ1 = proratedQ1.toInteger(); int QtyQ1 = planqtyQ1? planqtyQ1.toInteger() : 0 ; double PriceQ1 = tierPriceQ1 ? tierPriceqauterQ1 : intelPrice.toDouble() def planCostQ1 = (PriceQ1.toDouble() * QtyQ1.toInteger() * prorateddaysQ1.toInteger() * ContractDomainqauterQ1.toDouble() * commitmentqauterQ1.toDouble()).round(1) def expectedCostQ1 = queryplancostQ1.toDouble().round(1) //log.info("planCostQ1 $planCostQ1") //log.info("expectedCostQ1 $expectedCostQ1" ) assert planCostQ1 == expectedCostQ1 log.info("Assertion passed !! $planCostQ1 | $expectedCostQ1") //log.info("intelPriceQ1 :$intelPrice" ) //log.info("Qty: $QtyQ1") /*log.info(Qty) log.info( prorateddays) log.info(tierPriceqauter) log.info(ContractDomainqauter ) log.info(commitmentqauter) log.info(intelPrice) log.info(intelPrice) //Qty $prorateddays $tierPriceqauter $ContractDomainqauter $commitmentqauter) */ //Q2 double commitmentqauterQ2 = commitmentQ2 ? commitmentQ2.toDouble() :1 ; double ContractDomainqauterQ2 = contractDomainQ2 ? contractDomainQ2.toDouble() : 1 ; double tierPriceqauterQ2 = tierPriceQ2 ? tierPriceQ2.toDouble() : 1 ; int prorateddaysQ2 = proratedQ2.toInteger(); int QtyQ2 = planqtyQ2? planqtyQ2.toInteger() : 0 ; double PriceQ2 = tierPriceQ2 ? tierPriceqauterQ2 : intelPrice.toDouble() def planCostQ2 = (PriceQ2.toDouble() * QtyQ2.toInteger() * prorateddaysQ2.toInteger() * ContractDomainqauterQ2.toDouble() * commitmentqauterQ2.toDouble()).round(1) def expectedCostQ2 = queryplancostQ2.toDouble().round(1) assert planCostQ2 == expectedCostQ2 log.info("Assertion passed !! $planCostQ2 | $expectedCostQ2") //log.info("planCostQ2 : $planCostQ2") //log.info("QtyQ2: $QtyQ2") //log.info(PriceQ2) //log.info(tierPriceqauterQ2) //log.info(tierPriceQ2) //log.info(ContractDomainqauterQ2 ) //log.info(commitmentqauterQ2) //log.info(prorateddaysQ2) //Q3 double commitmentqauterQ3 = commitmentQ3 ? commitmentQ3.toDouble() :1 ; double ContractDomainqauterQ3 = contractDomainQ3 ? contractDomainQ3.toDouble() : 1 ; double tierPriceqauterQ3 = tierPriceQ3 ? tierPriceQ3.toDouble() : 1 ; int prorateddaysQ3 = proratedQ3.toInteger(); int QtyQ3 = planqtyQ3? planqtyQ3.toInteger() : 0 ; double PriceQ3 = tierPriceQ3 ? tierPriceqauterQ3 : intelPrice.toDouble() def planCostQ3 = (PriceQ3.toDouble() * QtyQ3.toInteger() * prorateddaysQ3.toInteger() * ContractDomainqauterQ3.toDouble() * commitmentqauterQ3.toDouble()).round(1) def expectedCostQ3 = queryplancostQ3.toDouble().round(1) assert planCostQ3 == expectedCostQ3 log.info("Assertion passed !! $planCostQ3 | $expectedCostQ3") //log.info("planCostQ3 : $planCostQ3") //log.info("intelPriceQ3 :$intelPrice" ) //log.info("QtyQ3: $QtyQ3") //Q4 double commitmentqauterQ4 = commitmentQ4 ? commitmentQ4.toDouble() :1 ; double ContractDomainqauterQ4 = contractDomainQ4 ? contractDomainQ4.toDouble() : 1 ; double tierPriceqauterQ4 = tierPriceQ4 ? tierPriceQ4.toDouble() : 1 ; int prorateddaysQ4 = proratedQ4.toInteger(); int QtyQ4 = planqtyQ4? planqtyQ4.toInteger() : 0 ; double PriceQ4 = tierPriceQ4 ? tierPriceqauterQ4 : intelPrice.toDouble() def planCostQ4 = (PriceQ4.toDouble() * QtyQ4.toInteger() * prorateddaysQ4.toInteger() * ContractDomainqauterQ4.toDouble() * commitmentqauterQ4.toDouble()).round(1) def expectedCostQ4 = queryplancostQ4.toDouble().round(1) assert planCostQ4 == expectedCostQ4 log.info("Assertion passed !! $planCostQ4 | $expectedCostQ4") //log.info("planCostQ4 : $planCostQ4") //log.info("intelPriceQ4 :$intelPrice" ) //log.info("QtyQ4: $QtyQ4") Re: How do we handle empty string dynamically in assertions in ReadyAPI richie My apologies , I thought i was clear in my head , yes you are absolutely right . Please find the snippets in attachment .I hope it is clearer Reiterating where i am getting this issue . In the UI i beleive you are able to see a few empty values so when i try to validate it with db empty values i am getting that error . DB : There's nothing i can do as it's coming from a stored proc . Groovy : This is where i am seeking help to modify my logic such that i could handle such empty strings . Kindly help jdbc output file for jdbc output . This is my beloow groovy scipt for logic and assertion . double commitmentqauterQ1 = commitmentQ1 ? commitmentQ1.toDouble() :1 ; double ContractDomainqauterQ1 = contractDomainQ1 ? contractDomainQ1.toDouble() : 1 ; double tierPriceqauterQ1 = tierPriceQ1 ? tierPriceQ1.toDouble() : 1 ; int prorateddaysQ1 = proratedQ1.toInteger(); int QtyQ1 = planqtyQ1? planqtyQ1.toInteger() : 0 ; double PriceQ1 = tierPriceQ1 ? tierPriceqauterQ1 : intelPrice.toDouble() def planCostQ1 = (PriceQ1.toDouble() * QtyQ1.toInteger() * prorateddaysQ1.toInteger() * ContractDomainqauterQ1.toDouble() * commitmentqauterQ1.toDouble()).round(1) def expectedCostQ1 = queryplancostQ1.toDouble().round(1) //log.info("planCostQ1 $planCostQ1") //log.info("expectedCostQ1 $expectedCostQ1" ) assert planCostQ1 == expectedCostQ1 log.info("Assertion passed !! $planCostQ1 | $expectedCostQ1") How do we handle empty string dynamically in assertions in ReadyAPI ERROR: An error occurred [empty String], see error log for details Hi i have a need to validate two data sources using nested loop on multiple records in several tables Steps Build a Rest Request get the datasource getting the data from db as expected result write a groovy script inorder to get a value to be validated with db Asert the values are equal Issue : I have multiple empty values in the data sources from the api(actual value) and expected value db Question : When i run my script i am getting this error ERROR: An error occurred [empty String], see error log for details for empty values asserted . Please help as i am on a deadline and am aunable to find a solution online . SolvedRe: Design For Automated testing of a Grid template UI usnig ReadyAPI Hi richie Apologies for the misunderstanding !! Context : We are trying to build an API automation test suite for a Grid based Application where in we input certain parameters and recieve data in the form of a grid like this : This is the application frontend it works on the basis of stored Procs that are written which are called when a particular functionality is called and drops the data for the particular parameter . This is what we do validate manually for now and we would like to automate the same hence API Automation felt like a natural step . Q1. what is the purpose of the REST request? A) REST Request is used to interact with the application to recieve the responses based on the request and we are looking to validate the same . Q2. What is the purpose of the storedproc? A) Purpose of the stored proc is to run when a related api call is called to throw the requested data . Q3. Is the storedproc doing something to the data retrieved in the REST request? A) No It is what is throwing the data to the frontend Q4. Are you saying the storedproc returns a json rather than xml payload? A) Stored proc return XML payload only . I can validate using the stored proc or json (We utilize it based on the scenario) Q5. Can you please attach rather than embed the screenshots? I cant see whats going on with embedded screenshots. attached A) The Ask is to validate the data treating them as individual objects by either callind the REST request or the Stored Proc and write a custom query to get similar data and validate the same . This is the proposed approach . Questions: 1) What i am looking for is your understanding of the design and feasibility of the same . Does it make sense in real world QA to validate in this way if yes then fine if no then please state your opinion . 2) Can you please tell me how i can implement the same in a short way that gives me a quick validation and a more logical way that would be dynamic and covers longer range Re: Design For Automated testing of a Grid template UI usnig ReadyAPI Hi richie Where's this json response come from? I ran a REST API call to the Application API (Grid based Application ) than the stored proc and received the JSON response . As you can see the response nodes are individual numbers and there is no global node which making it hard to get as a data source and then validate with the JDBC response . My idea is something like this as i have very less time at hand . I would appreciate if there is any script suggestion that could help here . I have attached the two responses below .- Hope this helps to clarify Also would appreciate if you could provide a world view to the same as in what could be the best practice to validate the Response from this application in general. P.S: I need a dynamic solution as the data that i will be validating would only increase in number can't keep individualy adding data for each node . This is the JDBC Step: Re: Design For Automated testing of a Grid template UI usnig ReadyAPI Hi richie , Thanks for being so articulate. I have people who have implemented the solution ,although i need to lay down the basic groundwork inorder to reach them .The team has allowed me to involve in upgrading my skills and also are open to other solutions such as getting the data from the UI in excel format . Another solution is to validate JSON response with the JDBC Step . Can you please help me with this ? I have my JSON Response something like this : (Can't provide actual data for security purposes but this is the response and they are severeal of these based on the request) { "$id" : "1", "$type" : "XYZ", "FeatureName" : "XYZ", "FeatureQuantity" : 1, "ToolFamily" : "XYZ", "IsPrimary" : true, "SupplierName" : "XYZ", "ProductCode" : "XYZ", "Description" : "XYZ", "ToolIsActive" : true, "FeatureIsActive" : true, "IsRemixable" : true, "IsAnnualized" : false, "ListPrice" : 10500.00000000, "ModifiedBy" : null, "ModifiedDate" : null, "CatalogId" : 21774, "Features" : "XYZ", "ProductType" : "A-la-carte" }, And with the help of the developer i have got the query that gives the response to certain fields from this and there are multiple records and vary with data required . Can you please provide any familiar way to validate such requests and the response can have n number of entries and have only numbers for nodes but i want to extract only the data that i need and have to validate it with the jdbc response . Let's say i have both can you please provide a solution to validate the same . Please let me know if there is anyway i could connect i terribly need to get this done by today .