Usage

This guide provides a basic overview of how to install and run a test recipe using the pypts framework.

Installation

This section provides the neccesary information needed to setup the environment and test to run. Before using pypts, you may need to install the following system dependencies for PySide6 (Qt GUI framework):

sudo dnf install libxcb libxcb-devel
sudo dnf install xcb-util xcb-util-wm xcb-util-keysyms xcb-util-image xcb-util-renderutil

To setup the test, start in the desired directory. Make a virtual environment. Name is arbitrary.

python -m venv .venv

Activate the environment. Install the package from Acc-PyPI CERN.

python -m pip install pts-framework==0.2.0

There are two ways of setting up the pypts framework after the package has been installed. A package-based setup or a minimal setup consisting of only test and recipe.

1. Minimal setup pypts-framework

The minimal setup does not use package-based recipe, see “Recipe YAML format”, but uses a gui. Through the gui, the recipe is loaded, which runs the tests. An example of the package structure is:

my_cwd/
├── .venv
├── tests/
│   ├── __init__.py
│   └── tests.py
└── my_recipe.yaml

But the only requirements is the recipe and the tests described in the recipe. Note: tests are required to be at least one directory down from the cwd. To run the test, the following command is required.

python -m pypts

This initializes the GUI where the recipe can be loaded and run. This pypts framework should not have a package in its recipe.

Setting up the framework

To setup the test from scratch, you can either use the provided initialization script or manually configure the environment. If using the init_env_min.exe executable:

init_env_min

This will set up the entire required framework. To understand the setup process, check the __main__.py file to see how the GUI is initialized.

Using the framework

To use the framework, the __main__.py file is required. Once the entire framework is set up, execute the following command to run the tests:

python -m pypts

This initializes the standard GUI. From the GUI, you can perform the following actions:

  • Open: Click to load the recipe into the framework. The recipe will be displayed in the GUI.

  • Start: Click to begin recipe execution. The tests will run according to the recipe definition.

  • Stop: Click to halt the currently running test. The framework will cleanly shut down and finalize results before displaying a summary in the GUI.

If the recipe includes a UserInteractionStep, interactive buttons will appear on the right side of the GUI below any displayed images.

For the current panelized GUI structure, see GUI Architecture.

2. Package-based pypts-framework

If the test is expected to be package-based, a different setup is required. With the installed package, the following structure is necessary:

CWD/
├── .venv
├── pyproject.toml
└── package/
    ├── __init__.py              # package root
    ├── __main__.py              # required to initialize the package
    ├── recipe.yaml              # inside package folder
    └── tests/                   # Not required to put tests in their own directory.
        ├── __init__.py          # tests as subpackage
        ├── test_module1.py
        └── test_module2.py

The recipe is not required to be inside the package, however the tests are. To compile into its own package, run:

pip install -e .

This will initialize your software as a package that can now be called:

python -m package

Setting up the framework

To setup the test from scratch, you can either use the provided initialization script or manually configure the environment. If using the init_env_pack.exe executable:

init_env_pack

This will set up the entire required framework. When making package-based tests using the PTS framework, it is required to include a pyproject.toml file that describes the package contents and its required libraries.

The framework requires the pts-framework to operate and must be installed. To make the package callable via python -m package, run:

python -m pip install -e .

This installs the package in editable mode so it can be executed directly.

Using the framework

To use the framework, the __main__.py file is required. Once the entire framework is set up, you can run the package-based framework with:

python -m package

This initializes the standard GUI. From the GUI, you can perform the following actions:

  • Open: Click to load the recipe into the framework. The recipe will be displayed in the GUI.

  • Start: Click to begin recipe execution. The tests will run according to the recipe definition.

  • Stop: Click to halt the currently running test. The framework will cleanly shut down and finalize results before displaying a summary in the GUI.

If the recipe includes a UserInteractionStep, interactive buttons will appear on the right side of the GUI below any displayed images.

For the current panelized GUI structure, see GUI Architecture.

Setting up required files for package-based pypts-framework

