Code Examples

  1. Working with Images and starting Sessions based on Images
  2. Simple session creation based on Runner installation
  3. Create and execute a test plan
  4. Load and execute a test plan
  5. Receiving results, logs and events from a Session
  6. How to work with component settings
  7. Configuring a Runner for default execution and using stored test plans on the Runner

Image creation

For this example we have a Runner started which has the ID: HKZ6QN3

Alt text

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);

// Specify image to use for the session
Image image = new Image();
image.Packages = new List<PackageSpecifier>
{
    new PackageSpecifier() { Name = "Demonstration" },
    new PackageSpecifier() { Name = "HTTP", Version = "1.0.0" },

    // We can even specify a different runner version for the session
    new PackageSpecifier() { Name = "Runner", Version = "1.2.1" }
};

image.Repositories = new List<string>() { "https://packages.opentap.io" };

// Ask the Runner to resolve the image. Resolution will check if the image can be created and download any missing packages.
Image resolvedImage = runner.ResolveImage(new List<Image>() { image });

// Start a new session with the resolved image
SessionClient newSession = runner.StartImageSession(resolvedImage);

// Use the session for test automation

// Shutdown the session
runner.ShutdownSession(newSession.Id);

In this example, we successfully resolved an image, started and stopped a session based on the image. This can be verified in the Runner logs:

Alt text

Session creation

Although the Image approach offers flexibility, some use-cases can be kept simple by just using a Runner Session based on the Runner installation.

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);


// Start a new session based on Runner installation
SessionClient newSession = runner.StartSession();

// Use the session for test automation. Plugins available in this session comes from the packages installed in the Runner.

// Shutdown the session
runner.ShutdownSession(newSession.Id);

Create and Run Test Plan

In this example, we use the simple session from the Session creation example above, but before shutting down the session, we setup and run a simple test plan.

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);

// Start a new session based on Runner installation
SessionClient newSession = runner.StartSession();

var types = newSession.GetStepTypes();
var plan = newSession.GetTestPlan(null);
plan.ChildTestSteps.Clear();
plan.ChildTestSteps.Add(types.FirstOrDefault(s => s.TypeName.Contains("Delay")));
plan = newSession.SetTestPlan(plan);

var delayStepSettings = newSession.GetSettings(plan.ChildTestSteps[0].Id);
if (delayStepSettings.FirstOrDefault(s => s.PropertyName == "DelaySecs") is TextBoxControl textBox)
    textBox.StringValue = "3 s";
delayStepSettings = newSession.SetSettings(plan.ChildTestSteps[0].Id, delayStepSettings);

var status = newSession.RunTestPlan(new List<Parameter>());
while (status.ExecutionState != ExecutionState.Idle)
{
    await Task.Delay(1000);
    status = newSession.GetStatus();
}

Console.WriteLine(status.Verdict.ToString());

// Shutdown the session
runner.ShutdownSession(newSession.Id);

In this example, we retrieved the available test step types using GetStepTypes and chose a Delay step and inserted into the Test Plan using SetTestPlan.

Afterwards, we retrieved the Delay step settings and modified the Time Delay to be 3 s.

Lastly, we ran the Test Plan and contiunually asked for the status until the ExecutionState turned back to Idle. The Verdict of the Test Plan was logged and the output of this program would be NotSet.

Load and Run Test Plan

In this example, we use the simple session from the Session creation example above, but before shutting down the session, we load and run a Test Plan locally stored on the disk.

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);

// Start a new session based on Runner installation
SessionClient newSession = runner.StartSession();

newSession.SetTestPlanXML(File.ReadAllText("MyTestPlan.TapPlan"));

var status = newSession.RunTestPlan(new List<Parameter>());
while (status.ExecutionState != ExecutionState.Idle)
{
    await Task.Delay(1000);
    status = newSession.GetStatus();
}

Console.WriteLine(status.Verdict.ToString());

// Shutdown the session
runner.ShutdownSession(newSession.Id);

Results, Logs and Events

In this example, we use the simple session from the Create and Run Test Plan section above, but with results, logs and events logged.

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);

// Start a new session based on Runner installation
SessionClient newSession = runner.StartSession();

// Connect to the session logs
newSession.ConnectSessionLogs(logHandler);
void logHandler(LogList list)
{
    foreach(var log in list.Logs)
        Console.WriteLine($"{log.Source,-12}: {log.Message}");
}

// Connect to the session results
newSession.ConnectSessionResults(resultHandler, runHandler);
void resultHandler(Result result)
{
    Console.WriteLine($"Result: {result.Status}");
}
void runHandler(TestRun run)
{
    Console.WriteLine($"Run: {run.Status}");
}

