Data Production Library (DPL)

PushToTest TestMaker's Data Product Library (DPL) is a powerful system to deliver data to tests at runtime. For instance, a test of an on-line registration service stores name and password values in a database and uses a DPL to access the database as the test operates. In a second instance, a test of a reporting service uses a DPL to access a comma-separated-value (CSV) file of acceptable responses to validate service responses.

Software developers, QA technicians, and IT managers with a variety of technical skills use TestMaker. It is important to provide DPLs that are ready to use and require no programming skills and to offer a framework for building your own DPLs. TestMaker 5 comes with the following DPLs:

DPL Goal DPL Package Name Description
Lingo DPL, creates pseudo English-like text words and sentences com.pushtotest.tool.dpl.provided.LingoDPL Input the number of gibberish words
Comma separated value (CSV) file DPL CSVDPL Input the path to the CSV file.
Relational Database Management System (RDBMS) DPL RDBMSDPL Input the URI to the datasource, ID, password, and SQL


NOTE: The standard DPL for TestMaker’s TOOL is CSVDPL.


Example Of A Provided DPL

In this example we will create a test in Jython, a TestScenario for a load test, and use the Lingo DPL.

Lingo is a package in TOOL that creates pseudo English-like text words and sentences. For instance, a call to Lingo will produce something like: Ipsem Delorum Sit Vernes. The Lingo test is handy when you need random text to insert into a field during a test.

We begin by writing a unit test of a service written in Jython:

from com.pushtotest.tool.protocolhandler import ProtocolHandler, HTTPProtocol
from com.pushtotest.tool.response import Response
import junit

# Base class of functions that support this test agent
# find this in testmaker_home/lib/agentbase.py
import agentbase

class DPLExample( agentbase.agentbase, junit.framework.TestCase ):
    '''
    Base class implements abstract methods need by recorded test agent script.
    '''

    def __init__( self, debuglevel = 0, logto="console", follow_redirects=0, \
                  successcodes='20.|300|301|302|303|304|307|401|403|408|41.', \
                  logpath="log.txt", sleeptime_min=0, sleeptime_max=0, imagesleeptime=0, \
                  loadimgtags = "1", imagecache = "1", agentname="test", openlog=1 ):
        ''' Initialize this test '''

        # Call the agentbase superclass's init method
        agentbase.agentbase.__init__( self, debuglevel, logto, follow_redirects, \
                                      successcodes, logpath, sleeptime_min, sleeptime_max, imagesleeptime, \
                                      loadimgtags, imagecache, agentname, openlog )

        junit.framework.TestCase.__init__(self, agentname)

    def setUp( self ):
        ''' Add any needed set-up code here. '''
        self.log( 1, "test: setUp" )
        self.config()

    def runTest( self, dpl_provided_argument_value ):
        ''' Run the test '''
        self.log( 1, "test: runTest" )

        self.params = [ [ '''testinput''', dpl_provided_argument_value ] ]
        self.get( '''http://examples.pushtotest.com/responder/htmlresponder''', self.params)

    def tearDown( self ):
        ''' Add any needed code to end the test here. '''
        self.log( 1, "test: tearDown" )


The code implements a JUnit TestClass named DPLExample. The runTest method takes a single argument, dpl_provided_argument_value, and passes it to the service being tested.


Next we create a TestScenario document defining a load test using the DPLExample class and runTest method. The class and TestScenario are found in testmaker_home/example_agents/DPLExamples (the following are the selected excerpts from the TestScenario document).

The <DataSources> element specifies the DPL type (type="Lingo DPL") and names it (name="lingo"). It also specifies the source to take one argument and return a single word (value="1"):

  <DataSources>
     <dpl name="lingo" type="LingoDPL">
     <argument dpl="lingo" value="1"/>
   </dpl>
  </DataSources>


The <resources> section identifies the Jython script:

  <resources>
       <module name="DPLExample" path="./example_agents/dplExample/DPLExample.py"/>
  </resources>


The <run> section tells TestMaker how to run the test, namely to get the next value from the Lingo DPL and use it as the argument to the runTest method call:

  <run name="test1" testclass="DPLExample" method="runTest" langtype="jython">
      <argument name="argrun2" dpl="lingo" value="getNextData"/>
  </run>



Creating Your Own DPL

Creating your own DPL requires Java programming skills and a familiarity with the DPL abstract class definition. Implementing a DPL requires a Java class to implement the standard DPL methods including getNextData, getDataByIndex, and more (example DPL source code and resources can be found in testmaker_home/example_agents/dplExample).

Once you define and compile a custom DPL, use the <DataSources> in a TestScenario document to identify your custom DPL. You may even pass parameters to your DPL at runtime. This TestScenario excerpt shows how to do this:

  <DataSources>
      <dplDefType name="SimpleDPL" library="./example_agents/dplExample/dplSimple.jar"
          lang="java" classname="com.dpl.SimpleDPL"/>

      <dpl name="lingo" type="LingoDPL"/>

      <dpl name="simple" type="SimpleDPL">
          <argument name="argrun2" value="Data"/>
      </dpl>

      <dpl name="simple" type="SimpleDPL">
          <argument name="argrun2" dpl="lingo" value="getNextData"/>
      </dpl>
  </DataSources>



Comma Separate Value (CSV) DPL

NOTE: This section presents an example found in testmaker_home/example_agents/dplCSVExample.

Comma separated value (CSV) files contain data formatted into rows, where each row is on a single line and contains one or more fields separated by commas. The CSV Data Production Library (DPL) reads rows of data from a CSV file and passes the data to a test script as string arrays.

Consider the following example data:


  Name,Age,Eye Color,Hair Color
  Pepe,24,black,red
  Heriberto,56,black,blue
  Austelina,77,black,yellow


Since each row contains the same number of fields, the data may be represented by a table:

Name Age Eye Color Hair Color
Pepe 24 Black red
Heriberto 56 Black blue
Austelina 77 Black yellow

You configure the CSV DPL in the <resources> section of a TestScenario document by defining its parameters including programs, Java classes, modules, and scripts. This example identifies a Java resource (print.jar) and a CSV data file (csv.txt):

  <resources>
      <data path="./example_agents/dplCSVExample/csv.txt"/>
      <jar path="./example_agents/dplCSVExample/print.jar"/>
  </resources>

TestMaker is a distributed environment and the files identified in the <resources> section are distributed to the TestNodes. When using a CSV DPL, test scripts do not access data through a direct path, for example a local directory (/usr/local/csv.txt or c:\documents\csv.txt), instead your TestScenario identifies a DPL and the DPL provides the data to the script. Here is an example:

  <DataSources>
      <dpl name="csv" type="CSVDPL">
          <argument name="file" dpl="rsc" value="getDataByIndex" index="0"/>
      </dpl>
  </DataSources>

The <DataSources> and <dpl> elements identify the CSV DPL type, a DPL resource name, and specifies the index to the first row of data.

As an example of how this works, this <messagesizes> element, from the example TestScenario document (testDPLCVS.xml), defines a load test to check a service with three different message sizes.

  <messagesizes>
      <messagesize value="0"/>
      <messagesize value="1"/>
      <messagesize value="2"/>
   </messagesizes>

The message size values are index values meaning the message size value 0 tells the DPL to use the first row of data in a CSV file.


Following are some example <run> element definitions.

This definition uses the DPL to get the next row of data; when the end of the file is reached, getNextData moves the DPL to the beginning of the file:

<run name="CVS" testclass="com.examples.print" method="print" langtype="java">
    <argument name="arg" dpl="csv" value="getNextData"/>
</run>


This definition uses the DPL to get a specific row of data, the first row (index="0"):

<run name="CVS" testclass="com.examples.print" method="print" langtype="java">
    <argument name="arg" dpl="csv" value="getDataByIndex" index="0" />
</run>


This definition uses the DPL to get the row of data defined by the <messagesize> value for the test-use-case during a load test:

<run name="CVS" testclass="com.examples.print" method="print" langtype="java">
    <argument name="arg" dpl="csv" value="getDataByIndex" index="messagesize"/>
</run>


Multiple Data Files

Multiple DPLs may be used in one TestScenario, as this example where the <resource> element identifies two data files:

<resources>
    <data path="./example_agents/dplCSVExample/csv.txt"/>
    <data path="./example_agents/dplCSVExample/otherFile.txt"/>
</resources>


To access the first file (csv.txt):

    <argument name="firstfile" dpl="rsc" value="getDataByIndex" index="0"/>

To access the second file (otherFile):

    <argument name="secondfile" dpl="rsc" value="getDataByIndex" index="1"/>

To use the CSV DPL, the DPL must created:

<DataSources>
    <dpl name="csv" type="CSVDPL">
         <argument name="file" dpl="rsc" value="getDataByIndex" index="0"/>
    </dpl>
</DataSources>


That definition mapped in Java code:

CSVDPL cvs = new CSVDPL();
Cvs.setup(“/remote_resource_path/cvs.txt”);


This is the definition to access a data row from the CSVDPL:

<run name="CSV example 1" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl="csv" value=" getDataByIndex" index="0"/>
</run>

<run name="CSV example 1" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl="csv" value=" getDataByIndex" index="1"/>
</run>

