Yats – Implementing Custom Test Parameter Type

By | July 22, 2013

This post will give an example on how to add support for a custom test parameter type. The basic idea of test parameter value handling could be summarized as such:

  • A parameter of a certain type is declared in a test case. In this example, the test case parameter could look like:

class MyTest { // ..skipped

private byte[] buffer;

public byte[] Buffer

{

get {return buffer;}

set {buffer = value;}

}

  • Somewhere within Yats DLLs a class implementing AbstractParameterValue is written. It handles (generates, loads, stores etc.) one or more parameter types.
  • During program start, all assemblies (DLLs) are searched for classes implementing AbstractParameterValue.
  • Objects of all such classes are instantiated automatically and their InitType() method is called. In this method, the parameter value type should be associated with a parameter type.
  • Similar to classes handling parameter values, GUI value editors are declared and associated with the parameter value types they support.
  • When a the user is about to edit a parameter (i.e. byte[]), the possible parameter value handler classes (classes implementing¬†AbstractParameterValue) are chosen. Parameter editors supporting the value handlers (classes implementing IEditor interface) are found and shown in tabs.

This creates a mapping of 1 parameter type -> N value handlers -> N editors.

This post will show an example of implementing a value handler that generates a random byte buffer (random size array filled with random bytes). It will be associated with byte[] and List<byte> test case parameters.

Source code:


public class RandomByteArrayValue : AbstractParameterValue
{
// Minimum size of the generated buffer
int minSize;
public int MinSize
{
[DebuggerStepThrough]
get { return minSize; }
[DebuggerStepThrough]
set { minSize = value; }
}

// Maximum size of the generated buffer
int maxSize;
public int MaxSize
{
[DebuggerStepThrough]
get { return maxSize; }
[DebuggerStepThrough]
set { maxSize = value; }
}

// parameterless constructor is needed for serialization
public RandomByteArrayValue()
{
}

public RandomByteArrayValue(int minSize, int maxSize):this()
{
this.minSize = minSize;
this.maxSize = maxSize;
}

public override AbstractParameterValue Clone()
{
return new RandomByteArrayValue(minSize, maxSize);
}

public override void InitType()
{
// a delegate is used to determine that RandomByteArrayValue is suitable for byte[] or List<byte>
ParameterTypeCollection.AddEntry(this.GetType(), "random buffer", delegate(IParameter parameterInfo, ref int valueTypePriority)
{
if ((parameterInfo.IsArray || parameterInfo.IsList) && parameterInfo.ParamType == typeof(byte).AssemblyQualifiedName)
{
valueTypePriority = 30; // low priority - should put the editor tab towards the end
return new RandomByteArrayValue();
}
return null;
});
}

// User-friendly summary for GUI
public override string GetDisplayValue()
{
return string.Format("Random buffer [{0}..{1}]B", minSize, maxSize);
}

// Returns the actual parameter value, to be assigned before running a test case
public override object GetValue(IParameter format)
{
var rnd = new Random();
byte [] result = new byte[rnd.Next(minSize, maxSize)];
rnd.NextBytes(result);
return result;
}

// Used to detect when parameter implementation has been changed between program runs
public override int GetParamValueTypeHash()
{
return this.GetType().Name.GetHashCode();
}
}

The parameter value handler is associated with parameter type. Unfortunately, there are no parameter editor components that could be used to edit the Min/Max values. Editing a byte array parameter will still not suggest a random option yet. A separate post will show how to implement and associate an editor.

Leave a Reply

Your email address will not be published.