The required files for a package based setup are the files __main__.py and pyproject.toml mentioned in the section above. The __main__.py file is responsible for running the code. It is constructed as below.

from pypts import run_pts
from pypts.startup import create_and_start_gui
import sys

if __name__ == '__main__':

    api = run_pts()

    window, app = create_and_start_gui(api, recipe_file="optional path to recipe if gui should start with preloaded recipe")
    # Start the Qt event loop
    exit_code = app.exec()

    # Exit with the application's exit code
    sys.exit(exit_code)

The main file does not require anything else to initialize and run the GUI. In create_and_start_gui() there is an optional argument which is the recipe_file=. By giving this the path to your recipe, the GUI will have the recipe preloaded upon startup.

The pyproject file operates similarily to a makefile and is the construction of a package based on the files inside. This allows for calling the package like python -m package

1. Define your Recipe (my_recipe.yaml)

Create a YAML file defining your test sequence. The recipe consists of a main document defining metadata and global variables, followed by documents defining named sequences. See Recipe YAML Format for full explaination of all steps available for recipe.

my_recipe.yaml
# SPDX-FileCopyrightText: 2026 CERN <home.cern>
# SPDX-License-Identifier: CC-BY-SA-4.0
---
name: Device acceptance recipe
version: "1.0"
recipe_version: 2.0.0
description: Configure a device, measure it, and disconnect safely.
main_sequence: Main
test_package: my_project.tests
globals:
  device_address: COM3
  test_voltage: 5.0
---
sequence_name: Main
description: Run the device acceptance flow.
parameters: {}
locals:
  measurement: null
outputs: {}
setup_steps:
  - steptype: PythonModuleStep
    step_name: Configure device
    description: Configure the device before measurement.
    action_type: method
    module: device_driver.py
    method_name: setup_device
    input_mapping:
      port: {type: global, global_name: device_address}
      voltage: {type: global, global_name: test_voltage}
    output_mapping:
      success: {type: passfail}
steps:
  - steptype: WaitStep
    step_name: Initial delay
    description: Allow the device to settle.
    input_mapping:
      wait_time: {type: direct, value: 2}
    output_mapping: {}
  - steptype: PythonModuleStep
    step_name: Take measurement
    description: Read and validate the configured voltage.
    action_type: method
    module: device_driver.py
    method_name: read_measurement
    input_mapping: {}
    output_mapping:
      measured_value: {type: local, local_name: measurement}
      status: {type: range, min: 4.8, max: 5.2}
teardown_steps:
  - steptype: PythonModuleStep
    step_name: Disconnect device
    description: Close the device connection during teardown.
    action_type: method
    module: device_driver.py
    method_name: disconnect
    input_mapping: {}
    output_mapping: {}

Note

Replace device_driver.py with the actual name of your Python module containing the methods called by PythonModuleStep. Adding the path should not be done as the system automatically detects the path to the specified test. Therefore, avoid naming modules the same unless you specify a test_package as described below.

Alternative: Resource-Based Module Loading

For better distribution and deployment, you can use resource-based module loading by organizing your test modules as Python packages:

The complete example above already uses resource-based loading. The focused fields are:

# Header fragment
test_package: my_project.tests

# PythonModuleStep fragment
module: device_driver.py  # Resolves to my_project.tests.device_driver

Package Structure Example:

my_project/
├── __init__.py
├── tests/
│   ├── __init__.py
│   ├── device_driver.py
│   └── other_test_modules.py
└── my_recipe.yaml

Benefits of Resource-Based Loading:

  • Distribution: Test modules are bundled with your package

  • Reliability: No dependency on current working directory

  • Deployment: Tests are guaranteed available if package is installed

  • Standards: Uses Python’s standard import mechanism

  • Naming: Avoids errors appearing as a result of tests having the same name between packages

2. Run the Recipe (__main__.py)

In situations where a level of user interaction with buttons is required, the one above is not enough. For a level of user interaction with steptype UserInteractionStep, a GUI is added. As the above, use the run_pts function from the pypts.pts module to execute the recipe file. Use the function create_and_start_gui() from the pypts.startup module to create a gui and start it, using the execution of the run_pts.

