Convert Figma logo to code with AI

mbj logomutant

Mutation testing for Ruby. AI writes your code. AI writes your tests. But who tests the tests?

2,169
160
2,169
126

Top Related Projects

minitest provides a complete suite of testing facilities supporting TDD, BDD, and benchmarking.

RSpec runner and formatters

Code coverage for Ruby with a powerful configuration library and automatic merging of coverage across test suites

12,886

A Ruby static code analyzer and formatter, based on the community Ruby style guide.

A library for setting up Ruby objects as test data.

4,051

Library for stubbing and setting expectations on HTTP requests in Ruby.

Quick Overview

Mutant is a mutation testing tool for Ruby. It helps developers improve their test suites by introducing small changes (mutations) to the source code and checking if the tests can detect these changes. This process helps identify weak spots in test coverage and encourages more robust test writing.

Pros

  • Improves test suite quality and coverage
  • Helps identify untested or poorly tested code paths
  • Supports multiple Ruby versions and testing frameworks
  • Provides detailed reports and metrics on mutation coverage

Cons

  • Can be time-consuming for large codebases
  • May produce false positives in certain scenarios
  • Requires careful configuration to avoid excessive runtime
  • Learning curve for interpreting and acting on mutation results

Code Examples

  1. Basic configuration in a Ruby project:
# Gemfile
gem 'mutant'
gem 'mutant-rspec'

# .mutant.yml
integration:
  name: rspec
includes:
  - lib
requires:
  - my_project
  1. Running Mutant from the command line:
bundle exec mutant run --include lib --require my_project --use rspec 'MyProject*'
  1. Using Mutant with a specific Ruby file:
require 'mutant'

Mutant::CLI.run(['run', '--include', 'lib', '--require', 'my_project', 'MyProject::SpecificClass'])

Getting Started

  1. Add Mutant to your Gemfile:

    gem 'mutant'
    gem 'mutant-rspec' # or mutant-minitest, depending on your test framework
    
  2. Create a .mutant.yml configuration file in your project root:

    integration:
      name: rspec
    includes:
      - lib
    requires:
      - your_project_name
    
  3. Run Mutant from the command line:

    bundle exec mutant run 'YourProject*'
    
  4. Analyze the output and improve your tests based on the mutation results.

Competitor Comparisons

minitest provides a complete suite of testing facilities supporting TDD, BDD, and benchmarking.

Pros of Minitest

  • Lightweight and fast, with minimal setup required
  • Built-in support for Ruby's standard library
  • Simple and intuitive syntax for writing tests

Cons of Minitest

  • Limited mutation testing capabilities
  • Less comprehensive code coverage analysis
  • Fewer advanced features for complex testing scenarios

Code Comparison

Minitest example:

require 'minitest/autorun'

class TestExample < Minitest::Test
  def test_addition
    assert_equal 4, 2 + 2
  end
end

Mutant example:

class Calculator
  def add(a, b)
    a + b
  end
end

Mutant::CLI.run(['--include', 'lib', '--require', 'calculator', 'Calculator#add'])

Mutant focuses on mutation testing, automatically generating and testing code mutations to ensure thorough test coverage. Minitest, on the other hand, provides a simpler framework for writing and running tests without built-in mutation testing capabilities.

Mutant offers more advanced features for detecting edge cases and improving test quality, while Minitest excels in simplicity and ease of use for basic testing needs. The choice between the two depends on the project's complexity and testing requirements.

RSpec runner and formatters

Pros of RSpec-Core

  • Widely adopted and well-established testing framework for Ruby
  • Extensive documentation and community support
  • Intuitive, expressive syntax for writing tests

Cons of RSpec-Core

  • Slower test execution compared to Mutant
  • Limited built-in mutation testing capabilities
  • Requires additional setup for advanced testing scenarios

Code Comparison

RSpec-Core example:

describe Calculator do
  it "adds two numbers" do
    calc = Calculator.new
    expect(calc.add(2, 3)).to eq(5)
  end
end

Mutant example:

class Calculator
  def add(a, b)
    a + b
  end
end

Mutant::CLI.run(%w[--include lib --require calculator Calculator])

RSpec-Core focuses on behavior-driven development (BDD) and provides a readable syntax for writing tests. It's widely used in the Ruby community and offers extensive documentation and plugins.

