Skip to content

Type hints/checking to reduce mutants #467

@Otto-AA

Description

@Otto-AA

This issue is here to collect ideas, how mutmut could use type hints to prevent mutants that a type checker would catch.

For instance:

def foo():
    x: int = 1
# should not be mutated to
def foo():
    x: int = None

1. Using type hints while generating mutants

For simple cases like above, we could check the variable type hint, and if it's a basic type like str, int, ... then only allow these types. For more complex cases, I think we would need to use some type checker with an API and use it to understand which mutations are valid or not. I think this would get complex quickly and also the type checker we use would need to be compatible with the type checker of the user (as types are not 100% standardized).

2. Generating mutants, then filtering out with type checker

I wonder if for (2), we could simply run a type checker and ignore mutants where the mutated method has a type error:

  1. Generate mutants
  2. Run type checker
  3. Go through all lines with a type error
  4. If the line is a mutated method, disable this mutant
  5. For all remaining mutations, run pytest

The question I have here, is if we can ensure that mutations will only cause type errors in their own function. Could be possible, but not 100% sure.

At least our current implementation breaks it with pyright (see https://github.com/microsoft/pyright/blob/main/docs/type-inference.md#multi-assignment-type-inference):

class Foo:
    def xǁFoo_foo__mutmut_orig(self):
        self.x = 'foo'

    def xǁFoo_foo__mutmut_1(self):
        self.x = None # mutated code

Originally, Foo().x is inferred to be of type str. With the mutated method in the same class, pyright will infer Foo().x to be the union str | None. This wlil break users of instance variables.

I think approach (2) is worth a try. If someone wants to work on it, let me know and I can give some pointers. Maybe I'll also start it when I have some free time :)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions