This topic explains how to extend Parasoft Load Test’s functionality with custom load test components. In this section:
Parasoft Load Test functionality can be extended by creating custom load test components. Parasoft Load Test acts as a container for load test components, or load test beans. A load test component is a functional core that defines the behavior of a virtual user during load testing. The load test container provides the following services to the component:
A load test component can be created by extending the SimRunnable
class of the Load Test component Java API located in the com.parasoft.simulator.api
package. SimRunnable stands for Simulator runnable. Simulator is the name for the Load Test container, which simulates multiple virtual user activities.
The component examples are located in the examples\dev\components
folder of your SOAtest/Load Test installation. The simple-runnable-source.jar and the socket-runnable-source.jar archives contain the source, configuration, and build files for the components described in this tutorial. You will need to unjar these archives to the Load Test component projects directory, which must be created manually.
To create a component projects directory outside the Load Test installation:
SocketRunnable
directory, which must be created manually. Each source directory contains a component-build.xml ANT build script.load.test.install.root
property is pointing to your SOAtest/Load Test installation directory.load.test.jar.path
property to point to the loadtest.jar file located in the <INSTALL-DIR>/plugins/com.parasoft.ptest.libs.web_<VERSION>/root
directory.To create a SimpleRunnable load test component project in Eclipse:
SimpleRunnable
.SocketRunnable/target/classes
.<INSTALL-DIR>/plugins/com.parasoft.ptest.libs.web_<VERSION>/root
directory.The components should be built with Java 1.5 JRE, preferably with JRE 1.5.0_18. The default target of the component-build.xml ANT script in each example project builds a component jar archive, which could be deployed to the Load Test as a custom or built-in component. If you use Eclipse to compile the component project as described here, remove the compile target dependency from the jar target of the component-build.xml script. |
The SocketRunnable component extends the SimpleRunnable component. Compile SimpleRunnable
first and put the main.jar from the root directory of the SimpleRunnable project into the lib
directory of the SocketRunnable project.
To create a SocketRunnable load test component project in Eclipse:
SimpleRunnable/target/classes
.<
INSTALL-DIR>/plugins/com.parasoft.ptest.libs.web_<VERSION>/root
directory. lib/jtidy-r820.jar
and lib/main.jar
are on the project class path.A component can be loaded into Load Test as an external archive or deployed as a built-in component.
To load a component from an external archive:
If component validation failed, the error messages will be shown in the lower table of the Deployment view.
To deploy a component archive into the Load Test application as a built-in component:
Place the component jar archive into the <INSTALL-DIR>/plugins/com.parasoft.ptest.libs.web_<VERSION>/root/lt-components/built-in
folder.
Javadoc documentation for the Load Test component API is available by going to Help > API > Component API on the Load Test application menu bar.
This section examines the SimpleRunnable Load Test component.
SimpleRunnable is a basic component that emulates test execution of a configurable duration and produces errors with a configurable frequency. It’s designed to get you acquainted with the Load Test Component API and the process of component archive creation and deployment.
The main method of a load test component is run(PrivateContext context). The component behavior that emulates user activities should be implemented inside this method. The component run method is invoked by a Virtual User object of a specific Profile. The Virtual Users in their turn are invoked by the Load Test application according to the load test Scenario.
The rest of the SimpleRunnable methods perform various services that are required by the container. Below, we will describe the most important of the component methods. For details on the rest of the methods, look at the source code of the SimpleRunnable class and the JavaDoc of SimRunnable.
Here are descriptions of the most important methods of the component:
boolean done() – This method is called by the container after invoking the run() method of this class to determine whether the component has completed its activities. A component can emulate a multi-step user activity with each step followed by the Virtual User think time as configured in the load test Profile. In such a case, the run() method will be called more than once until the done() returns true. Returning false will cause the framework to retain the Virtual User to which the instance of this component class belongs and call its run() method again. Returning true will cause the Virtual User to which the instance of this component class belongs to be removed from the Virtual User pool.
You eventually need to return true from the done() method in order to allow the Virtual Users to be removed from the pool. Once a Virtual User is removed from the pool, it will be replaced with a new Virtual User of the same profile if it is required by the load test Scenario. Releasing the Virtual Users is important because it allows the framework to follow the ups and downs of the scheduled virtual user or hit per second rate. |
Notice that the writeExternal() and readExternal() methods of the SimpleRunnable class have only skeleton implementation and do not write or read any data. These methods are used to transfer the component state to the remote Load Test machines. The SimpleRunnable component does not require such state transfer because the component external configuration file, which is included in the component archive, is used for the component configuration on local and remote machines. We will look at the implementation of writeExternal() and readExternal() in a different component example.
Next, let’s look at the SimpleRunnable’s external configuration file. The source folder of the SimpleRunnable component contains two component configuration files: LongExecTime.cfg and ZeroExecTime.cfg. One of them is included into the component archive (see component-build.xml ANT script).
When a component archive is deployed into the container, the archive is decompressed and the archive contents become available to the component via the DEPLOYMENT_BASE property of the DeploymentContext. The implementation of the onDeploy method of the SimpleRunnable class shows how the .cfg component configuration file is located and parsed to initialize an instance of SimpleRunnableConfiguration. If a load test configuration includes remote machines, the component archive is transferred to each remote machine before the beginning of the load test, after which each component is deployed.
After the deployment process is complete, the onDeploy method is called. The onDeploy method initializes the component from the .cfg file, which is included into the component archive. A component archive is serialized to a remote machine only if it is not present at the remote installation or if its checksums on the master and remote machines differ. This ensures that component archive transfer to the remote machines happens only when needed.
The lt-jar.xml component archive descriptor must be included into the root directory of each component archive. The descriptor must contain the class names of the main component class derived from the SimRunnable and the class name of the component output derived from SimRunnableOutput. See the lt-jar.xml files of the included components for the examples of the component archive descriptor file format.
Once you have deployed the SimpleRunnable component into Load Test and familiarized yourself with the SimpleRunnable source code and component archive structure, you can make modifications to the component archive configuration, rerun the load test, and see the effects of the modified component configuration. For instance, you can follow these steps in order to change the test execution time emulated by this component:
This section examines the SocketRunnable component. The SocketRunnable class extends SimpleRunnable and demonstrates the following:
The SocketRunnable component uses SocketTest class instances to establish a connection to a specific host and port, send a customizable request, and receive a response using Java Sockets. The SocketTest instances that belong to the component are configurable in the SocketRunnable compоnent view.
You may need the log immediately, so it is acquired from the Engine in the SocketRunnable constructor.Engine engine = (Engine)context.get(PrivateContext.ENGINE);
ComponentLog log = engine.getComponentLog();
A component can provide its custom configuration view to the container by implementing the SimRunnableConfigViewProvider interface. The container will display this view in the Configuration tab of the Load Test Runnable component panel shown above. The container calls the getConfigView() method of the SimRunnableConfigViewProvider interface to get the configuration view of the component. In this example, the SocketRunnableView class implements the component configuration view. The SocketRunnableView class uses SocketTest*View classes located in com.parasoft.loadtest.component.example.socket.test.view
package for individual SocketTest instance configuration.
A load test component can be designed to implement load test profile-specific behavior. Classes that implement ProfileRunnable or the SubProfileRunnable interfaces act as profile-specific subcomponents of the load test component. These classes implement the profile-specific behavior of the component.
There are two classes in the SocketRunnable example that implement ProfileRunnable interface: the SocketProfileRunnable and the SocketTestWrapper. The SocketProfileRunnable acts as a root profile runnable; it is a container for SocketTestWrappers. The SocketRunnable class keeps an instance of SocketProfileRunnable, where all configured SocketTestWrappers are stored. The SocketRunnable also keeps a Vector of SocketTestWrappers; this Vector represents a selection of ProfileRunnables for a specific Load Test profile. Each profile in the load test configuration keeps its copy of the component class. This guarantees that profile specific component configurations do not conflict and do not overwrite each other.
The populateSubProfileRunnables() method of the SocketRunnable fills the selectedProfileRunnables Vector based on the ProfileRunnableMap that is acquired from the profile specific PrivateContext. The ProfileRunnableMap contains load test profile-specific ProfileRunnable selections.
In order to let you select load test profile-specific ProfileRunnables, the SocketRunnable component implements the ProfileRunnableViewProvider interface as shown below.
SocketRunnable uses ProfileRunnableTreeView of the API.
A load test component can save its configuration to a Load Test project by implementing the SaveablePropertiesProvider interface. The component configuration is represented by the SimRunnableProperties class, which stores component property name/value pairs.
The component properties must be saved as String values independent of the component classes. This ensures that a project can be read into the Load Test application even if the component is not deployed. At the same time, this allows a project to store different component type configurations. The container uses the tag field of the SimRunnableProperties class to return the appropriate properties instance to the component. The tag value should be set by the component developer. SoatestRunnable uses "SOCKET_RUNNABLE_SAVEABLE_PROPS_V.1" string as its saveable properties tag.
If saving your component configuration requires a more complex data structure than a set of name/value property pairs, you can use XML as an alternative. Serialize your component configuration to an XML representation and save the XML string in a single name/value pair of the SimRunnableProperties instance. See the SocketRunnableXMLSerializer for an example how to save and restore component configuration using XML.
A load test component configuration, which can be either read from a load test project file or modified by you and your team, must be transferred to remote load test machines. The component state transfer should be implemented within the readExternal/writeExternal methods of the ParasoftExternalizable interface implemented by the component class. Since the configurable part of the SocketRunnable component is represented by the rootProfileRunnable member variable of type SocketProfileRunnable, it has to be transferred to the remote machines. The serialization of the SocketProfileRunnable class to the remote machines is demonstrated in the implementation of the readFrom/writeOn and readExternal/writeExternal methods this class. Alternatively, serialization to remote machines can reuse the code that saves component configuration to the load test project. For the SocketRunnable example, the SocketRunnableXMLSerializer class functionality can be reused to serialize/deserialize the component configuration to remote machines as an XML string.
Your component code can use jar Java libraries of your choice. The SocketRunnable example code uses the JTidy library to analyze the HTML code that it can receive in response to a Web page request (see checkTidy method of the SocketTest class). The component dependency jar files must be included into the component jar archive lib folder (see the socket.jar component archive built by the component-build.xml ant script).
You can use the LocalizationUtil API class to localize component strings. The Localization class of the SocketRunnable example loads the appropriate resource bundle and wraps the LocalizationUtil methods for easier access.