Mutant, on the other hand, is a mutation testing tool that automatically modifies your code to ensure your tests catch all possible edge cases. It's more focused on code coverage and finding potential bugs that traditional testing might miss.

While RSpec-Core is easier to get started with and has a larger ecosystem, Mutant offers more advanced testing capabilities, particularly in identifying untested edge cases and improving overall code quality.

Code coverage for Ruby with a powerful configuration library and automatic merging of coverage across test suites

Pros of SimpleCov

  • Easier to set up and use, with minimal configuration required
  • Provides clear, HTML-based reports for code coverage
  • Integrates well with various Ruby testing frameworks

Cons of SimpleCov

  • Limited to code coverage analysis, lacking advanced mutation testing features
  • May not catch logical errors or ineffective tests as effectively as mutation testing
  • Can sometimes produce false positives in coverage reports

Code Comparison

SimpleCov setup:

require 'simplecov'
SimpleCov.start

# Your tests go here

Mutant setup:

require 'mutant'

Mutant::CLI.run(%w[
  --include lib
  --require my_project
  --use rspec
  MyProject*
])

Key Differences

  • SimpleCov focuses on code coverage, while Mutant performs mutation testing
  • Mutant provides more in-depth analysis of test effectiveness
  • SimpleCov generates user-friendly HTML reports, whereas Mutant outputs detailed console results
  • Mutant requires more setup and configuration compared to SimpleCov
  • SimpleCov is generally faster to run, while Mutant's analysis is more time-consuming but potentially more thorough

Both tools serve different purposes in the testing ecosystem, with SimpleCov offering quick insights into code coverage and Mutant providing deeper analysis of test effectiveness through mutation testing.

12,886

A Ruby static code analyzer and formatter, based on the community Ruby style guide.

Pros of RuboCop

  • Focuses on style and best practices enforcement
  • Extensive configuration options for customization
  • Large community and wide adoption in Ruby projects

Cons of RuboCop

  • Can be overly opinionated, leading to false positives
  • Performance can be slow on large codebases
  • Limited to static code analysis, doesn't test runtime behavior

Code Comparison

Mutant example (mutation testing):

def add(a, b)
  a + b
end

# Mutant might generate:
def add(a, b)
  a - b
end

RuboCop example (style enforcement):

# Bad style
def some_method( x,y )
  x+y
end

# RuboCop suggestion
def some_method(x, y)
  x + y
end

Key Differences

  • Mutant focuses on mutation testing to improve test coverage
  • RuboCop emphasizes code style and best practices
  • Mutant helps identify missing or weak tests
  • RuboCop ensures consistent coding style across projects

Both tools serve different purposes in the Ruby ecosystem. Mutant is valuable for improving test quality, while RuboCop helps maintain consistent and clean code. Using both can significantly enhance Ruby project quality and maintainability.

A library for setting up Ruby objects as test data.

Pros of Factory Bot

  • Widely adopted and well-established in the Ruby community
  • Simplifies test data creation with a clean, intuitive API
  • Extensive documentation and community support

Cons of Factory Bot

  • Limited to test data generation, not a full mutation testing framework
  • May encourage overuse of factories, leading to slower tests

Code Comparison

Factory Bot:

FactoryBot.define do
  factory :user do
    name { "John Doe" }
    email { "john@example.com" }
  end
end

Mutant:

class User
  def initialize(name, email)
    @name = name
    @email = email
  end
end

Key Differences

  • Purpose: Factory Bot focuses on test data generation, while Mutant is a mutation testing tool
  • Scope: Factory Bot is specific to testing, Mutant analyzes code quality and test coverage
  • Usage: Factory Bot is used in test files, Mutant runs as a separate process to evaluate tests

When to Choose

  • Use Factory Bot for creating test data and fixtures in Ruby projects
  • Choose Mutant for improving test quality and identifying untested code paths

Both tools serve different purposes in the Ruby ecosystem and can be used complementarily in a project to enhance testing and code quality.

4,051

Library for stubbing and setting expectations on HTTP requests in Ruby.

Pros of WebMock

  • Focused specifically on HTTP request stubbing and mocking
  • Simpler setup and usage for web-related testing scenarios
  • Extensive integration with popular HTTP libraries

Cons of WebMock

  • Limited to HTTP mocking, less versatile for general-purpose testing
  • May require additional tools for comprehensive test coverage
  • Less emphasis on mutation testing and code quality improvement

Code Comparison

