throughput vs users

Loadunit is a Junit-based framework for unit-testing of scalability and performance. It enables running completely automated load-tests of software and generates reports about the throughput and performance of tested applications.

You can view a sample HTML report generated by Loadunit.

You can view the Loadunit Sourceforge Project Page for the latest information about Loadunit.

Loadunit is written and maintained by Bryan Che.


Table of Contents

  1. Introduction
  2. Why Use Loadunit?
  3. Loadunit Requirements
  4. Downloading and Installing Loadunit
  5. Loadunit Overview
  6. Loadunit Test Results
  7. Loadunit Parameters
  8. Sample Walkthrough
  9. License

Introduction

Loadunit is a Junit-based framework written in Java for unit testing of scalability of performance. It should run in any environment with Java 1.4 or greater.

People may use Loadunit for testing many types of applications. Loadunit is particularly well-suited for testing Web-based applications and includes several tests specifically for testing Web applications.

Developers can write Junit tests for the Loadunit framework and use these tests for automated scalability tests. Loadunit will ramp up to a configurable number of virtual users, each running these tests. Furthermore, Loadunit supports having each of these users test with different data from each other in order to generate realistic load patterns.

Loadunit allows control over how to ramp up virtual users for testing and features automatic bottleneck-detection to stop load tests once these tests have reached a scalability bottleneck. Loadunit also generates reports containing charts of Throughput-Vs-Users and Performance-Vs-Users data for test runs.

Why Use Loadunit?

Many different types of load-testing software already exist. Why would you want to use Loadunit, then?

Loadunit will not replace a sophisticated load-testing tool. But, Loadunit can prove to be valuable and complementary to traditional load-testing software in a couple of significant ways:


Loadunit Requirements

Loadunit Software Requirements

Loadunit requires Java 1.4 to run. Loadunit also depends upon several free software libraries:

Loadunit includes jar files for all these libraries in its distribution.

Loadunit Hardware Requirements

The easiest way to setup Loadunit is to install it on the same machine as the application you want to test. Indeed, developers may want to do this so that they can quickly check if changes they make impact scalability or performance. Running Loadunit on the same machine as the tested application, though, is not a good configuration for long-term, repeatable unit-testing. This is because Loadunit itself will greatly affect the machine's performance.

The ideal configuration for Loadunit is to place Loadunit on a separate machine from the tested application's machine. However, Loadunit's computer and the tested application's computer should be on the same high-bandwidth network so as to remove network issues as a potential bottleneck in your application testing.

Loadunit's machine should also be powerful enough to generate the type of load with which you want to test. When running Loadunit for the first few times, monitor Loadunit's CPU and memory usage to make sure that neither one hits 100% utilization. Otherwise, your test results will reflect a bottleneck in Loadunit's own performance rather than your application's performance.

Loadunit can generate over 500 virtual users on a dual-PIII 1.4 GHz box with 1 GB of RAM without any problems.

For more detailed information about configuring Loadunit, see the Loadunit Parameters section.


Downloading and Installing Loadunit

Obtaining Loadunit

To download the latest release of Loadunit, go to https://sourceforge.net/project/showfiles.php?group_id=119363.

Installing Loadunit

Loadunit comes in a zip file. This zip file contains Loadunit documentation (including this document), a Loadunit jar file, jar files on which Loadunit depends, and also the Loadunit source code.

To install Loadunit,

  1. Unzip the loadunit zip file to a directory. Let this directory be LOADUNIT_HOME.
  2. Add all the jar files under LOADUNIT_HOME/lib to your classpath.

    For example, On Linux, using bash, do

    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/loadunit-1.0.jar
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/commons-httpclient-2.0.1.jar
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/concurrent.jar	 
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/jfreechart-0.9.19.jar	
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/commons-logging-1.0.2.jar     
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/jcommon-0.9.4.jar  
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/junit-3.8.1.jar	
    CLASSPATH=$CLASSPATH:$LOADUNIT_HOME/lib/log4j.jar
    export CLASSPATH
    

    On Windows, do

    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\loadunit-1.0.jar
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\commons-httpclient-2.0.1.jar
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\concurrent.jar	 
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\jfreechart-0.9.19.jar	
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\commons-logging-1.0.2.jar     
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\jcommon-0.9.4.jar  
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\junit-3.8.1.jar	
    set CLASSPATH=%CLASSPATH%:%LOADUNIT_HOME%\lib\log4j.jar
    

Loadunit Overview

Loadunit uses three main types of classes for running tests:

LoadunitTestCase
The LoadunitTestCase interface extends the basic Junit Test interface and adds methods for performing operations before and after a load test as well as for setting parameters like throughput and performance requirements. You can think of a LoadunitTestCase as what one virtual user will do in a multi-user load test.
LoadunitTest
A LoadunitTest is a single load test. It takes a LoadunitTestCase and ramps up many virtual users to do scalability and performance tests with that LoadunitTestCase. LoadunitTests have configurable settings for things like how to rampup virtual users, the maximum number of virtual users with which to test, and whether to automatically stop the test when a bottleneck is detected. LoadunitTests also write out charts and data for their results.
LoadunitSuite
A LoadunitSuite is a suite of LoadunitTests. This class allows you to set common settings for a group of LoadunitTests and to run them all with these settings. At the conclusion of its run, a LoadunitSuite will generate a report summarizing the results of all the individual tests it ran. LoadunitSuites take LoadunitCases and wrap them in LoadunitTests for running.

When you write tests for running in Loadunit, you will create classes that implement the The org.loadunit.LoadunitTestCase interface. LoadunitTestcase is the basic type of test in the Loadunit framework. It provides three main methods for controlling a test:

preTest()
These are actions that a virtual user will do once before performing its basic test. A common scenario where you would use a preTest is when you want to load-test a Web page that requires a login. In that case, you could write a preTest() that logins the user. Then, having logged in, the user would perform the main test. PreTest operations do not count towards throughput or performance results.
test()
These are the main actions for a user to perform during a load test. These operations count towards final throughput and performance results.
postTest()
These are actions that a virtual user will perform once when it is done with its test. A common scenario where you would use a postTest() is when you want to clean up data or undo operations from the main test. PostTest operations do not count towards throughput or performance results.

The LoadunitTestCase interface also has methods for setting/getting the name of a test and for setting/getting throughput and performance requirements.

Loadunit comes with classes that implement the LoadunitTestCase interface, including:


Loadunit Test Results

Loadunit generates two basic types of results: Throughput-Vs-Users data and Performance-Vs-Users data.

Throughput Vs Users

Loadunit records the number of tests per second an application can perform for a given number of concurrent users. This number is the throughput that an application can achieve for a given load. It is a measure of how well an application scales. For example, say that you have a test which load tests one Web page. In this case, Loadunit would report the pages/second your Web application could serve for a given number of users.

Following is a sample Throughput-Vs-Users chart that Loadunit generated: throughput vs users

Performance Vs Users

Loadunit records the average test time in milliseconds that an application takes to perform a test for a given number of concurrent users. This number represents how long an application takes to complete a test when under a certain load. It is a measure of how well an application performs. For example, say that you have a test which load tests one Web page. In this case, Loadunit would report the average number of milliseconds your Web application takes to serve that page for a given number of users.

Following is a sample Performance-Vs-Users chart that Loadunit generated: performance vs users

Loadunit Reports

Loadunit generates reports whenever it runs a Loadunit Suite. You can configure the reports that Loadunit runs by editing the appropriate parameter. You can view a sample report generated by Loadunit's HTMLReporter.

Test Failures

Loadunit supports setting specific failure points for its tests. You can configure a Loadunit test to fail if the test performs too slowly or the test does not scale to a high enough throughput.

To set a LoadunitTestCase test to fail if it does not reach a certain throughput, call the method LoadunitTestCase.setMinThroughput().

To set a LoadunitTestCase test to fail if it takes too long, call the method LoadunitTestCase.setMaxTime().


Loadunit Parameters

You must create a loadunit.properties and place it in your classpath when running Loadunit. Loadunit comes with a loadunit.properties.in file that you can copy and use as a starting point for setting your Loadunit parameters.

The loadunit.properties file has the following parameters you must set:

org.loadunit.host
The hostname of the machine you want to load test. e.g. localhost
org.loadunit.port
The port of the machine you want to load test. e.g. 80
org.loadunit.prefix
Prefix to place before all url's. e.g. "/ccm"
org.loadunit.outputfolder
The folder to which to write Loadunit results
org.loadunit.maxusers
The maximum number of concurrent users to load test
org.loadunit.delay
The Delay between user requests, in milliseconds. Often referred to as think time.
org.loadunit.rampup.users
The number of users to ramp up at a time until maxusers is reached
org.loadunit.rampup.iterations
The number of times each virtual user will run a test between rampups. Loadunit will ramp up after n iterations at each user load level
org.loadunit.reporters
The list of reporters to run after the test, separated by commas. The reporters must each be fully qualified Java names, like org.loadunit.report.HTMLReporter.

Sample Walkthrough

This section will walk you through using Loadunit to load test a fictional Web application, ShoppingCart. ShoppingCart is a simple Web application that lets users browse or search for products and add them to a shopping cart. Adding an item to a shopping cart requires a user login.

You can see all the code in this walkthrough in the class, org.loadunit.example.ShoppingCartSuite.

Create a LoadunitSuite

First, you must create your LoadunitSuite. Create a class, ShoppingCartSuite, that extends org.loadunit.LoadunitSuite. Add a basic constructor that sets the name of the suite:

public class ShoppingCartSuite extends LoadunitSuite {
    public ShoppingCartSuite() {
        super("shoppingcart-loadunit-suite");
    }
}

Test Home Page

We'll start by creating a simple test to load test the ShoppingCart home page. Add the following method to ShoppingCartSuite:

public static Test homePageTest() {
    String sURL = "/home";
    URLTestCase test = new URLTestCase(sURL);
    test.setName("HomePageTest");
    return test;
}

This test tests the home page, which is located at "/home." Notice that the test only specifies a relative URL. This is because Loadunit allows you to set the test site's host name, port, and URL prefix through a properties file. By using a relative URL, you can run the same test on a variety of test machines without modifying your test code.

Notice also that we set the test name. You should always set the test name for reporting purposes.

Test Searching

Now, let's create a test that will load test searching. Add the following method:

public static Test searchTest() {
    //the base url that doesn't change
    String sSearchURL="/search.cgi?q=";
    
    //the search terms.  Each virtual user will randomly select
    //one of these search times each time it makes a request 
    String[] params = {"linux", "computers", "cars"};
       
    ParameterizedURLTestCase test =
        new ParameterizedURLTestCase(sSearchURL, params);
    test.setName("SearchTest");        
    return test;
}

This test uses a ParameterizedURLTestCase. ParameterizedURLTestCases are useful when you want to test a dynamic Web page that operates differently depending on what parameters it receives.

In this case, we create a list of search terms. Each virtual user will randomly select a different search term whenever it makes a request. This assures that the server will see varied load patterns under a load test.

Test Browsing

Let's say that we want to load test a specific sequence of Web pages. We can do that by adding the following method:

public static Test browseTest() {
    //navigate to the help contacts
    String[] URLs = { "/home/", "/help/about", "/help/about/contacts" };
        
    URLSeriesTestCase test = new URLSeriesTestCase(URLs);
    test.setName("BrowseTest");
    return test;
}

Test Adding to Shopping Cart

Finally, we'll create a test that adds an item to a shopping cart. Remember that this action requires a user login. But, we don't want to load test the login process--we want to load test adding something to a shopping cart. How do we do that? We use a preTest().

In this case, we'll write a preTest() to login a user. Then, we'll write a test() to add an item to a shopping cart. Loadunit will run the login preTest once for each virtual user and hold the resulting login cookie throughout the main test:

public static Test addItemToCartTest() {
    Test test = new AbstractHTTPTestCase() {
            
            //set login cookies using a preTest
            public void preTest() {
                String sURL = "/login";
                String sUsername = "testuser";
                String sPassword = "testpassword";
                
                NameValuePair username = new NameValuePair("username", sUsername);
                NameValuePair password = new NameValuePair("password", sPassword);
                
                clientPostURL(sURL, new NameValuePair[]{ username, password});
            }

            protected void doTest() {
                //now that we're logged in, load test adding an item to the cart
                String sURL = "/cart/add";
                String sProductID = "235";
                NameValuePair product = new NameValuePair("productID", sProductID);
                clientPostURL(sURL, new NameValuePair[] {product});
            }
        };
    
    ((LoadunitTestCase)test).setName("AddItemToCartTest");
    return test;
}

Add Tests to Suite

Finally, we want to create a ShoppingCartSuite and add the tests we have just written to it. We will also write a main method to run this suite:

public static Test suite() {
    ShoppingCartSuite suite = new ShoppingCartSuite();

    suite.addTest(homePageTest());
    suite.addTest(searchTest());
    suite.addTest(browseTest());
    suite.addTest(addItemToCartTest());
        
    return suite();
}

public static void main(String[] args) {
    junit.textui.TestRunner.run(suite());
}

Sample Walkthrough Addendum: Testing Arbitrary Code

The sample code in the ShoppingCartSuite tests Web pages. However, Loadunit supports load testing of arbitrary code. If you want to load test a particular software component, just create a class that implements the org.loadunit.LoadunitTestCase interface and tests your code. You may want to have your class extend org.loadunit.AbstractLoadunitTestCase and just implement that abstract class's doTest() method.

License

Loadunit is licensed under the GPL.