Step-by-Step Guide

This section provides a step-by-step guide on how to use XOA Core to run XOA test suites.

Create Project Folder

To run XOA test suites, you need a folder to place the test suite plugins, the test configuration files, and yous Python script to control the tests.

Let’s create a folder called /my_xoa_project

Create the project folder
/my_xoa_project
    |

Install XOA Core

After creating the folder, you can either choose to install XOA Core in a Python virtual environment or install in your global namespace .

If you have already installed XOA Core in your system, either to your global namespace or in a virtual environment, you can skip this step.

Place Test Suite Plugins

Depending on what XOA test you want to run, place the corresponding XOA test suite plugins and the test configuration files in /my_xoa_project.

Your project folder will look like this afterwards.

Copy test suite plugins into the project folder
/my_xoa_project
    |
    |- /test_suites
        |- /plugin2544
        |- /plugin2889
        |- /plugin3918

Run Tests from XOA Test Suite Configurations

Important

If you run Valkyrie test suite configuration files (.v2544 for Valkyrie2544, .v2889 for Valkyrie2889, .v3918 for Valkyrie3918, and .v1564 for Valkyrie1564), go to Run Tests from Valkyrie Test Suite Configurations.

Copy your XOA test configuration .json files into /my_xoa_project for easy access. Then create a main.py file inside the folder /my_xoa_project.

Copy XOA test configs and create main.py
/my_xoa_project
    |
    |- main.py
    |- new_2544_config.json
    |- new_2889_config.json
    |- new_3918_config.json
    |- /test_suites
        |- /plugin2544
        |- /plugin2889
        |- /plugin3918

This main.py controls the test workflow, i.e. load the configuration files, start tests, receive test results, and stop tests. The example below demonstrates a basic flow for you to run XOA tests.

from __future__ import annotations
from xoa_core import (
    controller,
    types,
)
import asyncio
import json
from pathlib import Path

PROJECT_PATH = Path(__file__).parent
XOA_CONFIG = PROJECT_PATH / "xoa_2544_config.json"
PLUGINS_PATH = PROJECT_PATH / "test_suites"


async def subscribe(ctrl: "controller.MainController", channel_name: str, fltr: set["types.EMsgType"] | None = None) -> None:
    async for msg in ctrl.listen_changes(channel_name, _filter=fltr):
        print(msg)


async def main() -> None:
    # Define your tester login credentials
    my_tester_credential = types.Credentials(
        product=types.EProductType.VALKYRIE,
        host="10.20.30.40"
    )

    # Create a default instance of the controller class.
    ctrl = await controller.MainController()

    # Register the plugins folder.
    ctrl.register_lib(str(PLUGINS_PATH))

    # Add tester credentials into teh controller. If already added, it will be ignored.
    # If you want to add a list of testers, you need to iterate through the list.
    await ctrl.add_tester(my_tester_credential)

    # Subscribe to test resource notifications.
    asyncio.create_task(subscribe(ctrl, channel_name=types.PIPE_RESOURCES))

    # Load your XOA 2544 config and run.
    with open(XOA_CONFIG, "r") as f:

        # Get rfc2544 test suite information from the core's registration
        info = ctrl.get_test_suite_info("RFC-2544")
        if not info:
            print("Test suite RFC-2544 is not recognized.")
            return None

        # Test suite name: "RFC-2544" is received from call of c.get_available_test_suites()
        test_exec_id = ctrl.start_test_suite("RFC-2544", json.load(f))

        # The example here only shows a print of test result data.
        asyncio.create_task(
            subscribe(ctrl, channel_name=test_exec_id, fltr={types.EMsgType.STATISTICS})
        )

    # By the next line, we prevent the script from being immediately
    # terminated as the test execution and subscription are non blockable, and they ran asynchronously,
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())

Then simply run main.py:

Run test suite in Windows.
[my_xoa_project]> python main.py
Run test suite in macOS/Linux.
[my_xoa_project]$ python3 main.py

Run Tests from Valkyrie Test Suite Configurations

If you want to run your Valkyrie test suite configuration files, you should install xoa-converter to convert Valkyrie test suite configurations into XOA test suite configurations, as illustrated below.

Illustration of Valkyrie-to-XOA conversion flow

See also

Read more about installing XOA Config Convert

Copy your Valkyrie test configurations into /my_xoa_project for easy access. Then create a main.py file inside the folder /my_xoa_project.

Copy Valkyrie test configs and create main.py
/my_xoa_project
    |
    |- main.py
    |- old_2544_config.v2544
    |- old_2889_config.v2889
    |- old_3918_config.v3918
    |- /test_suites
        |- /plugin2544
        |- /plugin2889
        |- /plugin3918

This main.py controls the test workflow, i.e. convert Valkyrie configs into XOA configs, load the configuration files, start tests, receive test results, and stop tests. The example below demonstrates a basic flow for you to run Valkyrie tests.

from __future__ import annotations
import sys
from xoa_core import (
    controller,
    types,
)
import asyncio
import json
from pathlib import Path
# XOA Converter is an independent module and it needs to be installed via `pip install xoa-converter`
try:
    from xoa_converter.entry import converter
    from xoa_converter.types import TestSuiteType
except ImportError:
    print("XOA Converter is an independent module and it needs to be installed via `pip install xoa-converter`")
    sys.exit()

PROJECT_PATH = Path(__file__).parent
OLD_2544_CONFIG = PROJECT_PATH / "old_2544_config.v2544"
OLD_2889_CONFIG = PROJECT_PATH / "old_2889_config.v2889"
PLUGINS_PATH = PROJECT_PATH / "test_suites"


async def subscribe(ctrl: "controller.MainController", channel_name: str, fltr: set["types.EMsgType"] | None = None) -> None:
    async for msg in ctrl.listen_changes(channel_name, _filter=fltr):
        print(msg)



async def main() -> None:
    # Define your tester login credentials
    my_tester_credential = types.Credentials(
        product=types.EProductType.VALKYRIE,
        host="10.20.30.40"
    )

    # Create a default instance of the controller class.
    ctrl = await controller.MainController()

    # Register the plugins folder.
    ctrl.register_lib(str(PLUGINS_PATH))

    # Add tester credentials into teh controller. If already added, it will be ignored.
    # If you want to add a list of testers, you need to iterate through the list.
    await ctrl.add_tester(my_tester_credential)

    # Subscribe to test resource notifications.
    asyncio.create_task(subscribe(ctrl, channel_name=types.PIPE_RESOURCES))

    # Convert Valkyrie 2544 config into XOA 2544 config and run.
    with open(OLD_2544_CONFIG, "r") as f:
        # get rfc2544 test suite information from the core's registration
        info = ctrl.get_test_suite_info("RFC-2544")
        if not info:
            print("Test suite is not recognized.")
            return None

        # convert the old config file into new config file
        new_data = converter(TestSuiteType.RFC2544, f.read())

        # you can use the config file below to start the test
        new_config = json.loads(new_data)

        # Test suite name: "RFC-2544" is received from call of c.get_available_test_suites()
        execution_id = ctrl.start_test_suite("RFC-2544", new_config)


        # The example here only shows a print of test result data.
        asyncio.create_task(
            subscribe(ctrl, channel_name=execution_id, fltr={types.EMsgType.STATISTICS})
        )

    # By the next line, we prevent the script from being immediately
    # terminated as the test execution and subscription are non blockable, and they ran asynchronously,
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())

Receive Test Result Data

XOA Core sends test result data (in JSON format) to your code as shown in the example below. It is up to you to decide how to process it, either parse it and display in your console, or store them into a file.

Receive test result data
async for stats_data in ctrl.listen_changes(execution_id, _filter={types.EMsgType.STATISTICS}):
    print(stats_data)

See also

Read about Test Result Types