Tuesday, January 31, 2012

JMeter quick start guide (part 3)

--------------------------
3. Setting up data and running a test
--------------------------

Update the test file (.jmx) to use the variables from your .csv files.

This is by no means the only way to do this, I've just found it best because the JMeter GUI kind of sucks. There is no Find that I know of and for a big test you may have hundreds of HTTP requests to look through to find the one(s) that contain your variables. It's probably good to look for the one with the login (since it should be near the top of the list of HTTP requests) and see what it looks like in the GUI before and after you open the .jmx and do your search/replace. It should be clear that all the GUI is doing is showing the fields saved in the .jmx and is really pretty transparent as far as 1 request in the .jmx mapping to one HTTP Request screen in the GUI, and all the inputs map directly to xml elements (like Server Name in the GUI mapping to "HTTPSampler.domain").

  1. open the test .jmx file with a good editor such as Textpad
  2. update the hostname so that you can point the test at a different server at a later date
    1. search the .jmx for your server name or for HTTPSampler.domain. should find a line that looks like: myApp.com
    2. do a global replace of myApp.com with ${HOSTNAME}
      1. hopefully myApp.com will not appear any where else in the .jmx. It shouldn't, but it may be safer to replace something like HTTPSampler.domain">myApp.com with HTTPSampler.domain">${HOSTNAME}
  3. update any inputs you gave during the recording session (username, password, report name, etc.)
    1. search the .jmx for the username you put in, let's say it's "myUser"
    2. replace this single instance of myUser with ${IU_01_USER} (this is the name of the USER variable we chose when setting up the .csv file (see earlier in this documentation))
    3. do the same for password
    4. remember when you're searching that any spaces you used in inputs (like the name of a partner you created) will look like:
      1. My+Company+Name
      2. I just avoid spaces all together and use underscores as spaces
    5. when we set up our Thread Group earlier all we set up was username and password but for other simple inputs such as report name it may be a little trickier. For example when I recorded running a simple report (no inputs to the report) I had to search for the report name a couple times to find it (it was selected from a dropdown, not typed in a text field):
      1. I found this block, which is typical:
      2. <elementProp name="reportType" elementType="HTTPArgument">
        <boolProp name="HTTPArgument.always_encode">false</boolProp>
        <stringProp name="Argument.name">reportType</stringProp>
        <stringProp name="Argument.value">institution-order-report</stringProp>
        <stringProp name="Argument.metadata">=</stringProp>
        </elementProp>

      3. so I would replace this single instance of institution-order-report with the ${IU_01_REPORT_NAME}
    6. for other more complex inputs, it's the same basic idea, for example when I recorded running a report that took several inputs I had to replace several things. Let's say I wanted to keep the report name the same, but parametrize the inputs (institution id, start date...):
      1. After I found the report name, I find the adjacent elements being sent in the HTTP request such as
      2. <elementProp name="institutionId" elementType="HTTPArgument">
        <boolProp name="HTTPArgument.always_encode">false</boolProp>
        <stringProp name="Argument.name">institutionId</stringProp>
        <stringProp name="Argument.value">8a5c510e2905229e0129055a035f000c</stringProp>
        <stringProp name="Argument.metadata">=</stringProp>
        </elementProp>
        <elementProp name="startTime" elementType="HTTPArgument">
        <boolProp name="HTTPArgument.always_encode">false</boolProp>
        <stringProp name="Argument.name">startTime</stringProp>
        <stringProp name="Argument.value">12312010</stringProp>
        <stringProp name="Argument.metadata">=</stringProp>
        </elementProp>

      3. so I would replace this single instance of 8a5c510e2905229e0129055a035f000c with ${IU_01_INSTITUTION_ID} and this single instance of 12312010 with ${IU_01_START_TIME}
    7. there are also JMeter-defined variables such as ${_time(YMDHMS)} and ${_threadNum} which you can use inline with your text such as
      1. jmeter_test_${__time(YMDHMS)}
  4. verify in the GUI a few things that you updated in the .jmx
    1. in your thread group, look for a request for /j_spring_security_check and click on it (Edit: this is a page name specific to our app, so yours will likely be different)
    2. look in the Send Parameter With the Request section and you should see your updated values being send for username and password

Create some .csv data input files