__main__.py
from pypts._version import version as __version__
import logging
import sys
import os
from pypts.pts import run_pts
from pypts.startup import create_and_start_gui

logger = logging.getLogger(__name__)
# Configure basic logging
log_format = '%(levelname)s : %(name)s : %(message)s'
logging.basicConfig(level=logging.DEBUG, format=log_format)
# Reduce verbosity of noisy libraries
logging.getLogger("paramiko.transport").setLevel("WARN")


if __name__ == '__main__':
    """Main entry point for the PTS application.

    Sets up the QApplication, MainWindow, logging, RecipeEventProxy,
    and connects signals/slots between the proxy and the window.
    Starts the recipe execution and event processing threads.
    """
    api = run_pts()

    window, app = create_and_start_gui(api)

    exit_code = app.exec()
    sys.exit(exit_code)

It can also be initialized through the command:

python -m pypts

3. Check the Reports

After execution (or during, for the CSV), check the ~/pts_reports/ directory for:

  • report.csv: Incrementally updated CSV file with detailed step results.

  • report.html: HTML version of the report generated after the recipe finishes.

4. Migrating from File-Based to Resource-Based Loading

Both file-based and ressource-based loading are possible for the framework. If you have existing recipes using file-based module loading, here’s how to migrate:

Step 1: Organize Test Modules

Convert your test file structure to a proper Python package:

# Before (file-based)
my_project/
├── tests/
│   ├── test_module1.py
│   └── test_module2.py
└── recipe.yaml

# After (resource-based)
my_project/
├── __init__.py                    # NEW: Makes it a package
├── tests/
│   ├── __init__.py               # NEW: Makes tests a subpackage   ├── test_module1.py
│   └── test_module2.py
└── recipe.yaml

Step 2: Update Recipe Configuration

Add the dotted test_package field and make module paths relative to it:

# File-based module field
module: tests/test_module1.py

# Resource-based header and module fields
test_package: my_project.tests
module: test_module1.py  # Relative to my_project.tests

Step 3: Install and Test

Make sure your package is properly installed:

# Install in development mode
pip install -e .

# Or install normally
pip install .

Step 4: Verify Package Structure

Test that your modules can be imported:

# This should work without errors
import my_project.tests.test_module1

Common Migration Issues

Import Errors: Make sure all directories have __init__.py files

Module Not Found: Verify the test_package field matches your actual package structure

Path Issues: Use paths relative to test_package. For example, helpers/test_module.py imports my_project.tests.helpers.test_module.

Package Installation: Ensure your package is installed in the Python environment where you’re running pypts

5. Running a Recipe

Once your recipe is defined and your environment is set up, you can execute the recipe through the graphical user interface.

Starting the GUI

Launch the application using one of these commands:

# For minimal setup
python -m pypts

# For package-based setup
python -m package

The GUI window will open, displaying the PTS runtime interface as a panelized window. At a high level:

  • the top area contains the menu bar, toolbar, and screen-state tabs

  • the left side contains either the idle placeholder, the live step table, or the final results panel

  • the right side contains the operator interaction panel and the runtime log

See GUI Architecture for the structural details and component breakdown.

Loading a Recipe

In the GUI toolbar, click the “Open” button (folder icon) to load your recipe YAML file. The recipe will be validated and prepared for execution. Once loaded, the recipe name and description appear in the left panel, and the step list is populated with all steps defined in your recipe.

Executing the Recipe

After loading a recipe:

  1. Click the “Start” button (play icon) in the toolbar to begin recipe execution

  2. The GUI will display the current step being executed in the left panel

  3. Step results are updated in real-time with color-coded status indicators:

  • Green: Step passed

  • Red: Step failed

  • Yellow: Step skipped or warning

  • Blue: Step in progress

User Interaction Steps

During recipe execution, if a UserInteractionStep is encountered:

  1. A message box appears on the right side of the GUI with instructions

  2. If the step includes an image, it will be displayed in the image panel

  3. Interactive buttons are dynamically created for user responses (e.g., “Pass”, “Fail”, “Retry”, etc.)

  4. Click the appropriate button to respond to the step request

  5. The recipe will continue after your response is processed