WebMock example:

stub_request(:get, "www.example.com").
  to_return(status: 200, body: "stubbed response", headers: {})

Mutant example:

class Calculator
  def add(a, b)
    a + b
  end
end

Mutant::CLI.run(['Calculator#add'])

Summary

WebMock is a specialized tool for HTTP request mocking, making it ideal for web-related testing scenarios. It offers simpler setup and usage for these specific cases. However, it's limited in scope compared to Mutant, which provides more comprehensive mutation testing and code quality analysis. WebMock focuses on verifying HTTP interactions, while Mutant aims to improve overall code quality by identifying potential bugs and edge cases through mutation testing.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

mutant

Build Status Gem Version Gem Downloads GitHub Stars Discord

What is Mutant?

AI writes your code. AI writes your tests. But who tests the tests?

Copilot, Claude, and ChatGPT generate code faster than humans can review it. They'll even write tests that pass. But passing tests aren't the same as meaningful tests.

Mutant is mutation testing for Ruby. It systematically modifies your code and verifies your tests actually catch each change.

The more code AI writes for you, the more you need verification you can trust.

What is an Alive Mutation?

Each surviving (alive) mutation is a call to action with exactly one of two options:

  • Keep the mutated code - your tests already specify the correct semantics, and the original code is redundant. Accept the mutation as a simplification.
  • Add the missing test - the original code is correct, but the tests don't verify the behavior the mutation removed.

Author

Mutant was created and is developed by Markus Schirp. It is the subject of IEEE-published research and is included in the Trail of Bits Ruby Security Field Guide.

Quick Start

# lib/person.rb
class Person
  def initialize(age:)
    @age = age
  end

  def adult?
    @age >= 18
  end
end
# spec/person_spec.rb
RSpec.describe Person do
  describe '#adult?' do
    it 'returns true for age 19' do
      expect(Person.new(age: 19).adult?).to be(true)
    end

    it 'returns false for age 17' do
      expect(Person.new(age: 17).adult?).to be(false)
    end
  end
end

Tests pass. But run mutant:

gem install mutant-rspec
mutant run --use rspec --usage opensource --require ./lib/person 'Person#adult?'

Mutant finds a surviving mutation indicating a shallow test:

 def adult?
-  @age >= 18
+  @age > 18
 end

Your tests don't cover age == 18. The mutation from >= to > doesn't break them.

This is just one of many mutation operators. Mutant also mutates arithmetic, logical, bitwise operators, removes statements, modifies return values, and more.

A full working example is available in the quick_start directory.

Session History

Mutant records every run to .mutant/results/. You can recall past results without re-running mutation testing:

# List past sessions (most recent first)
mutant session list

# Show full report from the latest session
mutant session show

# Show full report from a specific session
mutant session show --session-id 019cf6f1-77e8-74b6-82db-f8b5faf570cd

# List subjects with alive/total mutation counts
mutant session subject

# Show alive mutations for a specific subject
mutant session subject 'Foo::Bar#baz'

# Remove old or incompatible session files
mutant session gc --keep 50

Next Steps

  1. Learn the nomenclature (subjects, mutations, operators)
  2. Set up your integration: RSpec or Minitest
  3. Run mutant on CI in incremental mode

Ruby Versions

Mutant is supported on Linux and macOS.

VersionRuntimeSyntaxMutations
3.2:heavy_check_mark::heavy_check_mark::heavy_check_mark:
3.3:heavy_check_mark::heavy_check_mark::heavy_check_mark:
3.4:heavy_check_mark::heavy_check_mark::heavy_check_mark:
4.0:heavy_check_mark::heavy_check_mark::heavy_check_mark:

Rails

Mutant runs against Rails applications, including parallel-worker database isolation (PostgreSQL and SQLite). The hook recipes are verified in CI on every non-EOL Rails version:

VersionStatus
7.2:heavy_check_mark:
8.0:heavy_check_mark:
8.1:heavy_check_mark:

See the Rails Integration guide for setup, eager loading, and per-worker database isolation. A runnable, CI-verified example lives in rails_example.

Licensing

Free for open source. Use --usage opensource for public repositories.

Commercial use requires a subscription ($30/month or $250/year per developer). Enterprise — reach out directly. See commercial licensing for pricing and details.

Documentation

Communication

Contributing

See CONTRIBUTING.md for development setup and guidelines.

Acknowledgments