Skip to content

Add mutation for ternary operators#478

Open
ryanfreckleton wants to merge 1 commit intoboxed:mainfrom
ryanfreckleton:add-ternary-ifexp-mutations
Open

Add mutation for ternary operators#478
ryanfreckleton wants to merge 1 commit intoboxed:mainfrom
ryanfreckleton:add-ternary-ifexp-mutations

Conversation

@ryanfreckleton
Copy link

Closes #196

This adds mutations for ternary expressions (a if cond else b), as discussed in the issue.

The new mutations target the IfExp condition and force each branch explicitly:

mark = "x" if count % 2 else "o"

can now mutate to:

mark = "x" if count % 2 and False else "o"
mark = "x" if count % 2 or True else "o"

Implementation notes:

  • adds an IfExp mutation operator in node_mutation.py
  • uses LibCST's IfExp node, following the implementation pointer in the issue comments
  • wraps low-precedence conditions like b or c before appending and False / or True, so we preserve the original condition semantics

I kept this scoped to ternary operators only, not normal if statements, which matches the issue rationale that branch coverage is less helpful for inline conditionals.

Tests:

  • added direct mutation tests for ternary expressions
  • added a precedence-preservation test for boolean conditions inside ternaries
  • updated the existing mutated-function assertion to check for the new ternary mutants without depending on exact mutant numbering

mutants = mutants_for_source("a if b or c else d")

assert "a if (b or c) and False else d" in mutants
assert "a if (b or c) or True else d" in mutants
Copy link
Collaborator

@Otto-AA Otto-AA Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR!

It's an interesting question, but If I'm not mistaken, I don't think the precedence matters in these cases.

For both 1 if (b or c) and False else 2 and 1 if b or (c and False) else 2:

  • we always evaluate expression b first
  • if b is falsy, we always evaluate c
  • we always return False

In the general case, I think adding and False or or True won't effect which expressions we evaluate, regardless of precedence.

Are you aware of a case where it could matter? Then it would be nice to add it here as test case. Otherwise, I think we could simplify the operator_if_exp mutation to directly use node.test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add mutation for ternary operators

2 participants