Rough Book

random musings of just another computer nerd

Writing Performance Tests in Grinder using a Framework

Constructor

The constructor for the Scenario class accepts two arguments: a description and a dictionary for URLs. As mentioned earlier, each task has a URL (or URLs) associated with it. By setting a URL for a scenario, you cause all tasks added to that particular task to have the same URL. Simce the tasks by themselves do not have any previously defined URLs, we need to make sure that the supplied dictionary is not empty. The constructor also initializes a list called tasks which of course, maintains a list of tasks.

addTask method

The addTask() method lets you add a Task to a Scenario. First we check to see if the object passed in implements the setUrlDict() method. If it doesn’t we raise an exception. If it does implement the method, we check to see whether the current instance of the Scenario class has a non-empty urlDict dictionary. If it does, we go ahead and set the task’s urlDict property to the same value. As a side note, Python doesn’t have explicit interfaces. The language has implied interfaces. Hence, we need to inspect the object at runtime to see whether it implements a necessary method.

The next if-statement checks to see whether the supplied object implements the initializeTask() method. If it does, we go ahead and run that method.

Finally, we check to see if the supplied object implements the run() method, since it makes no sense to add a task that we cannot run. If it does, we add it to our list of tasks.

Accessor methods

The class has two accessor methods: getUrl() and getUrlDict() which perform the same functions as the Task base classes’s getUrl() and getUrlDict() methods.

Mutator methods

You might be wondering why the mutator methods don’t actually let you change anything. The reason is because all the child tasks of a Scenario must have the same URL. As you can see, we initialize the URL of a task only when it is added. If you were allowed to change the URL of a Scenario later, then the tasks wouldn’t have the same URL as the scenario. Of course, you could then say that in the setUrlDict() or setUrl() methods we just need to update all the tasks with the new URL. But that would be a side-effect, and side-effects are not good! Finally, there simply is no reason to change the URL of a Scenario during runtime. Since the tests themselves are tied to a task, and therefore to a scenario, altering the URL of a scenario while the test is running would make your statistics meaningless.

run() method

The run() method iterates through all the tasks belonging to this scenario.

Now that we’ve gone over the building blocks of the framework, let’s use them to create a scenario that we want to test.

Popularity: 100% [?]

Pages: 1 2 3 4 5 6 7 8 9 10

September 16, 2009 - Posted by | Java, Jython, Programming and Development, Python | , , , , ,

36 Comments »

  1. Dear vivin

    Happy onam to you. we are a group of students from cochin who are currently building a web portal on kerala. in which we wish to include a kerala blog roll with links to blogs maintained by malayali’s or blogs on kerala.

    you could find our site here: http://enchantingkerala.org

    the site is currently being constructed and will be finished by 1st of sep 2009.

    we wish to include your blog located here

    http://vivin.net/

    we’ll also have a feed fetcher which updates the recently updated blogs from among the listed blogs thus generating traffic to your recently posted entries.

    If you are interested in listing your site in our blog roll; kindly include a link to our site in your blog in the prescribed format and send us a reply to enchantingkerala.org@gmail.com and we’ll add your blog immediatly.

    pls use the following format to link to us

    Kerala

    hoping to hear from you soon.

    warm regards

    Biby Cletus

    ReplyReply

    Comment by bibbi | September 18, 2009

  2. Hi,

    I was evaluating Grinder tool..
    If the Tester Runner method is big . i mean if Testrunner class exceeds certain length then i am unable to run the test and the tool is throwing following exception…

    As a workaround we can divide the script into more than once script but the problem here is how can i call one script in other…?? could you help me..

    Thanks In Advance
    Kamalakar

    ReplyReply

    Comment by kamalakar | September 25, 2009

  3. @kamalakar
    That’s strange – I’ve never run into that issue before. What is the exception you’re getting? You might consider putting each one into a class of its own and since they’re callable, you might be able to call them split them into separate classes and then write a wrapper that calls them? I think you’ll probably have better luck on the grinder-use mailing list – have you asked your question on there?

    ReplyReply

    Comment by vivin | September 25, 2009

  4. I have read some of your posts and find your style of writing very interersting. Salute you on how neatly the articles are presented.

    ReplyReply

    Comment by Avinash Mangipudi | October 9, 2009

  5. @Avinash Mangipudi
    Thanks Avinash!

    ReplyReply

    Comment by vivin | October 9, 2009

  6. I get following error for all import statements of my framework scripts (ImportError: no module named sci).

    This goes away if I compile all my dependent scripts and add jar to classpath of agent. But then I cant parameterize methods in those dependent scripts as they are already classes.

    How do I solve this?

    I tried settting PYTHONPATH, passing python.home in grinder.properties. nothing seems to work for me.

    ReplyReply

    Comment by Mukes Nair | November 3, 2009

  7. I found out the issue. I had to put my script sources folder in Jython registry file.@Mukes Nair

    ReplyReply

    Comment by Mukesh Nair | November 3, 2009

  8. @Mukesh Nair
    Sorry I didn’t get back to you sooner. I didn’t check my email until now! I’m glad that you were able to fix the issue. I wasn’t clear on your initial problem though. Did you have problems importing the actual scripts (that you created using the framework) themselves?

    ReplyReply

    Comment by vivin | November 3, 2009

  9. Hi ,

    I am trying to use torque framework , facing problem with the scenario class.
    As scenario class showing error at following code.

    ” urlDict = property(getUrlDict, setUrlDict)” because my eclipse is unable to find property import.
    i have jython 2.1 with me. it seems the property import is not available on the jython 2.1

    Could you please help me wat might be the problem..?

    Thanks
    Kamalakar

    ReplyReply

    Comment by kamalakar | November 5, 2009

  10. I need a a way to share some data between tasks..
    How can i do this?
    Do we need to add other prop in the scenario class

    ReplyReply

    Comment by kamalakar | November 5, 2009

  11. @kamalakar
    Hi
    i am able to fix this error.. the problem is with my environment
    Actually i am using GrinderStone its eclipse plugin for Grinder Tool.

    Thanks
    Kamalakar

    ReplyReply

    Comment by kamalakar | November 5, 2009

  12. @kamalakar
    Sorry I wasn’t able to get to you sooner! Glad you were able to fix the issue – it did sound like an environment problem.

    What data are you trying to share between tasks?Tasks are discrete entities that should have nothing in common with each other. Hence, they shouldn’t be sharing state-data. However, they can share input data (from a common resource – like a file).

    ReplyReply

    Comment by vivin | November 5, 2009

  13. suppose consider following usecase:
    1.login is one task: after user got logged in we will get a userid .
    2.second task :
    — Here the request in this task need the userid from the previous task.

    So, we need a global parameters that can be accessible throughout the scenario.
    Could you suggest me how we can achieve . I have one approach in my mind.
    — Add another param like ‘urlDict’ in the Scenario Class . what do you say.?

    Thanks
    Kamalakar

    ReplyReply

    Comment by kamalakar | November 5, 2009

  14. @kamalakar
    In this case I’d parameterize the usernames and userId’s and link them to the thread number. You’d have to do this even if you were testing a pure Grinder-script that didn’t use the framework.

    ReplyReply

    Comment by vivin | November 6, 2009

  15. I have another issue to resolve. Any help will be appreciated. Lets take a scenario of a billing counter like of BestBuy. The associate will log in and load the billing screen. Then he will enter items and print receipt for a customer. Then for the next customer and so on. Here I have classified tasks in the scenario as follows
    1. Login Task
    2. Load Billing Screen Task
    3. Enter Items Task
    4.Print receipt Task
    5. Logout task

    Now in the run I want to run tasks 1, 2 and 5 only once. I want to repeat 3 and 4.

    How do I do this?

    Thanks
    Mukesh

    ReplyReply

    Comment by Mukesh Nair | November 19, 2009

  16. @Mukesh Nair

    I’m assuming that you know how many times you need to repeat tasks 3 and 4? You can simply create n “Enter Items” tasks and n “Print receipt” tasks (through a loop perhaps, and maybe have an array for each, for example enterItemsTaskArray and printReceiptTaskArray).

    When you build your scenario, you add Task 1 and 5, then iterate through both arrays at the same time and them to the scenario (so you’d add one “Enter items” task and then one “Print receipt” task). After you’re done you add Task 5.

    ReplyReply

    Comment by vivin | November 19, 2009

  17. Actually I don’t know how many times I will be repeating 3 and 4. I found another way to tackle the issue. Like this.

    class TestRunner:
    def __init__(self):
    log(“initializing scenario %s” % self.__class__.__name__)
    myScenario.initialize()

    def __call__(self):
    log(“running scenario %s” % self.__class__.__name__)
    myScenario.run()

    def __del__(self):
    log(“finalizing scenario %s” % self.__class__.__name__)
    myScenario.finalize()

    ReplyReply

    Comment by Mukesh Nair | November 19, 2009

  18. @Mukesh Nair

    so my scenario will look like:

    myScenario.addInitTask(loginTask)
    myScenario.addInitTask(loadPackScreenTask)
    myScenario.addTask(scanShipmentTask)
    myScenario.addTask(newCaseTask)
    myScenario.addTask(scanItemTask)
    myScenario.addTask(closeContainerTask)
    myScenario.addFinalTask(logoutTask)

    I think this should solve my current issue.

    ReplyReply

    Comment by Mukesh Nair | November 19, 2009

  19. @Mukesh Nair
    That would work as well. I’m assuming that you’re using meta-programming and extending the Scenario class at runtime?

    Even if you didn’t know how many times you’d be repeating it, as in let’s say that it will be repeated a random number of times, you can add a random number of items to the arrays. But I do like your solution. It’s a little more elegant.

    ReplyReply

    Comment by vivin | November 19, 2009

  20. I have a problem of data getting mixed up between threads. Look at the log below.

    initially thread-1 had value 100000019. Once thread -0 got the value 100000024, i printed out values again. Now both threads have the same value.

    I decompiled one of the class files and I found that self is declared as:
    static final py self;

    Did you face similar issue?

    11/20/09 10:56:09 AM (thread 1 run 0 test 101): self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"] 100000019
    11/20/09 10:56:09 AM (thread 0 run 0 test 101): suggestedShipments ['100000019', '100000024']
    11/20/09 10:56:09 AM (thread 0 run 0 test 101): self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"] 100000024
    11/20/09 10:56:09 AM (thread 1 run 0 test 4201): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 365 bytes
    11/20/09 10:56:09 AM (thread 1 run 0 test 4201): sleeping for 29 ms
    11/20/09 10:56:09 AM (thread 0 run 0 test 4201): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 919 bytes
    11/20/09 10:56:09 AM (thread 0 run 0 test 4201): sleeping for 31 ms
    11/20/09 10:56:09 AM (thread 1 run 0 test 4301): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 244 bytes
    11/20/09 10:56:09 AM (thread 1 run 0 test 4301): sleeping for 34 ms
    11/20/09 10:56:09 AM (thread 0 run 0 test 4301): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 244 bytes
    11/20/09 10:56:09 AM (thread 0 run 0 test 4301): sleeping for 30 ms
    11/20/09 10:56:09 AM (thread 1 run 0 test 4401): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 919 bytes
    11/20/09 10:56:09 AM (thread 0 run 0 test 4401): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 919 bytes
    11/20/09 10:56:09 AM (thread 1 run 0 test 4401): sleeping for 63 ms
    11/20/09 10:56:09 AM (thread 0 run 0 test 4401): sleeping for 60 ms
    11/20/09 10:56:09 AM (thread 1 run 0 test 4501): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 341 bytes
    11/20/09 10:56:09 AM (thread 1 run 0 test 4600): self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"] 100000024
    11/20/09 10:56:09 AM (thread 0 run 0 test 4501): http://10.10.20.80:7099/smcfs/console/exuipack.exui -> 200 OK, 341 bytes
    11/20/09 10:56:09 AM (thread 0 run 0 test 4600): self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"] 100000024

    ReplyReply

    Comment by Mukesh Nair | November 20, 2009

  21. @Mukesh Nair
    How are you parameterizing the data? Are you doing it based on the thread number?

    ReplyReply

    Comment by vivin | November 20, 2009

  22. @vivin
    am setting data in the task itself using one method call to a utility script, like below

    def SelectStationAndScanShipment2(self):
    “”"Selecting station and scanning shipment POST exuipack.exui (request 201).”"”
    self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"] = self.StringUtil.getAPickedShipmentNumber(self.parameters["SelectStationAndScanShipment2"]["201"]["OrganizationCode"])
    self.log(“self.parameters[\"SelectStationAndScanShipment2\"][\"201\"][\"BarcodeData\"] %s” % self.parameters["SelectStationAndScanShipment2"]["201"]["BarcodeData"])

    ReplyReply

    Comment by Mukesh Nair | November 20, 2009

  23. @Mukesh Nair
    I recommend not modifying the actual task. What you want to do is create a parameterizing method that sets the values in the parameters dictionary for you. Check out my examples in this post.

    ReplyReply

    Comment by vivin | November 20, 2009

  24. @vivin
    i wanna show you a grinder xml which is not producing correct url in the task created by the perl script. I directly created grinder script using proxy. I can see a lot of arguements witht he url. But when it is converted using using the perl script into a task, all the arguements are missing. let me know where to send the related files so that you can take a look. I haven’t looked into perl yet. So I thought you could resolve it faster.

    ReplyReply

    Comment by Mukesh Nair | November 23, 2009

  25. @Mukesh Nair
    Is it a POST or a GET? I can take a look at it. I DM’ed you my email on twitter. So just send me the XML and I’ll take a look at it.

    ReplyReply

    Comment by vivin | November 23, 2009

  26. [...] alerted me to a problem with the Perl conversion script (that converts the XML produced by the Grinder [...]

    Pingback by An update to the Grinder testing-framework | Rough Book | December 7, 2009

  27. Hi Vivin,

    Here i need your help. I am working in web application and i wanna to test the load of the application. For this i am using the grinder tool and under stand all the things except properties file of grinder framework. Is it possible to run more than one script or divide the scripts in threads on same time. Here i can explain you through example. Suppose we have 4 scripts and want 4 scripts are equally divided in 100 user’s. is it possible?

    ReplyReply

    Comment by vicky | March 4, 2010

  28. @vicky
    I looked around for ways to run multiple scripts and I ran into this post here that says you can do it by making each script as a separate property and not space delimited. So what you need to do is divide the load (and select a user) based on the thread number. Script 1 will use user1-user25 (if the thread number is between 1 and 25), script 2 will use user26-user50 (if the thread number is between 26 and 50). This basically means that you need to have 100 threads.

    ReplyReply

    Comment by vivin | March 4, 2010

  29. The Perl file under the link on page 9 is not the same as the one you packaged in the ZIP.

    ReplyReply

    Comment by Marcel | March 16, 2010

  30. @Marcel
    Thanks for pointing that out Marcel; I’ll fix it!

    ReplyReply

    Comment by vivin | March 17, 2010

  31. @Mukesh Nair
    Could you show the details about it. I have the same problem.

    ReplyReply

    Comment by mike | April 15, 2010

  32. Hi vivin.
    I have a question about the using of regex. Since grinder just allows to compile regex within the runner, how do i parse http results in torqueo tasks? I didn’t get any valuable answers in the internet so far. Do you have any advices? Would be great, thx!

    ReplyReply

    Comment by muellae | October 25, 2010

  33. @muellae
    Sorry for taking so long to respond. I was pretty busy with school and work. There is no way (as of now) to have access to the HTTP results. It’s abstracted away inside the tasks. What you could do, is modify the autogenerated task-files themselves and get access to the result that way.

    The reason that the result is not provided (and possibly cannot be provided per the current design) is that a task consists of one or more requests. So it doesn’t make sense to talk about the “result” of a task. A task represents an abstract unit.

    ReplyReply

    Comment by vivin | November 16, 2010

  34. Hi vivin!
    Thanks for your answer. I actually meant a http request only and was not able to parse it. The problem was, that it’s hardly (or even not?) possible to use the python regex lib in jython. I’m now just using the java regex library and it works like a charm.
    Thanks anyway for your answer! You did a great job with torqueo, it’s a great tool which helped me a lot.

    ReplyReply

    Comment by muellae | November 16, 2010

  35. @muellae
    Glad to know you figured it out. Also, thank you for your kind words :) I’m glad you find my tool helpful!

    ReplyReply

    Comment by vivin | November 23, 2010

  36. Hi Vivin,

    Thanks for describing the test framework. Its nice to see the way u maintained the tutorials for Grinder. Have few queries on implementing few features related to Grinder.
    1. How to call a user defined function
    2. How to monitor server side metrics like CPU,memory and Disk etc.
    3. Do we have an option to add users dynamically.

    Do u have any monitoring template available

    Thanks
    Sattish.

    ReplyReply

    Comment by Sattish | November 24, 2010


Leave a Comment

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
All original content on these pages is fingerprinted and certified by Digiprove