TestUnit Integration

From Second Life Wiki
Jump to navigation Jump to search

This document assumes that you have already read this page: http://wiki.secondlife.com/wiki/LSL_Test_Harness, with special attention to the section called, "The Test Unit(s)".

First, open the Test Unit template page here: http://wiki.secondlife.com/wiki/TestUnit_TestScript.lsl

I will use the Binary Operators Test Unit in this exmaple: https://wiki.secondlife.com/wiki/TestUnit_MATH_Binary_Operators.lsl

The Test Units run tests that you create yourself, and insert into the Test Unit Template. They have 4 parts that require attention, Global Variables,

Runtest, Report and Initialize. Before you sit down and start adding anything to a Test Unit, you need to define what you want to accomplish.

Choose an area of functionality and extract all of the data that you need to go into, and out of the test.

I will break them down the 4 major sections where you, the author, will be adding data, below:

Global variable declaration

This is where you place all of the variable declarations for the variables that you will use in your Test Unit script. This includes the

defaults that the script uses. It is good practice to create a pass variable for each test that you put into the Test Unit. The following is an excerpt

from the Binary Operators test script:

			// Global Variables
			
			/// These variables are used in all LSL Test Unit scripts.
			integer toAllChannel = -255;           // (for all Test Units)general channel - linked message
			integer passFailChannel = -355;        // test scripts channel for cummunicating pass/fail - linked message
			integer debug = 0;                     // level of debug message
			integer debugChannel = DEBUG_CHANNEL;  // output channel for debug messages
			
			// These variables are unique to this script.
			integer ArithmeticAddition_PASS;                    
			integer ArithmeticSubtraction_PASS;                  
			integer ArithmeticMultiplication_PASS;                 
			integer ArithmeticDivision_PASS;                  
			integer ArithmeticModulo_PASS;                    
			integer ArithmeticGreaterThan_PASS;               
			integer ArithmeticLessThan_PASS;
			integer ArithmeticGreaterThanOrEqualTo_PASS; 
			integer ArithmeticLessThanOrEqualTo_PASS; 
			integer LogicalInequality_PASS; 
			integer LogicalEquality_PASS; 
			integer LogicalAND_PASS; 
			integer LogicalOR_PASS; 
			integer BitwiseAND_PASS; 
			integer BitwiseOR_PASS; 
			integer BitwiseLeftShift_PASS; 
			integer BitwiseRightShift_PASS;
			integer BitwiseExclusiveOR_PASS;

Runtest

This section is where the tests are actually run. It is broken down into three discrete parts. In most cases, the first is a series of

conditional statements against the data set that you established, where each conditional statement sets a pass bit. Here is an example, from the

Binary Operators Test Unit:

			RunTest()
			{
			        // initialize PASS variable        
			        ArithmeticAddition_PASS = 0;
			        // Compare data against criteria in GetType function, which returns an integer corresponding to the type.        
			        if (1 + 1 == 2)
			        {
			            ArithmeticAddition_PASS = 1;
			        }
        			
			        // initialize PASS variable        
			        ArithmeticSubtraction_PASS = 0;
			        // Compare data against criteria in GetType function, which returns an integer corresponding to the type.        
			        if (1 - 1 == 0)
			        {
			            ArithmeticSubtraction_PASS = 1;
			        }
			        
			        // initialize PASS variable        
			        ArithmeticMultiplication_PASS = 0;
			        // Compare data against criteria in GetType function, which returns an integer corresponding to the type.        
			        if (2 * 2 == 4)
			        {
			            ArithmeticMultiplication_PASS = 1;
			        }
			        
			        // initialize PASS variable        
			        ArithmeticDivision_PASS = 0;
			        // Compare data against criteria in GetType function, which returns an integer corresponding to the type.
			        if (4 / 2 == 2)
			        {
			            ArithmeticDivision_PASS = 1;
			        }

...and so on.

The second part in the Runtest section is where you look at your PASS variables to check for any failures. If there are no failures in the

test, a global PASS variable is set for the entire Test Unit:

			//check to see if any failures occured. 
			   integer pass = ArithmeticAddition_PASS &
			                  ArithmeticSubtraction_PASS &
			                  ArithmeticMultiplication_PASS &
			                  ArithmeticModulo_PASS &
			                  ArithmeticDivision_PASS &
			                  ArithmeticGreaterThan_PASS &
			                  ArithmeticLessThan_PASS &
			                  ArithmeticGreaterThanOrEqualTo_PASS &
			                  ArithmeticLessThanOrEqualTo_PASS &
			                  LogicalInequality_PASS &
			                  LogicalEquality_PASS &
			                  LogicalAND_PASS &
			                  LogicalOR_PASS &
			                  BitwiseAND_PASS &
			                  BitwiseOR_PASS &
			                  BitwiseLeftShift_PASS &                       
			                  BitwiseRightShift_PASS &
			                  BitwiseExclusiveOR_PASS;

The last part of the Runtest section of the Test Unit broadcasts your global pass/fail result to the main harness, and looks like this:

			     // if all of the individual cases pass, test passes.                                
			     if( pass )
			     {
			       llMessageLinked(LINK_SET, passFailChannel, "PASS", NULL_KEY);
			     }
			     else
			     {
			         llMessageLinked(LINK_SET, passFailChannel, "FAIL", NULL_KEY);
			     }

Report

The Report mechanism takes your pass / fail data, and maps it to results output in three ways, QUIET, NORMAL, and VERBOSE. How

you set up your reporting mechanisms is up to you, but all three should be available to the Test Harness for reporting, as the Harness Coordinator

has these options built in, in the controller. For each report type, construct report strings based on what ever level you want to provide for the

data that you tested in your Test Unit. It is up to you how you will package your report data, to be sent back to the report utility in the harness.

Here is an example of what a section of the VERBOSE report string building in the Binary Operators Test Unit:

			//VERBOSE - highest level of reporting
			if( reportType == "VERBOSE" )
			{
			         reportString = "///////////////////////////////////////////////////////////////////////////////////////////" + "\n"+
			            "// Type: ArithmeticAddition" + "\n" +
			            "// Returns an integer representing the integer type constant" + "\n" +
			            "// • ArithmeticAddition = 1" + "\n" +
			            "///////////////////////////////////////////////////////////////////////////////////////////" + "\n" +
			            "PASS/FAIL -> " + ArithmeticAddition_PASSstring + "\n\n" +
			
			            "/////////////////////////////////////////////////////////////////////////////////" + "\n" +
			            "// Type: BitwiseExclusiveOR" + "\n" +
			            "// Returns an integer representing the invalid data type constant" + "\n" +
			            "// • BitwiseExclusiveOR = 0" + "\n" +
			            "/////////////////////////////////////////////////////////////////////////////////" + "\n" +
			            "PASS/FAIL -> " + BitwiseExclusiveOR_PASSstring + "\n\n";                 
			    
			} // end verbose

This is what the section looks like that sends the report string variable to the Coordinator:

			//AddUnitReport()
			//send to Coordinator on the broadcastChannel the selected report
			//format example -> AddUnitReport::unitKey::00000-0000-0000-00000::Report::Successful Completion of Test
			llSay( controlChannel, "AddUnitReport::unitKey::" + (string)llGetKey() + "::Report::" + reportString);

Initialize

This section is used solely to place the name of your Test Unit's name in hovertext above the Test Unit in world. The following is an

example of how that looks:

			Initialize()
			{
			    llSetText( "MATH_BinaryOperators", <255,255,255>, 1);
			}


Reminder

Don't forget to add the appropriate information to your TestUnit_nc (TestUnit Notecard). Here is what is contained in the notecard for this test:

            UnitName:[BinaryOperators]
            GroupName:[MATH]