Skip to content

Missing branch coverage with multiline case statement in Python 3.14 #2070

@burritoatspoton

Description

@burritoatspoton

Describe the bug
When using multiline case statements in match..case (e.g. with a long list of variants) coveragepy reports incomplete branch coverage (missing jump from a long case statement to the following one, to be exact). I haven't managed to reproduce the issue using Python versions other than 3.14.

To Reproduce
Installed Python: 3.14.0
Installed coverage: 7.11.0

.coveragerc

[run]
branch = true
[report]
show_missing = true

match.py

def foo(x: int) -> int:
    match x:
        case (
            1
            | 2
        ):
            return 1
        case _:
            return 0


print(foo(1))
print(foo(2))
print(foo(3))

Output of coverage erase && coverage run match.py && coverage report:

1
1
0
Name       Stmts   Miss Branch BrPart  Cover   Missing
------------------------------------------------------
match.py       9      0      2      1    91%   3->8
------------------------------------------------------
TOTAL          9      0      2      1    91%

Same output after we collapse the long case statement to a single line (case 1 | 2:):

1
1
0
Name       Stmts   Miss Branch BrPart  Cover   Missing
------------------------------------------------------
match.py       9      0      2      0   100%
------------------------------------------------------
TOTAL          9      0      2      0   100%

Answer the questions below:

  1. What version of Python are you using? 3.14.0

  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.

    coverage debug sys
    -- sys -------------------------------------------------------
                   coverage_version: 7.11.0
                    coverage_module: /Users/burrito/coverage-report/.venv/lib/python3.14/site-packages/coverage/__init__.py
                               core: -none-
                            CTracer: available from /Users/burrito/coverage-report/.venv/lib/python3.14/site-packages/coverage/tracer.cpython-314-darwin.so
               plugins.file_tracers: -none-
                plugins.configurers: -none-
          plugins.context_switchers: -none-
                  configs_attempted: /Users/burrito/coverage-report/.coveragerc
                       configs_read: /Users/burrito/coverage-report/.coveragerc
                        config_file: /Users/burrito/coverage-report/.coveragerc
                    config_contents: b'[run]\nbranch = true\n\n[report]\nshow_missing = true\n'
                          data_file: -none-
                             python: 3.14.0 (main, Oct 10 2025, 12:54:13) [Clang 20.1.4 ]
                           platform: macOS-15.7.1-arm64-arm-64bit-Mach-O
                     implementation: CPython
                              build: main
                                     Oct 10 2025 12:54:13
                        gil_enabled: True
                         executable: /Users/burrito/coverage-report/.venv/bin/python
                       def_encoding: utf-8
                        fs_encoding: utf-8
                                pid: 36117
                                cwd: /Users/burrito/coverage-report
                               path: /Users/burrito/coverage-report/.venv/bin
                                     /Users/burrito/.local/share/uv/python/cpython-3.14.0-macos-aarch64-none/lib/python314.zip
                                     /Users/burrito/.local/share/uv/python/cpython-3.14.0-macos-aarch64-none/lib/python3.14
                                     /Users/burrito/.local/share/uv/python/cpython-3.14.0-macos-aarch64-none/lib/python3.14/lib-dynload
                                     /Users/burrito/coverage-report/.venv/lib/python3.14/site-packages
                        environment: HOME = /Users/burrito
                       command_line: /Users/burrito/coverage-report/.venv/bin/coverage debug sys
             sqlite3_sqlite_version: 3.50.4
                 sqlite3_temp_store: 0
            sqlite3_compile_options: ATOMIC_INTRINSICS=1, COMPILER=clang-20.1.4, DEFAULT_AUTOVACUUM,
                                     DEFAULT_CACHE_SIZE=-2000, DEFAULT_FILE_FORMAT=4,
                                     DEFAULT_JOURNAL_SIZE_LIMIT=-1, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                     DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                     DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
                                     DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=2,
                                     DEFAULT_WORKER_THREADS=0, DIRECT_OVERFLOW_READ, ENABLE_DBSTAT_VTAB,
                                     ENABLE_FTS3, ENABLE_FTS3_PARENTHESIS, ENABLE_FTS4, ENABLE_FTS5,
                                     ENABLE_GEOPOLY, ENABLE_MATH_FUNCTIONS, ENABLE_RTREE,
                                     MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                     MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
                                     MAX_FUNCTION_ARG=1000, MAX_LENGTH=1000000000,
                                     MAX_LIKE_PATTERN_LENGTH=50000, MAX_MMAP_SIZE=0x7fff0000,
                                     MAX_PAGE_COUNT=0xfffffffe, MAX_PAGE_SIZE=65536, MAX_SQL_LENGTH=1000000000,
                                     MAX_TRIGGER_DEPTH=1000, MAX_VARIABLE_NUMBER=32766, MAX_VDBE_OP=250000000,
                                     MAX_WORKER_THREADS=8, MUTEX_PTHREADS, SYSTEM_MALLOC, TEMP_STORE=1,
                                     THREADSAFE=1
    
  3. What versions of what packages do you have installed? The output of pip freeze is helpful.

    uv pip freeze
    coverage==7.11.0
    
  4. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix.

    I don't have such commit at hand, only the minimal example posted above.

  5. What commands should we run to reproduce the problem? Be specific. Include everything, even git clone, pip install, and so on. Explain like we're five!

    I've ran the example in a uv-managed venv.

    pyproject.toml

    [project]
    name = "coverage-bug-report"
    requires-python = ">=3.14"
    version = "0.0.0"
    dependencies = [
        "coverage==7.11.0",
    ]

    Then installed coverage and activated the venv:

    uv sync
    source .venv/bin/activate

    Then proceeded with the example as described above.

Expected behavior
coverage report should show complete branch coverage regardless of the formatting.

Additional context
N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions