Writing Performance Tests in Grinder using a Framework

by vivin

A high-level view of the framework

To understand the framework, first let’s figure out what it is that we want to do exactly. To create a scenario, our framework should let us do the following things:

  1. Define a scenario
  2. Add tasks to the scenario
  3. Execute the scenario

How about looking at what we want to do from a programming perspective?

  1. Create a scenario object
  2. Add the tasks we want to the scenario object
  3. Execute the scenario

Of course, this is still a rather simple view. We actually want to do a bit more than that. We also want to parameterize our tasks. So, the list of things we want to do actually looks like this:

  1. Create a scenario object
  2. Create an instance of a task we want
  3. Parameterize the task
  4. Add the task to the scenario object
  5. Repeat steps 2-4 as many times as necessary
  6. Execute the scenario

Now that we know what we want to do, let’s take a look at the actual code behind the framework.

The Task class

All tasks that you record and create will extend the Task class. The Task class by itself is pretty simple, and not very useful. It looks like this:

Task.py:

# Base class for all Tasks.

class Task:

      numberOfTasks = 0;

      def __init__(self):
          """Initialize properties of class"""
          self.urlDict = {}
          self.parameterizingMethods = {}
          Task.numberOfTasks += 1

      def setUrlDict(self, urlDict):
          """Setter for urlDict property"""
          self.urlDict = urlDict

      def getUrlDict(self, urlDict):
          """Getter for urlDict property"""
          return self.urlDict

      def setUrl(self, key, value):
          """Sets value to 'value' of particular url in URL dict identified by key 'key'"""
          self.urlDict[key] = value

      def getUrl(self, key):
          """Returns value of particular url in URL dict identified by key 'key'"""
          return self.urlDict[key]

      def callParameterizingMethodFor(self, key):
          """Calls parameterizing method associated with page identified by key 'key'"""
          if(self.parameterizingMethods.has_key(key)):
             self.parameterizingMethods[key]()

      def setParameterizingMethodFor(self, key, value):
          """Sets parameterizing method associated with page identified by key 'key' to method in 'value'"""
          self.parameterizingMethods[key] = value

      def getParameterizingMethodFor(self, key):
          """Returns the parameterizing method associated with page identified by key 'key'"""
          return self.parameterizingMethods[key]

      def instrumentMethod(self, test, method_name):
          """Instrument a method with the given Test."""
          unadorned = getattr(self.__class__, method_name)
          import new
          method = new.instancemethod(test.wrap(unadorned), None, self.__class__)
          setattr(self.__class__, method_name, method)