Forum Discussion

richie's avatar
richie
Community Hero
7 years ago

Extract specific string value from whole string contained within a Datasource Property

Hi to all,

 

I have a flat | delimited file (see below for format) that I need to parse for a specific value and extract it to a property so I can use it later in my test

 

file contents as below:

CustRefID|title|firstname|lastname|addressline1|addressline2|addressline3|postcode
ID0000001|MR|RICH|JONES|5 WHATEVER WAY|HODGE HILL|BIRMINGHAM|B36 9LB
Rows=1

I'm extracting the file contents using the Datasource - Directory type (to minimise the groovyscript) and assigning the file contents to a fileContents property. I am using the fileContents property later in a POST request (by posting the whole string in the fileContents property) to the webservice.

 

HOWEVER - I need to parse the fileContents property for a particular value (my CustRefID attribute value) within the file, so I can add in a GET request after my POST to query the webservice to check the POST was successful - I need the CustRefID value that was submitted in the POST. I understand I can do this from the response probably more easily than extracting it from the testdata, however, there are reasons why I'm not allowed to do that, so I MUST extract the value from the testdata.

 

So I'm expecting my testcase to look something like the following:

 

Directory (Datasource) - sourcing files of particular type from the directory. I have a fileContents property setup to hold the file contents
Groovy step - (to parse the fileContents property to extract the CustRefId value)
REST POST step - (posting the fileContents property to the web service)
REST GET step- (querying the webservice (using the CustRefID value) to ensure the POST was successful)
Datasource Loop step - (looping round for the next file in my Directory Datasource)

 

I should highlight that I need to preserve the header record and the footer record in my REST requests, which is one of the reasons I'm going for the above approach despite loads of help from Rao, Radford, msiadak, and IgorG.

 

 

The below is courtesy of Rao from another post I made - I'm hoping its fairly straightforward to alter the code below

 

def lines = new File('data.txt').readLines()  // need to change this line to read the contents of the fileContents property???
lines.eachWithIndex { line, index ->
    if (index) {
    	def data = line.split('|')*.trim()
	log.info data[0]   //need to alter this SOMEHOW to pick out the CustRefID value         	   
    }	    	
}

 

I'm pretty sure the line.split will do it - but my reading is only taking me so far at the moment.

 

I can see the above is reporting the first character on lines 2 and 3 of the file - I've tried playing with the script myself but I'm struggling. Could anyone point me in the right direction?

 

Essentially - I need to parse the fileContents property (created in the Directory - Datasource object) to pull out the CustRefID value.

 

I've attached my project file in case this helps clarify.

 

As always - many thanks to all/anyone who can help - I do appreciate that you are helping me doing my job for me!

 

richie

13 Replies

  • nmrao's avatar
    nmrao
    Champion Level 3
    With the above script, data[0] (here 0 represents the index of the column)contains CustRefID of each line.

    Not sure what exactly the further.
    Is that you need to ignore the last line (Rows=1) which is not actual data?

    Then you change it from:
    if (index) {
    to:
    if (index && (lines.size() != index+1)) {
    • richie's avatar
      richie
      Community Hero

      Hey Rao,

       

      I'm sorry - I'm not being clear enough in my descriptions.

       

      I already have a datasource with a filecontents property (which holds the whole file contents).  What I need is ANOTHER test step (I'm guessing using groovy) to pick out the CustRefID attribute value from the file, as I have a GET step that uses the CustRefID in the GET request to confirm the POST was successful.

       

      I am expecting my TestCase to look like the following

       

       

      DataSource - DirectoryType (fileContents property)
      GroovyStep <-- to extract the CustRefID value from the fileContents property POST /path/synchronous-upload <-- this POST publishes the fileContents property GET /path/contact?CustRefID=${#TestCase#CustRefID}

       

       

      I can't rely on the POST response providing the CustRefID, to extract to pass onto the GET request, so I need to extract it (I think) from the fileContents property

       

      The file contents are as follows:

       

      CustRefID|title|firstname|lastname|addressline1|addressline2|addressline3|postcode
      ID0000001|MR|RICH|JONES|5 WHATEVER WAY|HODGE HILL|BIRMINGHAM|B36 9LB
      Rows=1

      Your original script was as follows:

       

      def lines = new File('D:\\Donor Marketing\\SoapUI\\nongroovyscriptfile\\New Text Document.dat').readLines()
      lines.eachWithIndex { line, index ->
          if (index) {
          	def data = line.split('|')*.trim()
      	log.info data[0]            	   
          }	    	
      }

       

      When I ran your original script - an 'Information' dialogue appears with the whole file contents displayed, and the info in the log output reports the following:

       

      Tue May 23 10:46:56 BST 2017:INFO:I
      Tue May 23 10:46:56 BST 2017:INFO:R

      As you can see - it appears the script is logging the first character of every line after the header row.

       

       

      I am hoping I can change your script to capture the whole value of 'ID000001' so I can pass it to the GET request later in my test case.

       

      In summary - I'm hoping you can help editing your script so that it parses the fileContents property and captures the 'ID0000001'

       

      I did edit your script to the following:

       

      def lines = new File('D:\\Donor Marketing\\SoapUI\\nongroovyscriptfile\\New Text Document.dat').readLines()
      lines.eachWithIndex { line, index ->
          if (index) {
          	def data = line.split('|')*.trim()
      	log.info data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]         	   
          }	    	
      }

       and the logging was as follows:

       

      Tue May 23 10:46:56 BST 2017:INFO:ID0000001
      Tue May 23 10:46:56 BST 2017:INFO:Rows=1nullnullnull

       

      I only need to capture the ID0000001 value - so that I can pass it to the GET Request.

       

       

      I hope I've been clear - at this point, I need to edit the script to parse the fileContents property (rather than from the directory as the script currently is doing (because I'm going to use a Datasource of Directory type with lots of files to cycle through) and to ONLY capture the ID0000001 value.

       

      Many, many thanks to all, and especially Rao,

       

      richie

      • groovyguy's avatar
        groovyguy
        Champion Level 1

        Try changing

         

            	def data = line.split('|')*.trim()

        to

         

            	def data = line.tokenize('|');

        That may work better for harvesting the first item out of every column. 

    • nmrao's avatar
      nmrao
      Champion Level 3

      richie,

       

      Usually I try before providing the code snippet. Looks this case I was lazy to do so as split would do the job with |, but it requires escaping.  Sorry about it.

       

      So here is the change code, this would also take care of additional row in the last line:

       

      def lines = new File('/tmp/data.txt').readLines()
      lines.eachWithIndex { line, index ->
           if (index && (lines.size()-1 != index)) { // handles extra unwanted last line
          	def data = line.split('\\|')*.trim()
      //CustRefID field's index 0
      	log.info data[0]
          }	    	
      }

      Now, it appears that you wanted to do the further processing with each CustRefID? In that case

       

      Hope you can alter the step sequence as below

       

      DataSource - DirectoryType (fileContents property)
      POST /path/synchronous-upload     <-- this POST publishes the fileContents property

      GroovyStep    <-- to extract the CustRefID value from the fileContents property
        for each CustRefID
           save CustRefID at test case level
           run step from with in groovy step ==> GET /path/contact?CustRefID=${#TestCase#CustRefID}