xmljmeterjmeter-plugins

How to send random number of XML blocks with each jmeter sampler


I have a sampler with below XML post body,

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Body>
    <GetSoapRequest xmlns="http://www.demandmatrix.net/HBSIXML4/">
      <InterfacePayload>
        <ChannelIdentifierId>Dnata_XML4R</ChannelIdentifierId>
        <Version>2005A</Version>
        <Interface>HBSI XML 4 OTA</Interface>
        <TimeOut>30</TimeOut>
      </InterfacePayload>
      <Message>
        <RequestId>20220728122327zQOxgSf6ZQ</RequestId>
        <Transaction>HotelRateAmountNotifRQ</Transaction>
        <XML>
                    &lt;OTA_HotelRateAmountNotifRQ xmlns="http://www.abcd.org/ORR/2003/05" TimeStamp="2022-07-28T12:23:27+00:00" Target="TEST" Version="1.003" PrimaryLangID="en-us" HotelCode="${HotelCode9}" HotelCityCode="XYZ" HotelName="abc_Hotel"&gt;
                        &lt;POS&gt;
                            &lt;Source&gt;
                                &lt;RequestorID Type="abc" ID="abc"/&gt;
                                &lt;BookingChannel Type="2" Primary="true"&gt;
                                    &lt;CompanyName&gt;abc&lt;/CompanyName&gt;
                                &lt;/BookingChannel&gt;
                            &lt;/Source&gt;
                        &lt;/POS&gt;
                        &lt;RateAmountMessages HotelCode="${HotelCode9}" HotelCityCode="MEL" HotelName="XYZ"&gt;
  &lt;RateAmountMessage LocatorID="1"&gt;
    &lt;StatusApplicationControl Override="1" RatePlanCodeType="RatePlanCode" InvCodeApplication="InvCode" IsRoom="1" Start="${__timeShift(yyyy-MM-dd ,,P${StartDate9}D,,)}" End="${__timeShift(yyyy-MM-dd ,,P${EndDate9}D,,)}" RatePlanCode="${RatePlanCode9}" InvCode="${RoomCode9}" /&gt;
    &lt;Rates&gt;
      &lt;Rate NumberOfUnits="1" RateTimeUnit="Day" UnitMultiplier="1"&gt;
        &lt;BaseByGuestAmts&gt;
          &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${AdultPrice9}" AmountAfterTax="${__jexl2(${AdultPrice9}+(${AdultPrice9}*${Tax9}))}" NumberOfGuests="1" AgeQualifyingCode="10" /&gt;
          &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*2*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*2*${PercentIncreasePerGuest9}+${AdultPrice9}*2*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="2" AgeQualifyingCode="10" /&gt;
          &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*3*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*3*${PercentIncreasePerGuest9}+${AdultPrice9}*3*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="3" AgeQualifyingCode="10" /&gt;
          &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*4*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*4*${PercentIncreasePerGuest9}+${AdultPrice9}*4*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="4" AgeQualifyingCode="10" /&gt;
        &lt;/BaseByGuestAmts&gt;
      &lt;/Rate&gt;
    &lt;/Rates&gt;
  &lt;/RateAmountMessage&gt;
&lt;/RateAmountMessages&gt;
                    &lt;/OTA_HotelRateAmountNotifRQ&gt;
                </XML>
      </Message>
      <Login>
        <LoginType>Component</LoginType>
        <ComponentInfo>
          <ComponentType>Hotel</ComponentType>
          <Id>${HotelCode}</Id>
          <User>abc</User>
          <Pwd>hu@QTUls#*3U2C$Yt0Ni</Pwd>
        </ComponentInfo>
      </Login>
    </GetSoapRequest>
  </soap:Body>
</soap:Envelope>

There are two requirements,

  1. I need to send random number (any number from 1 to 50) of messages (Message is in above post body from line#25 to line#37 i.e tag name as 'RateAmountMessage') with each sampler. For example 1 request can have 5 messages, next request can have 10 messages.
  2. Now once we have the post body ready with different number of messages (lets say 10 messages), each message will read the dynamic values (i.e StartDate9, EndDate9, RatePlanCode9, RoomCode9, AdultPrice9, Tax9) from a csv. For example first message will take the values from 1st line of csv, 2nd message will take the values from 2nd line of csv and so on.

csv file is as below,

95106,BAR1,Double Deluxe Room,142,162,25.1,5,0.9,0.1
95106,BAR2,Double Deluxe Room,142,162,35.2,10,0.9,0.1
95106,BAR3,Double Deluxe Room,142,162,45.3,15,0.9,0.1
95106,BAR4,Double Deluxe Room,142,162,55.4,20,0.9,0.1
95106,BAR5,Double Deluxe Room,142,162,65.5,25,0.9,0.1
95106,BAR1,Double Room,142,162,75.6,30,0.9,0.1
95106,BAR2,Double Room,142,162,85.7,35,0.9,0.1
95106,BAR3,Double Room,142,162,95.8,40,0.9,0.1

We tried doing this with with the help of jsr223, but its not picking up the values from the csv, also not able to resolve __jexl2 function. I am using Jmeter 5.6.3 Can someone please help on this!


Solution

  • You can add a JSR223 PreProcessor and use the code like:

    def message = '''
                        &lt;RateAmountMessage LocatorID="1"&gt;
                        &lt;StatusApplicationControl Override="1" RatePlanCodeType="RatePlanCode" InvCodeApplication="InvCode" IsRoom="1" Start="${__timeShift(yyyy-MM-dd ,,P${StartDate9}D,,)}" End="${__timeShift(yyyy-MM-dd ,,P${EndDate9}D,,)}" RatePlanCode="${RatePlanCode9}" InvCode="${RoomCode9}" /&gt;
                        &lt;Rates&gt;
                        &lt;Rate NumberOfUnits="1" RateTimeUnit="Day" UnitMultiplier="1"&gt;
                        &lt;BaseByGuestAmts&gt;
                        &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${AdultPrice9}" AmountAfterTax="${__jexl2(${AdultPrice9}+(${AdultPrice9}*${Tax9}))}" NumberOfGuests="1" AgeQualifyingCode="10" /&gt;
                        &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*2*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*2*${PercentIncreasePerGuest9}+${AdultPrice9}*2*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="2" AgeQualifyingCode="10" /&gt;
                        &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*3*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*3*${PercentIncreasePerGuest9}+${AdultPrice9}*3*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="3" AgeQualifyingCode="10" /&gt;
                        &lt;BaseByGuestAmt CurrencyCode="USD" AmountBeforeTax="${__jexl2(${AdultPrice9}*4*${PercentIncreasePerGuest9})}" AmountAfterTax="${__jexl2(${AdultPrice9}*4*${PercentIncreasePerGuest9}+${AdultPrice9}*4*${PercentIncreasePerGuest9}*${Tax9})}" NumberOfGuests="4" AgeQualifyingCode="10" /&gt;
                        &lt;/BaseByGuestAmts&gt;
                        &lt;/Rate&gt;
                        &lt;/Rates&gt;
                        &lt;/RateAmountMessage&gt;'''
    
    def randomNumber = org.apache.commons.lang3.RandomUtils.nextInt(1, 51)
    def messages = new StringBuilder()
    
    1.upto(randomNumber, { index ->
        def lineFromCSV = new File('/path/to/your/file.csv').readLines().get(index - 1)
        //do what you need with CSV file here
        messages.append(message)
    })
    
    vars.put('messages', messages.toString())
    

    and then replace post body from line#25 to line#37 with ${messages}

    See Apache Groovy: What Is Groovy Used For? article for more information on Groovy scripting in JMeter.

    __jexl2() function works fine in JMeter 5.6.3:

    enter image description here