Stopping Execution

To halt recipe execution at any time, click the “Stop” button (stop icon) in the toolbar. The current step will attempt to gracefully terminate, and results collected up to that point will be available for review.

Viewing Results

As the recipe executes:

  • Left Panel - Step List: Shows all steps with their execution status while the recipe is running

  • Left Panel - Results Tree: Displays a hierarchical view of step results after execution completes

  • Right Panel - Interaction Panel: Shows operator prompts, images, and action buttons

  • Right Panel - Log Console: Contains detailed logging information and debug messages

  • Reports Directory: After execution, check ~/pts_reports/ for CSV and HTML reports

6. Creating and Editing Recipes with Recipe Creator tool

For users who prefer a visual approach to recipe creation and editing, the Recipe Creator tool provides an interactive recipe editor. In the codebase this editor is implemented by the YamVIEW package.

Launching Recipe Creator

You can access Recipe Creator through the main PTS GUI:

  1. Open the PTS application as described above

  2. In the menu bar, navigate to Edit → Edit Recipe

  3. A new window will open with the Recipe Creator recipe editor

The runtime GUI and YamVIEW are separate applications. The runtime GUI launches the editor as a separate process, but both now share the same theme layer and dark-mode behavior. See GUI Architecture. Alternatively, if you have Recipe Creator installed separately, you can launch it directly:

python -m pypts.YamView.recipe_creator

Creating a New Recipe

In the Recipe Creator editor: 1. Click File → New Recipe (or the folder icon in the toolbar) 2. A dialog will appear prompting you to configure initial recipe settings 3. Fill in the recipe metadata (name, description, version) 4. Click OK to generate a template recipe 5. The YAML preview will appear on the right side of the editor

Editing Recipes

The Recipe Creator editor provides three main editing surfaces:

  • Sequencer Panel (Left): hierarchical sequence/step editor with toolbar actions

  • YAML Editor (Right): direct YAML text editing with syntax highlighting

  • Interactive Dialogs: double-click any step to open a configuration dialog

Adding Sequences and Steps

In the Sequencer Panel:

  1. Click the “Add Sequence Folder” button (folder icon) to create a new sequence

  2. Click the “➕” button to add a new step to the selected sequence

  3. A dialog will open allowing you to configure the step type, parameters, and mappings

  4. Select the appropriate step type from the dropdown (e.g., PythonModuleStep, WaitStep, UserInteractionStep)

  5. Fill in the required fields for the selected step type

  6. Click OK to add the step to the recipe

Disabling Steps

To temporarily disable steps without removing them:

  1. Select one or more steps in the Sequencer Panel

  2. Click the “±” button (Disable/Enable button)

  3. A dialog will appear listing all steps in the selected sequence

  4. Check the “Skip” checkbox for any steps you want to skip during execution

  5. Check the “Continue on Error” checkbox to allow the recipe to continue even if a step fails

  6. Click OK to apply the changes

Saving Recipes

To save your recipe:

  • Click File → Save Recipe (Ctrl+S) to save to the current file

  • Click File → Save Recipe As to save to a new location

  • Use the “Save” button in the toolbar (disk icon)

Validation and Recovery

The YamVIEW editor includes safety features:

  • Recipe Status Bar: Shows validation status at the top (green for valid, red for errors)

  • Recipe Verification: Recipes are automatically verified on save; if invalid, you’ll be prompted to fix errors

  • Recovery: Click “Restore last working recipe state” (reload icon) to revert to the last successfully validated version

  • Dark Mode: follows the operating system theme automatically and can still be toggled manually from View → Toggle Dark Mode

YAML Synchronization

The editor keeps the YAML view and the Sequencer in sync:

  • Edits in the YAML view are reflected in the Sequencer automatically

  • Changes in the Sequencer are immediately updated in the YAML view

  • Line highlighting shows which YAML section corresponds to the selected step