<run name="CSV example 2" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl="csv" value=" getDataByIndex" index="0"/>
</run>


That definition mapped in Java code:

simple.print spr = new simple.print();
spr.print (new String[] { “Name”, “age” , “eye color”, “hair color” };
spr.print (new String[] { “Pepe”, “24”, “black”, “red” };

simple.print spr2 = new simple.print ();
spr2.print (new String[] { “Name”, “age”, “eye color”, “hair color” };



Relational Database Management System (RDBMS) DPL

Relational Database Management Systems (RDBMS) store data in a relational model of tables, rows, and columns. The Structured Query Language (SQL) provides a syntax for defining views of the relational model. The Data Production Library (DPL) generates data from a relational database and passes the data to a test at runtime.

Note: The following presents an example found in testmaker_home/example_agents/MYSQLExample.

The RDBMS DPL has five configuration parameters: Here is the configuration syntax:

<DataSources>
    <dpl name=" rdbms" type="RDBMSDPL">
        <argument name="connector" value="com.mysql.jdbc.Driver" />
        <argument name="url" value="jdbc:mysql://localhost/tmstatus" />
        <argument name="login" value="userlogging" />
        <argument name="password" value="12345" />
        <argument name="query" value="select * from scenario" />
     </dpl>
</DataSources>


That definition mapped in Java code:

RDBMSDPL rdbms = new RDBMSDPL();
rdbms.setup(com.mysql.jdbc.Driver”,
            "jdbc:mysql://localhost/tmstatus",
            " userlogging ",
            "12345",
            “select * from scenario”);


Given a table called "person" in a SQL database called "tmstatus":

Name Age Eye Color Hair Color
Pepe 24 Black red
Heriberto 56 Black blue
Austelina 77 Black yellow


The syntax to access a data row using the RDBMS DPL:

<run name="CSV example 1" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl=" rdbms" value=" getDataByIndex" index="0"/>
</run>

<run name="CSV example 1" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl=" rdbms value=" getDataByIndex" index="1"/>
</run>

<run name="CSV example 2" testclass="simple.print" method="print" langtype="java">
    argument name="arrayString" dpl=" rdbmss value=" getDataByIndex" index="0"/>
</run>


Those definitions mapped in Java code:

simple.print spr = new simple.print ();
spr.print (new String[] { “Name”, “age”, “eye color”, “hair color” };
spr.print (new String[] { “Pepe”, “24”, “black”, “red” };

simple.print spr2 = new simple.print ();
spr2.print (new String[] { “Name”, “age”, “eye color”, “hair color” };



Lingo Provided DPL Source Code

To help understand how to create DPLs, here is the source code for the Lingo DPL:

package com.pushtotest.tool.dpl.provided;

import com.pushtotest.tool.dpl.DataProduction;
import com.pushtotest.tool.util.Lingo;
import java.util.Vector;
import java.util.Random;
import java.util.Date;

/**
 * DPL that provides Dummy text of the type "Lorem ipsum.."
 * @author wmartinez
 */
public class LingoDPL implements DataProduction{

    private Random myRandom = new Random(new Date().getTime());
    private Vector vPayloads = new Vector();
    private Lingo lingoGen = new Lingo();
    private int iPosition = 0;
    
    /** Creates a new instance of LingoDPL */
    public LingoDPL() {
    }

    public void setup() {
        // Default of Lingo default size
        vPayloads.add(lingoGen.getMessage());
    }

    public void setup(int messSize) {
        // Creates only one message of messSize
        vPayloads.add(lingoGen.getMessage(messSize));
    }

    public void setup(String[] arguments) {
        // arguments contains a list of sizes in string form
        for (String sSize: arguments) {
            int iSize = Integer.parseInt(sSize);
            vPayloads.add(lingoGen.getMessage(iSize));
        }
    }

    public Object getData() {
        return vPayloads.get(iPosition);
    }

    public Object getRandomData() {
        return vPayloads.get(myRandom.nextInt(vPayloads.size()));
    }

    public Object getNextData() {
        Object sToReturn = vPayloads.get(iPosition++);
        if (iPosition == vPayloads.size()){
            iPosition = 0;
        }
        return sToReturn;
    }

    public Object getDataByIndex(int index) {
        if (index >= vPayloads.size())
            index = vPayloads.size()-1;
        return vPayloads.get(index);
    }

    public void tearDown() {
        vPayloads.clear();
    }
    
}



Additional documentation, product downloads and updates are at www.PushToTest.com. While the PushToTest TestMaker software is distributed under an open-source license, the documentation remains (c) 2007 PushToTest. All rights reserved. PushToTest is a trademark of the PushToTest company.