ContributionsMost RecentMost LikesSolutionsAssertion Count - GetAllCatalogOfferingsOverview This is a very simple automated assertion to get a count of returned offerings. It is easily build by copying two lines form another assertion, edit the holder line "getAllCatalogOfferings-Metadata-false#Response", right-clicking to generate a response for the offering, and building a count line. This process has many uses. // Copy these two lines from another assertion, and change the holder line def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context) def holder = groovyUtils.getXmlHolder( "getAllCatalogOfferings-Metadata-false#Response" ) // Use right-click to generate below line def response = context.expand( '${getAllCatalogOfferings-Metadata-false#Response#declare namespace ns2=\'urn:n2bb:OpenStreamVODModule_v40\'; //ns2:GetAllCatalogOfferingsResponse[1]/ns2:offering[1]}' ) log.info response //Validate it works // get count of offerings by copying line from above and modifying it def cntofferings = holder["count(//ns2:GetAllCatalogOfferingsResponse[1]/ns2:offering)"] as int; log.info cntofferings; Wed May 16 14:09:58 MDT 2012:INFO:231 Request <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:n2bb:OpenStreamVODModule_v40"> <soapenv:Header/> <soapenv:Body> <urn:GetAllCatalogOfferingsRequest> <urn:catalogId>0</urn:catalogId> <urn:includeAssetMetadata>false</urn:includeAssetMetadata> <!--Optional:--> <!--Optional:--> <urn:maxDaysOld>30</urn:maxDaysOld> </urn:GetAllCatalogOfferingsRequest> </soapenv:Body> Response (tidbit) <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:GetAllCatalogOfferingsResponse xmlns="urn:n2bb:OpenStreamVODTypes_v40" xmlns:ns2="urn:n2bb:OpenStreamVODModule_v40"> <ns2:offering packageName="MSG-UsingNonEBCStdPkgs-1" serviceName="MarcioNoEBC" modifiedTime="2012-05-03T16:23:44.542Z" createTime="2012-05-03T16:23:44.000Z" expirationDate="2012-11-06T20:10:00.000Z" startDate="2012-05-01T06:00:00.000Z" rentalDuration="86400" price="234" serviceType="MOD" type="MOD" offeringId="43716"> <description>MSG-UsingNonEBCStdPkgs-1 TITLE Title</description> <offeringRef>43723</offeringRef> <offeringRef>43724</offeringRef> <offeringRef>43717</offeringRef> <offeringRef>43720</offeringRef> <offeringRef>43718</offeringRef> <offeringRef>43721</offeringRef> <offeringRef>43722</offeringRef> <offeringRef>43719</offeringRef> <packageAsset assetId="BDPK0001336062223794" providerId="indemand.com" assetName="MSG-UsingNonEBCStdPkgs-1" assetClass="PackageAsset"/> <titleAsset releaseYear="2003" rating="PG-13" runTime="3671" shortTitle="MSG-UsingNonEBCStdPkgs-1" title="MSG-UsingNonEBCStdPkgs-1 TITLE Title" assetId="BDTL0001336062223794" providerId="indemand.com" assetName="indemand.com::BDTL0001336062223794" assetClass="TitleAsset"> <description>This is the TITLE Summary Short</description> <actor>Nick Actor</actor> <actor>Wilma Actor</actor> <actor>Mark Actor</actor> <actor>Lana Actor</actor> </titleAsset> <movieSegmentGroupAsset assetId="SGEN0001336062223794" providerId="indemand.com" assetName="indemand.com::SGEN0001336062223794" assetClass="MovieSegmentGroupAsset"/> <viewingWindow> <startDate>2012-05-01T18:20:00.000Z</startDate> <endDate>2012-11-06T20:10:00.000Z</endDate> </viewingWindow> <deliveryType> <deliveryMethod>http-live-streaming</deliveryMethod> <deliverableAssetClass> <assetClass>MovieSegmentGroupAsset</assetClass> <url>http://0.0.0.0:1818/segment-group/HTTP_LIVE_STREAMING/asset/indemand.com/BDTL0001336062223794/</url> <deviceType>DeviceNoMetadata</deviceType> </deliverableAssetClass> </deliveryType> <deliveryType> <deliveryMethod>rtsp-iap-streaming</deliveryMethod> <deliverableAssetClass> <assetClass>MovieSegmentGroupAsset</assetClass> </deliverableAssetClass> </deliveryType> <deliveryType> <deliveryMethod>rtsp-iap-dvb-streaming</deliveryMethod> <deliverableAssetClass> <assetClass>MovieSegmentGroupAsset</assetClass> </deliverableAssetClass> </deliveryType> </ns2:offering> <ns2:offering packageName="MSG-UsingNonEBCStdPkgs-1" serviceName="MODEBC" modifiedTime="2012-05-03T16:23:44.608Z" createTime="2012-05-03T16:23:44.000Z" expirationDate="2012-11-06T20:10:00.000Z" startDate="2012-05-01T06:00:00.000Z" rentalDuration="86400" price="234" serviceType="MOD" type="MOD" offeringId="43718"> <description>MSG-UsingNonEBCStdPkgs-1 TITLE Title</description> <offeringRef>43723</offeringRef> <offeringRef>43724</offeringRef> <offeringRef>43717</offeringRef> <offeringRef>43720</offeringRef> <offeringRef>43721</offeringRef> <offeringRef>43716</offeringRef> <offeringRef>43722</offeringRef> <offeringRef>43719</offeringRef> <packageAsset assetId="BDPK0001336062223794" providerId="indemand.com" assetName="MSG-UsingNonEBCStdPkgs-1" assetClass="PackageAsset"/> <titleAsset releaseYear="2003" rating="PG-13" runTime="3671" shortTitle="MSG-UsingNonEBCStdPkgs-1" title="MSG-UsingNonEBCStdPkgs-1 TITLE Title" assetId="BDTL0001336062223794" providerId="indemand.com" assetName="indemand.com::BDTL0001336062223794" assetClass="TitleAsset"> <description>This is the TITLE Summary Short</description> <actor>Nick Actor</actor> <actor>Wilma Actor</actor> <actor>Mark Actor</actor> <actor>Lana Actor</actor> </titleAsset> <movieSegmentGroupAsset assetId="SGEN0001336062223794" providerId="indemand.com" assetName="indemand.com::SGEN0001336062223794" assetClass="MovieSegmentGroupAsset"/> <viewingWindow> <startDate>2012-05-01T18:20:00.000Z</startDate> <endDate>2012-11-06T20:10:00.000Z</endDate> </viewingWindow> <deliveryType> <deliveryMethod>dsmcc-ngod-streaming</deliveryMethod> <deliverableAssetClass> <assetClass>MovieSegmentGroupAsset</assetClass> </deliverableAssetClass> </deliveryType> </ns2:offering> </soapenv:Envelope>Assertion - Validate Multiple metadata Responses to SourceWhy did we write this assertion? 1) Learn how to assert against metadata 2) Learn how to assert against dynamic metadata 3) Master complex assertions 4) Build an assertion that can be our model for many different assertions. 5) Also learned about count & getNodeValue 6) Learned how to use automated features to get a single result, then automate it. NOTE: If you want a text version of this post, email me from here. Web Service Request & Response = APP getCatalogOffering Overview: The objective of this assertion is the automatic of validation of a WS response metadata for categories: <ns2:metadata value="/B1/B2/B3" name="MOD::Category"/> <ns2:metadata value="/A1/A2/A3" name="MOD::Category"/> <ns2:metadata value="/C1/C2/C3" name="MOD::Category"/> <ns2:metadata value="/All Movies" name="MOD::Category"/> This is not a simple process! In our test case model, we had manually also added a specific offering to another category = /All Movies Therefore, when calling getCatalogOffering, it had 4 categories. For a negative test condition, change one DataGen property category value. ASSERTION - getCatalogOffering (5-16-12) This is a complete FUNCTIONAL assertion, based on: CGW v31 VOD v31 Data Gen - 8 pre-defined properties (not all used) OfferingOne = 37963 Cat-A3 = 179018 Cat-B3 = 179015 Cat-C3 = 179021 Cat-A1-A2-A3-value = /A1/A2/A3 Cat-B1-B2-B3-value = /B1/B2/B3 Cat-C1-C2-C3-value = /C1/C2/C3 Cat-AllMovies = /All Movies Automated steps DataGen Property Transfer-OfferingId CGW addOfferingsToCategory Delay After Adds APP getCatalogOffering Assertion All TestStep Assertion = getCategory-getNodeValueAutoDirectories // The Complete Assertion is Below // def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context) def holder = groovyUtils.getXmlHolder( "APP getCatalogOffering#Response" ) // GET addOfferingsToCategory added CATEGORIES // def catc3 = context.expand( '${DataGen#Cat-C1-C2-C3-Value}' ); // read from DataGen properties (3 values) def cata3 = context.expand( '${DataGen#Cat-A1-A2-A3-Value}' ); def catb3 = context.expand( '${DataGen#Cat-B1-B2-B3-Value}' ); def catAllMovies= context.expand( '${DataGen#Cat-AllMovies}' ); // Added a 4th so I can refine the assertions area dynamically below def datagenlist = [cata3, catb3, catc3, catAllMovies]; def cntdatagencategories = datagenlist.size(); //log.info " DATAGEN Category Count = $cntdatagencategories"; //log.info datagenlist; // Below line generated with RIGHT-CLICK to get count and getNodeValue code, tested and then commented out. //def response = context.expand( '${APP getCatalogOffering#Response#declare namespace ns1=\'urn:n2bb:OpenStreamVODModule_v31\'; declare namespace ns2=\'urn:n2bb:OpenStreamVODTypes_v31\'; //ns1:GetCatalogOfferingResponse[1]/ns1:offering[1]/ns2:metadataOverrides[1]/ns2:metadata[1]/@value}' ) //log.info " RESPONSE $response"; // get count of categories def cntcategories = holder["count(//ns1:GetCatalogOfferingResponse[1]/ns1:offering[1]/ns2:metadataOverrides[1]/ns2:metadata)"] as int; //log.info " RESPONSE Category Count = $cntcategories"; def aa = 1 as int; // must start at 1, not zero def addedcat = ""; // variable for found category def categorieslist = []; // empty array while (aa <= cntcategories) { addedcat = holder.getNodeValue("//ns1:GetCatalogOfferingResponse[1]/ns1:offering[1]/ns2:metadataOverrides[1]/ns2:metadata[$aa]/@value") // code returns categorieslist.add(addedcat); // add category to a list aa++ } cntcategories = categorieslist.size() as int; // give # of elements in the array //log.info categorieslist; //log.info cntcategories; log.info " ** ASSERTION ZONE **"; // Assert "DataGen Properties" == "APP getCatalogOffering#Response" // Array for DataGen = offeringcatlist // Array for get categories = categorieslist def cp = 0 as int; // Outside "while" control def pass = 0 as int; // default untested def fail = 0 as int; // default untested def alike = 0 as int; // need alike == both counts, else have failure def bb = ""; // used for the individual offering category from the array def cc = 0 as int; // Loop 3 control def dd = ""; // category def matlst= []; // matched list, as can not seem to make strings work very well def ee = 0 as int // matlst control def ff = 0 as int // matlst control def gg = 0 as int // matlst control def hh = ""; // matlst control while ((cntcategories == cntdatagencategories) && (cp < cntdatagencategories)) { //log.info " Outer Loop: $cp"; // loop through each offeringcatlist aa = 1; while (aa <= cntdatagencategories) { bb = datagenlist[aa -1]; // category from offering list cc = 1; // use for loop through categorieslist //log.info " Each offering category: $bb"; // loop through categorieslist and compare to individual offeringcatlist item (bb) while (cc <= cntcategories) { dd = categorieslist[cc -1]; if (bb =~ dd) { // CHECK PREVIOUS MATCH: Must use an array, as string matches do not behave very well unfortunately //log.info " Inside L3: $dd $curmat"; ee = 0; ff = 0; gg = 0; hh = ""; ff = matlst.size(); while ((ff) && (gg < ff)) { hh = matlst[gg]; if (hh =~ dd) { ee =1; // control to skip match below gg = ff; // skip reset of the loop, as have a match } gg++; } // Not previously matched, so now a valid match: add to matlist & set 2 variables to skip loops if (!ee) { //log.info " NEW MATCH: $bb $dd"; matlst.add(dd); alike++; cc = cntcategories; // will incr out below aa = cntdatagencategories; // will incr out below } } cc++; } aa++; } cp++; } log.info matlst; if (alike == cntcategories) { pass = 1; }else { pass = 0; fail = 1; } log.info "cntcategories = $cntcategories, alike = $alike, pass = $pass, fail = $fail"; // ** ASSERTION **// if (alike == cntcategories) { assert pass != fail; // pass will be "1" if all match; fail will be "0" if all pass } else { assert pass == fail; // pass will be "0" if all match; fail will be "1" if all pass } //****************// Log output ---------- Wed May 16 10:44:38 MDT 2012:INFO: ** ASSERTION ZONE ** Wed May 16 10:44:38 MDT 2012:INFO:[/A1/A2/A3, /B1/B2/B3, /C1/C2/C3, /All Movies] Wed May 16 10:44:38 MDT 2012:INFO:cntcategories = 4, alike = 4, pass = 1, fail = 0 Web Service Request <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:n2bb:OpenStreamVODModule_v31" xmlns:urn1="urn:n2bb:OpenStreamVODTypes_v31"> <soapenv:Header/> <soapenv:Body> <urn:GetCatalogOfferingRequest> <!--1 or more repetitions:--> <urn:offeringRef> <!--You have a CHOICE of the next 3 items at this level--> <urn1:offeringId>37963</urn1:offeringId> </urn:offeringRef> <urn:includeAssetMetadata>true</urn:includeAssetMetadata><urn:catalogId>0</urn:catalogId> <!--You have a CHOICE of the next 2 items at this level--> <!--Optional:--> <!--Optional:--> </urn:GetCatalogOfferingRequest> </soapenv:Body> </soapenv:Envelope> Web Service Response - some content removed ... <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Header/> <env:Body> <GetCatalogOfferingResponse xmlns="urn:n2bb:OpenStreamVODModule_v31" xmlns:ns2="urn:n2bb:OpenStreamVODTypes_v31"> <offering packageName="MyStdMOD-1" serviceName="MOD" modifiedTime="2012-05-16T16:23:17.717Z" createTime="2012-05-09T17:07:48.000Z" expirationDate="2012-11-07T07:00:00.000Z" startDate="2004-01-01T07:00:00.000Z" rentalDuration="86400" price="0" serviceType="MOD" type="MOD" offeringId="37963"> <ns2:description>MyStdMOD-1 TITLE Title</ns2:description> <ns2:metadataOverrides> <ns2:asset> <ns2:providerId>arrivo.com</ns2:providerId> <ns2:assetId>BDTL0001336583264616</ns2:assetId> </ns2:asset> <ns2:metadata value="/B1/B2/B3" name="MOD::Category"/> <ns2:metadata value="/A1/A2/A3" name="MOD::Category"/> <ns2:metadata value="/C1/C2/C3" name="MOD::Category"/> <ns2:metadata value="/All Movies" name="MOD::Category"/> </ns2:metadataOverrides> <ns2:offeringRef>37964</ns2:offeringRef> <ns2:packageAsset assetId="BDPK0001336583264616" providerId="arrivo.com" assetName="MyStdMOD-1" assetClass="PackageAsset"> <ns2:metadata value="arrivo1" name="MOD::Provider_Content_Tier"/> <ns2:metadata value="MOD" name="AMS::Product"/> <ns2:metadata value="2004-11-22" name="AMS::Creation_Date"/> </ns2:packageAsset> <ns2:titleAsset releaseYear="2003" rating="PG-13" runTime="3671" shortTitle="MyStdMOD-1" title="MyStdMOD-1 TITLE Title" assetId="BDTL0001336583264616" providerId="arrivo.com" assetName="arrivo.com::BDTL0001336583264616" assetClass="TitleAsset"> <ns2:metadata value="N" name="MOD::Closed_Captioning"/> <ns2:metadata value="TITLE Episode Brief" name="MOD::Episode_Name"/> <ns2:description>This is the TITLE Summary Short</ns2:description> <ns2:actor>Nick Actor</ns2:actor> <ns2:actor>Mark Actor</ns2:actor> <ns2:actor>Wilma Actor</ns2:actor> <ns2:actor>Lana Actor</ns2:actor> </ns2:titleAsset> <ns2:movieAsset bitRate="0" releaseYear="2003" rating="PG-13" runTime="3671" shortTitle="MyStdMOD-1" title="MyStdMOD-1 TITLE Title" assetId="BDMV0001336583264616" providerId="arrivo.com" assetName="arrivo.com::BDMV0001336583264616" assetClass="MovieAsset"> <ns2:metadata value="fr" name="MOD::Dubbed_Languages"/> <ns2:actor>Nick Actor</ns2:actor> <ns2:actor>Mark Actor</ns2:actor> <ns2:actor>Wilma Actor</ns2:actor> <ns2:actor>Lana Actor</ns2:actor> </ns2:movieAsset> <ns2:viewingWindow> <ns2:startDate>2004-01-01T07:00:00.000Z</ns2:startDate> <ns2:endDate>2012-11-07T07:00:00.000Z</ns2:endDate> </ns2:viewingWindow> <ns2:deliveryType> <ns2:deliveryMethod>dsmcc-openstream-streaming</ns2:deliveryMethod> <ns2:deliverableAssetClass> <ns2:assetClass>MovieAsset</ns2:assetClass> </ns2:deliverableAssetClass> </ns2:deliveryType> <ns2:deliveryType> <ns2:deliveryMethod>rtsp-openstream-streaming</ns2:deliveryMethod> <ns2:deliverableAssetClass> <ns2:assetClass>MovieAsset</ns2:assetClass> </ns2:deliverableAssetClass> </ns2:deliveryType> </offering> </GetCatalogOfferingResponse> </env:Body> </env:Envelope>Custom Logging in Groovy ScriptObjective: Simple General File Logging Use: General in Groovy Scripts What Will This Logging Do? Capture the REQUEST & RESPONSE of each Web Service //**TestCase Properties **// logDirectoryName = C:\Users\Dave\Documents\SoapUI-Logs\ testCaseLogFileName = createPurchaseStreamingURL //** LOG FILE DEFINITION - Place somewhere at the top of the script **// def logDirectoryName = context.expand( '${#TestCase#logDirectoryName}' ) def testCaseLogFileName = context.expand( '${#TestCase#testCaseLogFileName}' ) def filext = ".log"; def fn = "$logDirectoryName$testCaseLogFileName$filext" def FileName = new PrintWriter( new FileWriter(fn)); // Add for optional timestamp logging def sdf = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); def myTime = ""; //** GENERIC LOGGING FOR STEPS RUN **// def numberOfSteps = testRunner.testCase.getTestStepCount(); //just a bonus piece of our logging to show step count if (dEBUG != 0 ) {log.info "Step Count = $numberOfSteps"} // Print out to review it def eaStep = ""; testRunner.testCase.getTestStepList().each() { eaStep = it.getName() if (dEBUG != 0 ) {log.info " This step = $eaStep"} //Print out so you can see the step names // You want to skip STEPS that are not Web Service Requests if ((eaStep =~ 'Groovy') || (eaStep =~ 'DataGen') ||(eaStep =~ 'Property Transfer')) { // Enhance as neede to skip more types of steps // We just skip this area //log.info(it.getName()) } else { //Here we generate just a list of WEB SERVICE STEPS. log.info(it.getName()) // can print to screen if U want. Comment out when done testing it. def request = testRunner.testCase.getTestStepByName( "$eaStep" ); // Get the WS def req = request.getProperty( "Request" ); // Get the request of the WS def resp = request.getProperty( "Response" ); // Get the response of the WS FileName.println( "$eaStep - Request:" ); // Print WS Name & Request: FileName.println( req.value ); // Print WS request FileName.println( "$eaStep - Response:" ); // Print WS Name & Response: FileName.println( resp.value ); // Print WS respone } } //** END OF GENERIC LOGGING **// //** Close Everything **// FileName.flush(); FileName.close(); //** Your Output **// Has now been written to a file. //** Option Timestamp Logging around a STEP **// myTime = sdf.format( new Date());FileName.println( "$myTime Start getOffering" ); //timestamp testRunner.runTestStepByName("getOffering"); // step myTime = sdf.format( new Date());FileName.println( "$myTime End getOffering" ); //timestampRe: Groovy Script Loop HOWTOMore enhanced Query Select with ROWNUM <= NN: //Testcase property def scriptLIMIT = context.expand( '${#TestCase#LIMIT}' ) sql.eachRow("select * from (select service_name from service where admin_state_id = 2 order by service_name)tmp where ROWNUM <= ${scriptLIMIT}") { row -> The query will now output "order by service_name" will output from the beginning.Re: trim from sql select statement solutionMay have quickly found my own solution. 1. Save to property testRunner.testCase.setPropertyValue( "AssetType", "$row.name" ) 2. Retrieve property and add trim to it. Seems to work. def assetType = context.expand( '${#TestCase#AssetType}' ).trim() log.info "|$assetType|" Tue Jan 10 10:46:15 MST 2012:INFO:|MovieAsset|trim from sql select statement solutionI have looked everywhere for this solution, but do not see it. Can not use "trim(at.name) as it gives an error = invalid column name Using "oracle.jdbc.driver.OracleDriver" sql.eachRow("select Distinct(ho.OFFERING_ID), adt.delivery_method, at.asset_type, at.name from h_offering ho, offering_delivery_type odt, asset_delivery_type adt, asset ass, asset_type at where ho.service_type = 1 and odt.offering_name = ho.offering_id and adt.delivery_type_id = odt.delivery_type_id and ass.asset_id = adt.asset_id and at.asset_type = ass.asset_type and ho.deleted_flag = 0 and ROWNUM <= ${scriptLIMIT} order by ho.offering_id, adt.delivery_method") { row -> log.info " $row.offering_id | $row.delivery_method | $row.asset_type | $row.name |"; Tue Jan 10 10:08:58 MST 2012:INFO: 3322 | dsmcc-openstream-streaming | 2 | MovieAsset | Need to trim $row.name so it can be easily used here: if (offeringStatusMovie == 'MovieAsset') { ... } Prefer to have a clean solution, as these testsuites passed on to QA groups w/less technical skill. Any thoughts? Thanks,Re: Testing multiple SOAPUI Projects or Services rajash wrote: Hi, Create a New Project with any one WSDL. To the same project Right click and add all the other wsdls. Remane the project as desired. Now all the operations of all wsdl's will be deplayed with in this project. Choose which ever operation you would need from each wsdl, right click on each request and add to TestSuite. Hope this helps, Sorry if i got your question wrong. Thanks, Raj Wow it works! This is amazing and it will add unlimited abilities to our testing. In less than 5 minutes we have 3 separate WSDLs combined under one project. Thanks!Re: setup script for a database connectionSolution is fairly simple, if you have the right pieces (based on what I have gathered / tested / used recently): Below is what we are using for a DB connection to Oracle. You can edit for your DB type. Make sure you also have JDBC connection properly configure. Note we define our DB connection properties at the TESTSUITE level. Groovy Script ------------- // Database connection: // All these properties are defined at the TEST SUITE LEVEL // Properties used: // DenServer25 // Password // sid // Database // DBport // Extract global property value as local Variables def scriptDenServer25 = context.expand( '${#TestSuite#DenServer25}' ) def scriptPassword = context.expand( '${#TestSuite#Password}' ) def scriptSid = context.expand( '${#TestSuite#sid}' ) def scriptDatabase = context.expand( '${#TestSuite#Database}' ) def scriptDBport = context.expand( '${#TestSuite#DBport}' ) //** DVA 12-28-11 Resolve db connection **// import groovy.sql.Sql import com.eviware.soapui.support.GroovyUtils log.info "Connecting to DB here"; com.eviware.soapui.support.GroovyUtils.registerJdbcDriver("oracle.jdbc.driver.OracleDriver") //***************************************// log.info "Running Query for TestCase1 - DBConnection R&D"; sql = Sql.newInstance("jdbc:oracle:thin:@${scriptDenServer25}:${scriptDBport}:${scriptSid}", "${scriptDatabase}", "${scriptPassword}", "oracle.jdbc.pool.OracleDataSource") // **TESTCASE** // def scriptMOD = context.expand( '${#TestCase#MOD}' ) def scriptLIMIT = context.expand( '${#TestCase#LIMIT}' ) // **MAIN QUERY ** // def aa = 0 def bb = 0 sql.eachRow("select my_id from mytable where type = ${scriptMOD} and deleted_flag = 0 and ROWNUM <= ${scriptLIMIT} order by my_id") { row -> //set property to value from row selected testRunner.testCase.setPropertyValue( "dbmyID", "$row.MY_ID" ) //log.info "Set Property dbofferingID = $row.OFFERING_ID"; // Now run desired test steps. Must send each individually. testRunner.runTestStepByName("Property Transfer to getCatalogOffering"); testRunner.runTestStepByName("getCatalogOffering"); bb++ } log.info "Records Processed = $bb"; sql.close()Re: Groovy Script Loop HOWTOI am not too sure why you loop continually. Also, I am not sure why you don't have a goto as your 1st step. I would do something like this: Define AssetID property TestCase. 1. Groovy Script-Goto 2. Property transfer 3. Soap request (getAsset) 4. Groovy Script Loop #1 only has one line in it: testRunner.gotoStepByName( "Groovy Script - Main Loop") #4 Groovy Script Loop: def aa =0 while (aa < 3) { aa++ // set property (which you defined in the testcase property) testRunner.testCase.setPropertyValue( "AssetID", "$aa" ) testRunner.gotoStepByName( "Property transfer") //property transfer gets AssetID and sets it into the getAsset step testRunner.gotoStepByName( "getAsset") log.info "aa = $aa"; } log.info "Records Processed = $aa"; See if this help, DaveGroovy Script Loop HOWTOThis will be a quick HOWTO with hopes of adding much more shorty. 1. Set variables at the TESTSUITE level. Double-click on testsuite, click on properties in the bottom of the larger window. Set things like DB login here. 2. Set testcase-related variables at the TESTCASE level. Use same process. 3. Test Steps (basic): Datagen File Groovy Script - Goto Property Transfer TestStepA TestStepB Groovy Script - Main Loop 4. Groovy Script - Goto (a single line is all that is necessary) testRunner.gotoStepByName( "Groovy Script - Main Loop") 5. Groovy Script - Main Loop Below is an actual script which has been modified to not show private information, but it is A FULLY FUNCTIONAL SCRIPT. You should be able to COPY THIS SCRIPT AS-IS and modify for your needs. // Database connection: // All these properties are defined at the TEST SUITE LEVEL // Properties used: // DenServer25 // Password // sid // Database // DBport // Extract global property value as local Variables def scriptDenServer25 = context.expand( '${#TestSuite#DenServer25}' ) def scriptPassword = context.expand( '${#TestSuite#Password}' ) def scriptSid = context.expand( '${#TestSuite#sid}' ) def scriptDatabase = context.expand( '${#TestSuite#Database}' ) def scriptDBport = context.expand( '${#TestSuite#DBport}' ) //** Resolve db connection **// import groovy.sql.Sql import com.eviware.soapui.support.GroovyUtils.* log.info "Connecting to DB here"; com.eviware.soapui.support.GroovyUtils.registerJdbcDriver("oracle.jdbc.driver.OracleDriver") //***************************************// log.info "Running Query for TestCase - My R&D"; sql = Sql.newInstance("jdbc:oracle:thin:@${scriptDenServer25}:${scriptDBport}:${scriptSid}", "${scriptDatabase}", "${scriptPassword}", "oracle.jdbc.pool.OracleDataSource") // **TESTCASE** // def scriptMOD = context.expand( '${#TestCase#MOD}' ) def scriptLIMIT = context.expand( '${#TestCase#LIMIT}' ) // **MAIN QUERY ** // def aa = 0 def bb = 0 sql.eachRow("select offering_id from h_offering where service_type = ${scriptMOD} and deleted_flag = 0 and ROWNUM <= ${scriptLIMIT} order by offering_id") { row -> testRunner.testCase.setPropertyValue( "dbofferingID", "$row.OFFERING_ID" ) log.info "Set Property dbofferingID = $row.OFFERING_ID"; // Now run desired test steps. Must send each individually. testRunner.runTestStepByName("Property Transfer to ABC"); testRunner.runTestStepByName("getMyStuff"); //** Add loop to only run a step one time **// while (aa < 1) { testRunner.runTestStepByName("getAuth"); testRunner.runTestStepByName("isAct"); testRunner.runTestStepByName("getAuthServ"); aa++ } //******************************************// testRunner.runTestStepByName("Delete It"); bb++ } log.info "Records Processed = $bb"; sql.close() // END OF GROOVY SCRIPT - MAIN LOOP // 6. DESIGN THEORY: a. The objective is a compact Test Suite / Test Case which connects to a database for all it's looping data. This of course eliminated HARD-CODED most source data. b. Before you can use this design, you must understand properties at the TESTSUITE & TESTCASE level. c. TESTSUITE properties provide DATABASE CONNECTIONS. d. TESTCASE properties allow setting and retrieval of values within the testcase. This provides the real power for the looping process. e. First you build a teststep for Datagen static values. f. Next you add a "Groovy Script-Goto" teststep. g. Next add two simple (and known) teststeps. h. Now add the "Groovy Script - Main Loop" teststep. i. Now edit this script and make it run. j. For now, I am not going to explain this script, as it already has lots of comments. LEARNING LOOP DESIGN This was not easy, in fact it took weeks of research, trial-n-error and failure before everything in it was mastered. Have fun!