Filenames are those we chose when setting up the .csv files (see earlier in this documentation):

  1. update .csv files
    1. Create HOSTNAME.csv
      1. a single line containing your server's address (such as 1.2.3.4 or www.myApp.com)
    2. Create IU_01.csv
      1. Earlier in this documentation when we set up the Thread Group we set up the CSV Data Set Config element to have username and password in this data file. In that case the data would look like (for example):
        1. userJoe, abc123
          userSusi, xyz987
          userAlan, ijk345
    3. More complex .csv files (for example report name):
      1. You could have the users and the report names in 1 file, making the file look like:
        1. userJoe, abc123, dailyReport
          userSusi, xyz987, monthlyReport
          userAlan, ijk345, yearlyReport
        2. If you modify the file to include this new report name column, you would need to
          1. search/replace the actual report name with ${IU_01_REPORT_NAME} in the .jmx as describe above
          2. update the CSV Data Set Config element as described when we set up the Thread Group earlier in this documentation, adding IU_01_REPORT_NAME to the end of the Variable Names list
      2. Or you could have the users and the report names in separate files, using the username, password file from above and a report file (doesn't need to have the same number of lines) which would just look like:
        1. dailyReport
          weeklyReport
          monthlyReport
          quarterlyReport
          yearlyReport
        2. if you add a new file with the report name, you would need to
          1. search/replace the actual report name with ${IU_01_REPORT_NAME} in the .jmx as describe above
          2. add a new CSV Data Set Config element as described when we set up the Thread Group earlier in this documentation

Setting up the App server:

  1. Disable XSS attack prevention:
    1. Our app uses DWR (a Java lib that implements Ajax), and the DWR requests made from JMeter fail due to a cross-site scripting attack prevention feature in Spring(?). To turn the feature off, add the crossDomainSessionSecurity param to the dwr-invoker servlet in web.xml.
    2. web.xml should be somewhere like /opt/ntc/jetty/webapps/root/WEB-INF on the app server. Add the 4 lines that define the corssDomainSessionSecurity init parameter:

    3. <servlet>
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
      <init-param id="dwrInvoker-debug">
      <param-name>debug</param-name>
      <param-value>true</param-value>
      </init-param>
      <init-param id="dwrInvoker-scriptCompressed">
      <param-name>scriptCompressed</param-name>
      <param-value>false</param-value>
      </init-param>
      <init-param>
      <param-name>crossDomainSessionSecurity</param-name>
      <param-value>false</param-value>
      </init-param>
      </servlet>

Running a test locally:

  1. There are two ways to run:
    1. Through the GUI: go to Run -> Start
      1. produces the JMeter log file: jakarta-jmeter-2.3.4/bin/jmeter.log
      2. produces the output .csv: jakarta-jmeter-2.3.4/data/output/out_graph_results.csv (which is what we specified when setting up the Graph Results element)
    2. Command line (probably a better idea since it requires less resources than the GUI)
      1. cd .../jakarta-jmeter-2.3.4/data (where the .jmx files are)
      2. jmeter -n -t myTestFile.jmx -j output/jmeterlogfile.log -l output/logfile.log
      3. produces the JMeter log file: jakarta-jmeter-2.3.4/data/output/jmeterlogfile.log
      4. produces the output .csv: jakarta-jmeter-2.3.4/data/output/out_graph_results.csv
      5. produces an XML version of the output .csv: jakarta-jmeter-2.3.4/data/output/logfile.csv
  2. After the test, move or rename the output file created by the Graph Results element. If you run the test twice, it will simply append to the old output file (and we don't want that). The graph in the Graph Results element will also just append. It's not an extremely helpful graph in my experience.
  3. View:
    1. the output .csv (in Excel) and if you're seeing "Non HTTP response code" all over the place you probably have a config issue (or your app is down). For example if you see "Non HTTP response message: ${HOSTNAME}" then your HOSTNAME.csv isn't being read properly
    2. the JMeter log file has lots of good info. You should be able to search for the names of your input .csv files and see whether they were stored or not found.
  4. Tweaking:
    1. It may take several tries to get it to run in a way that simulates a user well. If you're running a report, you'll need to check the app logs to see that the user successfully logged in and that report code is running (hopefully in debug mode, telling you what is being executed) and/or check a temp folder where the generated report may be stored
    2. Be sure to tweak the Uniform Random Timer in your Thread Group to slow down the rate that JMeter is firing off requests so that it's consistent with how a human user would use the system.
    3. Check the other Thread Group options (Number of Threads, Loop Count, etc.) to make sure they still make sense with the data set you've defined

Running a test on the JMeter server:

  1. The JMeter server is an Amazon image with the name XXXXXXX.net
  2. Base dir is ~/jakarta-jmeter-2.3.4
  3. Scripts are in ~/scripts
  4. Other dirs are set up the same way we have set up our local environment
  5. Ftp your .jmx and input .csv or other files to their respective dirs
  6. To run:
    1. Putty in as user ntc
    2. cd ~/jakarta-jmeter-2.3.4/data
    3. jmeter -n -t myTestFile.jmx -j output/jmeterlogfile.log -l output/logfile.log

No comments:

Post a Comment