# How DiscoveryMixIn Converts Cartesian Config Parameters to Avocado Test Parameters

> Learn how DiscoveryMixIn converts Cartesian config to Avocado test parameters. Explore identifier resolution, naming rules, and Avocado nrunner API compatibility.

- Repository: [avocado/avocado-vt](https://github.com/avocado-framework/avocado-vt)
- Tags: how-to-guide
- Published: 2026-02-25

---

**The `DiscoveryMixIn` class transforms raw Cartesian configuration dictionaries into structured Avocado test parameters by resolving test identifiers, applying backend-specific naming rules, and wrapping the result into a format compatible with the Avocado nrunner API.**

In the `avocado-framework/avocado-vt` repository, the bridge between legacy Cartesian configuration files and the modern Avocado test runner is implemented in the `DiscoveryMixIn` class. Located in [`avocado_vt/discovery.py`](https://github.com/avocado-framework/avocado-vt/blob/main/avocado_vt/discovery.py), this mixin provides the `convert_parameters()` method that translates the flat key-value pairs of a Cartesian config into the enriched parameter structure required by Avocado-VT's resolver and loader components.

## The Conversion Pipeline in DiscoveryMixIn

The `convert_parameters(self, params)` method orchestrates a six-step transformation process. According to the source code in [[`avocado_vt/discovery.py`](https://github.com/avocado-framework/avocado-vt/blob/main/avocado_vt/discovery.py)](https://github.com/avocado-framework/avocado-vt/blob/master/avocado_vt/discovery.py), the method begins at line 41 and handles the conversion through several distinct phases.

### Step 1: Receiving Raw Cartesian Parameters

The method accepts a `params` dictionary containing every key-value pair parsed from the Cartesian configuration matrix. This includes test-specific parameters like `mem`, `nettype`, and `image_format`, alongside metadata keys such as `_short_name_map_file` that track the configuration's origin.

```python

# Example input from the Cartesian parser

cartesian_params = {
    "_short_name_map_file": {"subtests.cfg": "tests/linux/boot"},
    "mem": "2048",
    "nettype": "bridge",
    "image_format": "qcow2"
}

```

### Step 2: Resolving the Test Identifier

The mixin determines the canonical test name through a hierarchical resolution strategy defined in lines 49-58. By default, the test name is extracted from `params["_short_name_map_file"]["subtests.cfg"]` as implemented at lines 49-50.

However, the method supports two override mechanisms. First, if the user provides a `vt-config` file and sets the option `vt.short_names_when_config` to true, the name is taken from the `shortname` key in the Cartesian dictionary (lines 50-53). Second, for the **spice** backend specifically—detected when `vt.type` equals `"spice"`—the mixin checks for an alternative key [`tests-variants.cfg`](https://github.com/avocado-framework/avocado-vt/blob/main/tests-variants.cfg) in the short name map (lines 54-58).

```python

# Default resolution

test_name = params.get("_short_name_map_file")["subtests.cfg"]

# Override with shortname if config flags are set

if get_opt(self.config, "vt.config") and get_opt(self.config, "vt.short_names_when_config"):
    test_name = params.get("shortname")

# Spice backend handling

elif get_opt(self.config, "vt.type") == "spice":
    short_name_map_file = params.get("_short_name_map_file")
    if short_name_map_file.get("tests-variants.cfg"):
        test_name = short_name_map_file["tests-variants.cfg"]

```

### Step 3: Enriching and Wrapping Parameters

Once resolved, the test identifier is injected back into the parameter dictionary at line 62 via `params["id"] = test_name`. This enrichment allows test code to reference its own identifier during execution. Finally, the method returns a structured dictionary at lines 63-64 containing two keys: `name` (the URI used by the runner) and `vt_params` (the original Cartesian dictionary now containing the `id` field).

```python
params["id"] = test_name
test_parameters = {"name": test_name, "vt_params": params}
return test_parameters

```

## From Parameters to Runnable: Integration Points

The output of `convert_parameters()` serves as the input for two critical integration points within Avocado-VT. The **VTResolverUtils** class in [[`avocado_vt/plugins/vt_resolver.py`](https://github.com/avocado-framework/avocado-vt/blob/main/avocado_vt/plugins/vt_resolver.py)](https://github.com/avocado-framework/avocado-vt/blob/master/avocado_vt/plugins/vt_resolver.py) converts these parameters into a `Runnable` object. Specifically, the `_parameters_to_runnable` method (lines 20-31) instantiates `avocado.core.nrunner.Runnable` with the kind `"avocado-vt"`, the URI from the `name` field, and the `vt_params` dictionary unpacked as keyword arguments.

Simultaneously, the **AVocadoVTLoader** in [[`avocado_vt/loader.py`](https://github.com/avocado-framework/avocado-vt/blob/main/avocado_vt/loader.py)](https://github.com/avocado-framework/avocado-vt/blob/master/avocado_vt/loader.py) utilizes the same conversion method when building test suites for the classic runner. At lines 94-96, the loader constructs tuples of `(VirtTest, self.convert_parameters(params))` to generate the final test suite list.

## Practical Implementation Example

The following example demonstrates the complete conversion flow using actual source patterns:

```python
from avocado_vt.discovery import DiscoveryMixIn
from avocado.core.settings import settings

# Initialize with Avocado configuration

config = settings.as_dict()
mixin = DiscoveryMixIn(config)

# Simulate Cartesian parser output

cartesian_dict = {
    "_short_name_map_file": {"subtests.cfg": "io.netperf.tcp_stream"},
    "netperf_client": "localhost",
    "netperf_server": "guest",
    "test_iterations": "5"
}

# Convert to Avocado-compatible parameters

result = mixin.convert_parameters(cartesian_dict)

print(result["name"])

# Output: io.netperf.tcp_stream

print(result["vt_params"]["id"])

# Output: io.netperf.tcp_stream

print(result["vt_params"]["netperf_client"])

# Output: localhost

```

When passed through the resolver, this becomes a executable Runnable:

```python
from avocado.core.nrunner import Runnable

runnable = Runnable(
    "avocado-vt",
    result["name"],
    **result["vt_params"]
)

# runnable.uri == "io.netperf.tcp_stream"

# runnable.kwargs contains the full VT configuration including 'id'

```

## Summary

- **DiscoveryMixIn** serves as the architectural boundary between Cartesian configuration matrices and Avocado's test execution API.
- The **test identifier resolution** follows a priority order: default [`subtests.cfg`](https://github.com/avocado-framework/avocado-vt/blob/main/subtests.cfg) entry, optional `shortname` override when `vt.short_names_when_config` is enabled, and special handling for the **spice** backend using [`tests-variants.cfg`](https://github.com/avocado-framework/avocado-vt/blob/main/tests-variants.cfg).
- The method enriches the original parameter dictionary by injecting the resolved identifier into the `id` key, then wraps it with the test name for URI generation.
- The output is consumed by both the **VTResolverUtils** (for nrunner compatibility) and the **AVocadoVTLoader** (for classic runner compatibility), demonstrating the mixin's central role in the discovery pipeline.

## Frequently Asked Questions

### What is the purpose of the `_short_name_map_file` key in Cartesian configs?

The `_short_name_map_file` key is a metadata dictionary injected by the Cartesian parser that maps configuration file names to their corresponding short test identifiers. `DiscoveryMixIn` uses this map to extract the default test name from the [`subtests.cfg`](https://github.com/avocado-framework/avocado-vt/blob/main/subtests.cfg) entry, providing a stable identifier derived from the configuration hierarchy rather than arbitrary parameter values.

### How does DiscoveryMixIn handle different backend types like spice?

The mixin implements backend-aware naming through a conditional check at lines 54-58. When `vt.type` is configured as `"spice"`, the method looks for an alternative key [`tests-variants.cfg`](https://github.com/avocado-framework/avocado-vt/blob/main/tests-variants.cfg) within the `_short_name_map_file` dictionary. This allows the spice backend to use its specific naming conventions while maintaining compatibility with the standard qemu backend resolution logic.

### What is the difference between the `name` and `vt_params` keys in the output dictionary?

The `name` key contains the resolved test identifier as a string, which serves as the URI for the Avocado runner to locate and execute the test. The `vt_params` key contains the complete, enriched Cartesian dictionary including all original parameters plus the injected `id` field. This separation allows the runner to use the URI for scheduling while passing the full configuration context to the test instance.

### Which Avocado-VT components consume the output of `convert_parameters`?

The output is consumed by two primary components: **VTResolverUtils** in [`plugins/vt_resolver.py`](https://github.com/avocado-framework/avocado-vt/blob/main/plugins/vt_resolver.py) converts the dictionary into a `Runnable` object for the Avocado nrunner architecture, and **AVocadoVTLoader** in [`loader.py`](https://github.com/avocado-framework/avocado-vt/blob/main/loader.py) uses it to build test suite tuples for the classic runner. Both components rely on the standardized output format to bridge Cartesian configuration with Avocado's execution models.