// Connect to the session events
newSession.ConnectSessionEvents(eventHandler);
void eventHandler(SessionEvent evt)
{
    Console.WriteLine($"Event: {evt.EventType}");
}

var types = newSession.GetStepTypes();
var plan = newSession.GetTestPlan(null);
plan.ChildTestSteps.Clear();
plan.ChildTestSteps.Add(types.FirstOrDefault(s => s.TypeName.Contains("Delay")));
plan = newSession.SetTestPlan(plan);

var delayStepSettings = newSession.GetSettings(plan.ChildTestSteps[0].Id);
if (delayStepSettings.FirstOrDefault(s => s.PropertyName == "DelaySecs") is TextBoxControl textBox)
    textBox.StringValue = "3 s";
delayStepSettings = newSession.SetSettings(plan.ChildTestSteps[0].Id, delayStepSettings);

var status = newSession.RunTestPlan(new List<Parameter>());
while (status.ExecutionState != ExecutionState.Idle)
{
    await Task.Delay(1000);
    status = newSession.GetStatus();
}

Console.WriteLine(status.Verdict.ToString());

// Shutdown the session
runner.ShutdownSession(newSession.Id);

This code should produce the following output, where events, runs and results are prepended with “Event: “, “Run: “, and “Result: “.

Alt text

Working with ComponentSettings

// Create connection
var options = ConnectionFactory.GetDefaultOptions();
options.Servers = new string[] { "nats://127.0.0.1:20111" };
IConnection connection = new ConnectionFactory().CreateConnection(options);
RunnerClient runner = new RunnerClient(connection.ServerInfo.ServerName, connection);
// Create a new session client
SessionClient newSession = runner.StartSession();

try
{
    // Let's get the overview of component settings available in the session

    var componentSettings = newSession.GetComponentSettingsOverview();
    foreach (var componentSetting in componentSettings)
        Console.WriteLine($"Component Setting: {componentSetting.Name} ({componentSetting.GroupName})");

    // Outputs:
    // Component Setting: DUTs(Bench)
    // Component Setting: Engine(-)
    // Component Setting: Instruments(Bench)
    // Component Setting: Connections(Bench)
    // Component Setting: Results(-)
    // Component Setting: Editor(-)
    // Component Setting: Cloud Drive(-)

    // Let's check the instruments component settings
    var intrumentIdentifier = componentSettings.FirstOrDefault(s => s.Name == "Instruments" && s.GroupName == "Bench");


    // Let's assume the session has Demonstration plugin installed and list the available instrument types
    var instrumentTypes = newSession.GetComponentSettingsListAvailableTypes(intrumentIdentifier.GroupName, intrumentIdentifier.Name);
    foreach (var instrumentType in instrumentTypes)
        Console.WriteLine($"Instrument Type: {string.Join("/", instrumentType.TypeDisplay.Group)}/{instrumentType.TypeDisplay.Name}");

    // Outputs:
    // Instrument Type: / Generic SCPI Instrument
    // Instrument Type: Demo / Battery Test / Power Analyzer
    // Instrument Type: Demo / Battery Test / Temperature Chamber
    // Instrument Type: Demo / Results And Timing/ Timing Instrument

    // Let's list the configured instruments
    var instruments = newSession.GetComponentSettings(intrumentIdentifier.GroupName, intrumentIdentifier.Name);
    if (instruments is ComponentSettingsList list)
    {
        foreach (var instrument in list.Items)
            Console.WriteLine($"Instrument: {instrument.Name}");
    }

    // Outputs:
    // Instrument: SCPI
    // Instrument: PSU
    // Instrument: TEMP

    // Let's assume we want to create a new instrument of type "Demo / Battery Test / Power Analyzer"
    instruments = newSession.AddComponentSettingsListItem(intrumentIdentifier.GroupName, intrumentIdentifier.Name, instrumentTypes.FirstOrDefault(s => s.TypeDisplay.Name == "Power Analyzer").TypeName);

    // Let's list the available instruments again
    if (instruments is ComponentSettingsList list2)
    {
        foreach (var instrument in list2.Items)
            Console.WriteLine($"Instrument: {instrument.Name}");
    }

    // Outputs:
    // Instrument: SCPI
    // Instrument: PSU
    // Instrument: TEMP
    // Instrument: PSU (1)

    // Let's check the settings of the new instrument "PSU (1)"
    foreach (var setting in (instruments as ComponentSettingsList).Items[3].Settings)
    {
        Console.WriteLine($"Setting: {setting.Display.Name}");
        if (setting is TextBoxControl textBox)
        {
            Console.WriteLine(textBox.StringValue);
        }
    }

    // Outputs:
    // Setting: Cell Size Factor
    // 0.005
}
finally
{
    runner.ShutdownSession(newSession.Id);
}

Default Endpoints

Default endpoints are endpoints that affect each other. They are:

  • SetDefaultImage: Sets a default image in the Runner environment. The image includes essential packages.
  • GetDefaultImage: Retrieves the currently set default image.
  • SetDefaultSettings: Applies default settings for the Runner. Settings might have various package dependencies.
  • GetDefaultSettings: Retrieves the current settings from the Runner.
  • StartDefaultSession: Starts a session using the default settings and image.
  • StartDefaultSessionOverrideImage: Begins a session with an overridden image for specific use cases.
  • SetTestPlans: Sets a list of test plans to be used in the Runner.
  • AddTestPlan: Adds a single test plan to the current list in the Runner.
  • GetTestPlans: Retrieves the list of test plans stored in the Runner.

A Session’s plugin configuration depends on:

  • The dependencies of the TestPlan.
  • The dependencies of the Settings.
  • The packages defined in a “default image”.
  • Optionally, the packages defined in an “image override”.

The following example demonstrates how to use the RunnerClient for managing test plans in a Runner session.

public static void DefaultTestPlanShowcase(RunnerClient runnerClient)
{
    // Set the base image. This includes basic packages that are not dependencies of the TestPlans or SettingsPackage
    Image baseImage = new Image()
    {
        Packages = new List<PackageSpecifier>()
        {
            new PackageSpecifier() { Name = "Runner", Version = "1.7.0" }
        },
        Repositories = new List<string>()
        {
            "https://packages.opentap.io"
        }
    };
    runnerClient.Default.SetImage(baseImage); // Apply the base image configuration

    // Define and set the Settings Package
    RepositoryPackageReference settingsPackageReference = new RepositoryPackageReference()
    {
        Repository = "https://test-automation.pw.keysight.com/api/packages",
        Path = "/users/dennis.rasmussen@keysight.com/BatterySettings.TapPackage",
        Version = "0.2.0"
    };
    runnerClient.Default.SetSettings(settingsPackageReference); // Apply settings package

    // Define and add Default TestPlans to be stored in the Runner
    List<RepositoryPackageReference> testPlans = new List<RepositoryPackageReference>()
    {
        // Define individual test plans
        new RepositoryPackageReference
        {
            Repository = "https://test-automation.pw.keysight.com/api/packages",
            Path = "/users/dennis.rasmussen@keysight.com/BatteryPlan.TapPlan",
            Version = "0.1.0-Draft.5"
        },
        new RepositoryPackageReference
        {
            Repository = "https://test-automation.pw.keysight.com/api/packages",
            Path = "/users/dennis.rasmussen@keysight.com/Demonstration.TapPlan",
            Version = "0.1.0-Draft.4"
        },
        new RepositoryPackageReference
        {
            Repository = "https://test-automation.pw.keysight.com/api/packages",
            Path = "/users/dennis.rasmussen@keysight.com/Calibration.TapPlan",
            Version = "0.1.0-Draft.1"
        }
    };

    // Add and set the test plans in the Runner
    runnerClient.Default.AddTestPlan(testPlans[0]);
    runnerClient.Default.SetTestPlans(testPlans); // Set multiple test plans at once

    // Fetch and run the stored TestPlans
    foreach (var plan in runnerClient.Default.GetTestPlans())
    {
        Console.WriteLine($"TestPlan: {plan.Path} {plan.Version}");

        // Start a session for each test plan
        // The Session will have the Packages needed required from the BaseImage, Settings dependencies & TestPlan dependencies
        // The Session will also already have the Settings and the TestPlan loaded
        var session = runnerClient.Default.StartSession(plan); 

        try
        {
            // Run the TestPlan and monitor its execution
            var status = session.RunTestPlan(new List<Parameter>());
            while (status.ExecutionState != ExecutionState.Idle)
            {
                status = session.GetStatus(); // Continuously check the status
                Thread.Sleep(1000); // Delay to avoid overloading
            }
            Console.WriteLine($"TestPlan: {plan.Path} {plan.Version} - Verdict {status.Verdict}");
        }
        finally
        {
            runnerClient.ShutdownSession(session.Id); // Ensure session is properly closed
        }
    }
}

Future code examples:

  • Editing Step and TestPlan settings
  • Load from and save to Repository