Sign In/My Account | View Cart  
advertisement

Load Testing Web Services with Grinder

   Print.Print
Email.Email weblog link
Discuss.Discuss
Blog this.Blog this
Jim Alateras

Jim Alateras
Mar. 23, 2005 04:51 AM
Permalink

Atom feed for this author. RSS 1.0 feed for this author. RSS 2.0 feed for this author.

Since finishing the first version of the Work Manager web service I have been looking at load test tools. During my search I revisited a load test framework called Grinder.

I first came across Grinder a year or so ago but never got beyond installing it on my machine. The latest version, which is still in beta, has a lot of new features, including support for the Jython scripting engine. The latest version also has a console, which collects and displays timing information generated by the load tests.

First impressions have been very positive indeed. I was able to install and run a simple Jython-scripted example in less that 1 hour. After one day with Jython and Grinder I was able to leverage some existing JUnit test cases to do some ad hoc load testing on my web service.

Initial contact with Jython has also been very positive and I intend on learning more about this scripting language. I found the Introduction to Jython Part 1 and Part 2 tutorials, from IBM devWorks, very useful.

Below is a simple Jython test script, which can be executed by Grinder. (Check the Grinder Tutorial for more details)


from net.grinder.script import Test;
from net.grinder.script.Grinder import grinder;
from com.comware.wm.test.rest.load import RestWorkManagerSession;

log = grinder.logger.output;
test = Test(1, "Create, Accept and Complete");
class TestRunner:
    def __call__(self):
        session = test.wrap(RestWorkManagerSession());
        session.getMyWorkList();

This test basically leverages an existing Java class called RestWorkManagerSession (partially shown below) and makes a call to the Work Manager web service to retrieve my work list.


public class RestWorkManagerSession extends AbstractRestTestCase {
	       ...
    public WorkItems getMyWorkList() {
	String myWorkListUrl = getLocationUri() + _sessionId + 
                               "/workLists/myWorkList";
        try {
	    return getWorkList(myWorkListUrl);

	} catch (Exception exception) {
	    // convert to a runtime exception

	    throw new RuntimeException("getMyWorkList",
		  		       exception);
	}
    }
}

Grinder uses a property file to parametize particular aspects of a load test. In the property file you can configure the number of processes, threads and iterations for a instance of grinder. You can also configure sleep time between each iteration, which is useful for simulating web service transaction rates.


#
# Example grinder.properties
#
grinder.processes=1
grinder.threads=2
grinder.runs=10

grinder.jvm.classpath=build/classes;build/test
grinder.jvm.arguments=-Dpython.home=/applications/jython-2.1

grinder.useConsole=false
grinder.consolePort=6372

grinder.logDirectory=logs
grinder.numberOfOldLogs=2
grinder.logProcessStreams=false

grinder.initialSleepTime=500
grinder.sleepTimeFactor=0.01
grinder.sleepTimeVariation=0.005

grinder.script=src/test/load/grinder/CreateAcceptCompleteScenario.py

To run grinder you simply pass it the property file


  grinder.bat grinder.properties

The next step is to determine whether I can configure grinder to execute the following load test

  • 10 users concurrently retrieving work lists every 5 seconds and

  • 5 users concurrently creating work items every 10 seconds and

  • 3 users accepting and completing work items every 15 seconds

Four years ago a collegue and I created openexec , which was supposed to do just that. This is what the configuration file looked like. (There is even some documentation).


<?xml version="1.0"?>
<OpenExecConfiguration>
  <Scheduler />
  <Logger />

  <Users>
    <User userName="chris" />
    <User userName="jima" maxConcurrentThreads="1" />
    <User userName="jimm" maxConcurrentThreads="2" />
  </Users>

  <Scenarios>
    <Scenario className="SleepExecutable" scenarioName="sleep100">
      <Properties>
        <Property name="sleep.time" value="100" />
      </Properties>
    </Scenario>
    <Scenario className="SleepExecutable" scenarioName="sleep1000">
      <Properties>
        <Property name="sleep.time" value="1000" />
      </Properties>
    </Scenario>
    <Scenario className="SleepExecutable" scenarioName="sleep10000">
      <Properties>
        <Property name="sleep.time" value="10000" />
      </Properties>
    </Scenario>
  </Scenarios>

  <UserScenarios>
    <UserScenario interval="500" delay="0" serialSceduling="false" 
      executionCount="20" userName="chris" scenarioName="sleep1000"/>
    <UserScenario interval="500" delay="15000" serialSceduling="false" 
      executionCount="20" userName="jima" scenarioName="sleep1000"/>
    <UserScenario interval="500" delay="40000" serialSceduling="false" 
      executionCount="20" userName="jimm" scenarioName="sleep10000"/>
  </UserScenarios>
</OpenExecConfiguration>

...the CVS logs show that it hasn't been touched for 4 years :-(

Jim Alateras is an independent consultant specializing in open source and emerging technologies.

Return to weblogs.oreilly.com.



Weblog authors are solely responsible for the content and accuracy of their weblogs, including opinions they express, and O'Reilly Media, Inc., disclaims any and all liabililty for that content, its accuracy, and opinions it may contain.

Creative Commons License This work is licensed under a Creative Commons License.




Sponsored By: