COLLECTION_SEMANTICS_WORKFLOW_RUNTIME_NEW_TESTS_PLAN

Implementation Plan: test_workflow_collection_semantics.py

Context

We’re building a dedicated API test file for collection semantics workflow runtime tests. The existing tests in test_workflows.py test collection behavior incidentally; these new tests are minimal, purpose-built, and explicitly annotated with which collection_semantics.yml label they verify. Full design in WORKFLOW_RUNTIME_NEW_TESTS.md.

Step 1: Create test file with scaffold

File: lib/galaxy_test/api/test_workflow_collection_semantics.py

Base class import from same file: from galaxy_test.api.test_workflows import BaseWorkflowsApiTestCase

Key imports:

import pytest
from galaxy_test.api.test_workflows import BaseWorkflowsApiTestCase
from galaxy_test.base.populators import skip_without_tool

Step 2: Phase 1 tests — basic mapping (6 tests)

All use cat tool (always available, no @skip_without_tool needed).

#TestInputPatternAssert
1test_basic_mapping_pairedpairedA (inline YAML)paired, 2 elements
2test_basic_mapping_paired_or_unpaired_pairedpaired_or_unpaired (paired data)B (create_paired_or_unpaired_pair_in_history)paired_or_unpaired, 2 elements
3test_basic_mapping_paired_or_unpaired_unpairedpaired_or_unpaired (unpaired data)B (create_unpaired_in_history)paired_or_unpaired, 1 element
4test_basic_mapping_list_paired_or_unpairedlist:paired_or_unpairedB (create_list_of_paired_and_unpaired_in_history)list:paired_or_unpaired
5test_basic_mapping_including_single_datasetlist + single datasetA (inline YAML)list, 2 elements
6test_basic_mapping_two_inputs_identical_structuretwo lists, same identifiersA (inline YAML)list, 2 elements

Tests 1, 5, 6 use _run_workflow() with inline test_data. Tests 2, 3, 4 create collections via populator, upload workflow, invoke with explicit inputs.

Step 3: Phase 2 tests — reduction (4 tests)

#TestToolInputPatternAssert
7test_collection_input_listcat_collectionlistAsingle dataset output
8test_collection_input_paired_or_unpairedcollection_paired_or_unpairedpaired_or_unpairedBsingle dataset output
9test_collection_input_list_paired_or_unpairedcollection_list_paired_or_unpairedlist:paired_or_unpairedBsingle dataset output
10test_list_reductionmulti_data_optionallistAsingle dataset output

All need @skip_without_tool.

Step 4: Phase 3 tests — subtyping (4 tests)

#TestInput type → Tool acceptsPatternAssert
11test_paired_or_unpaired_consumes_pairedpairedpaired_or_unpairedB (create_pair)single dataset
12test_mapping_list_paired_over_paired_or_unpairedlist:pairedpaired_or_unpairedB (create_list_of_pairs)list
13test_mapping_list_list_paired_over_paired_or_unpairedlist:list:pairedpaired_or_unpairedB (create_nested)list:list
14test_mapping_list_over_paired_or_unpairedlist:paired_or_unpairedpaired_or_unpairedB (create_list_of_paired_and_unpaired)list

All need @skip_without_tool("collection_paired_or_unpaired").

Step 5: Wire into spec YAML

Add workflow_runtime: api_test: entries to collection_semantics.yml for each test. This is a YAML-only change.

Pattern B detail

For tests that can’t use inline test_data YAML (paired_or_unpaired types):

with self.dataset_populator.test_history() as history_id:
    # 1. Create collection
    hdca = self.dataset_collection_populator.create_paired_or_unpaired_pair_in_history(
        history_id, wait=True
    ).json()["outputs"][0]
    # 2. Upload workflow
    workflow_id = self.workflow_populator.upload_yaml_workflow(WORKFLOW_YAML)
    # 3. Invoke with inputs dict
    invocation = self.workflow_populator.invoke_workflow_and_wait(
        workflow_id, history_id=history_id,
        inputs={"0": {"src": "hdca", "id": hdca["id"]}},
    )
    # 4. Assert

Input key "0" = step index 0 (the workflow input). Alternative: use inputs_by="name" with input label.

Critical files

FileAction
lib/galaxy_test/api/test_workflow_collection_semantics.pyCreate
lib/galaxy/model/dataset_collections/types/collection_semantics.ymlEdit (add workflow_runtime refs)
lib/galaxy_test/api/test_workflows.py:178Read-only (BaseWorkflowsApiTestCase)
lib/galaxy_test/base/populators.py:3473-3502Read-only (paired_or_unpaired populator methods)

Verification

Use the galaxy-backend-tests skill (/galaxy-backend-tests) to run API tests — it handles server startup, environment, and teardown automatically.

# Run just the new tests
/galaxy-backend-tests api test_workflow_collection_semantics

# Run a single test
/galaxy-backend-tests api test_workflow_collection_semantics -k test_basic_mapping_paired

Unit tests (no server needed) can still be run directly:

PYTHONPATH=lib python -m pytest test/unit/data/model/test_collection_semantics.py -v

Reference

See COMPONENT_API_TESTS.md for general Galaxy API test patterns including assertion helpers (api_asserts.py), the *_raw populator pattern, and modern pytest-style alternatives.