apache/beam · error · TypeError

tests attribute must be a list of test specifications.

Error message

tests attribute must be a list of test specifications.

What it means

run_tests reads the 'tests' attribute from the pipeline spec (or test suite file) and requires it to be a list of test specifications. If 'tests' exists but is not a list (e.g. a string or mapping), a TypeError is raised explaining the required shape.

Source

Thrown at sdks/python/apache_beam/yaml/main.py:183

  pipeline_spec = yaml.load(pipeline_yaml, Loader=yaml_transform.SafeLineLoader)
  options = _build_pipeline_options(pipeline_spec, pipeline_args)

  if known_args.create_test and known_args.fix_tests:
    raise ValueError(
        'At most one of --create_test and --fix_tests may be specified.')
  elif known_args.create_test:
    result = unittest.TestResult()
    tests = []
  else:
    if known_args.test_suite:
      with open(known_args.test_suite) as fin:
        test_suite_holder = yaml.load(
            fin, Loader=yaml_transform.SafeLineLoader) or {}
    else:
      test_suite_holder = pipeline_spec
    test_specs = test_suite_holder.get('tests', [])
    if not isinstance(test_specs, list):
      raise TypeError('tests attribute must be a list of test specifications.')
    elif not test_specs:
      raise RuntimeError(
          'No tests found. '
          "If you haven't added a set of tests yet, you can get started by "
          'running your pipeline with the --create_test flag enabled.')

    tests = [
        yaml_testing.YamlTestCase(
            pipeline_spec, test_spec, options, known_args.fix_tests)
        for test_spec in test_specs
    ]
    suite = unittest.TestSuite(tests)
    result = unittest.TextTestRunner().run(suite)

  if known_args.fix_tests or known_args.create_test:
    update_tests(known_args, pipeline_yaml, pipeline_spec, options, tests)

  if exit:

View on GitHub (pinned to 12126d8942)

Solutions

  1. Format 'tests' as a YAML list: each test specification on its own '- ' entry.
  2. If there is only one test, still wrap it in a one-element list: tests: - name: ... ...
  3. Validate the YAML loads as expected (yaml.safe_load) and that type(spec['tests']) is list before running.
  4. Catch the TypeError in tooling and point the author at the offending file/line in their test suite.

Example fix

# before
tests:
  name: my_test
# after
tests:
  - name: my_test
    pipeline: ...
    expected: [...]
Defensive patterns

Strategy: validation

Validate before calling

import yaml
spec = yaml.safe_load(open(suite_file))
tests = spec.get('tests', []) if isinstance(spec, dict) else []
assert isinstance(tests, list), f'tests must be a list, got {type(tests).__name__}'

Type guard

def is_valid_test_suite(spec):
    tests = spec.get('tests', []) if isinstance(spec, dict) else []
    return isinstance(tests, list) and all(isinstance(t, dict) for t in tests)

Try / catch

try:
    apache_beam.yaml.main.run(argv)
except TypeError as e:
    if 'tests attribute must be a list' in str(e):
        log.error('Fix tests: block in %s — each spec needs a leading dash', suite_file)
    raise

Prevention

When it happens

Trigger: Running with --test_suite (or a pipeline spec) whose top-level 'tests:' value is a scalar or dict rather than a YAML list, e.g. `tests: mytest` instead of `tests: [ ... ]`.

Common situations: Hand-edited YAML test suites where the list syntax was lost (missing dashes); wrapping a single test object directly under tests instead of a one-element list; YAML indentation mistakes collapsing a list into a string.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/d19629003f9f1a6b. Report an issue: GitHub.