mutant-minitest =============== Before starting with mutant its recommended to understand the [nomenclature](/docs/nomenclature.md). ## Setup To add mutant to your minitest code base you need to: 1. Add `mutant-minitest` as development dependency to your `Gemfile` or `.gemspec` This may look like: ```ruby # A gemfile gem 'mutant-minitest' ``` 2. Add `require 'mutant/minitest/coverage'` to your test environment (example to your `test/test_helper.rb`) Example: ```ruby require 'minitest/autorun' require 'mutant/minitest/coverage' class YourTestBaseClass < MiniTest::Test # ... ``` 3. Add `.cover` call sides to your test suite to mark them as eligible for killing mutations in subjects. Example: ```ruby class YourLibrarySomeClassTest < YourTestBaseClass cover 'YourLibrary::SomeClass*' # tells mutant which subjects this tests should cover # ... ``` 4. Run mutant against the minitest integration ```sh bundle exec mutant --include lib --require 'your_library.rb' --use minitest -- 'YourLibrary*' ``` ## Run through example This uses [mbj/auom](https://github.com/mbj/auom) a small library that has 100% mutation coverage. Its tests execute very fast and do not have any IO so its a good playground example to interact with. All the setup described above is already done. ```sh git clone https://github.com/mbj/auom bundle install # gemfile references mutant-minitest already bundle exec mutant --include lib --require auom --use minitest -- 'AUOM*' ``` This prints a report like: ```sh Mutant configuration: Matcher: # Integration: Mutant::Integration::Minitest Jobs: 8 Includes: ["lib"] Requires: ["auom"] Subjects: 23 Mutations: 1003 Results: 1003 Kills: 1003 Alive: 0 Runtime: 9.68s Killtime: 3.80s Overhead: 154.30% Mutations/s: 103.67 Coverage: 100.00% ``` Now lets try adding some redundant (or unspecified) code: ```sh patch -p1 <<'PATCH' --- a/lib/auom/unit.rb +++ b/lib/auom/unit.rb @@ -170,7 +170,7 @@ module AUOM # TODO: Move defaults coercions etc to .build method # def self.new(scalar, numerators = nil, denominators = nil) - scalar = rational(scalar) + scalar = rational(scalar) if true scalar, numerators = resolve([*numerators], scalar, :*) scalar, denominators = resolve([*denominators], scalar, :/) PATCH ``` Running mutant again prints the following: ``` AUOM::Unit.new:/home/mrh-dev/auom/lib/auom/unit.rb:172 - minitest:AUOMTest::ClassMethods::New#test_reduced_unit - minitest:AUOMTest::ClassMethods::New#test_normalized_denominator_scalar - minitest:AUOMTest::ClassMethods::New#test_normalized_numerator_unit - minitest:AUOMTest::ClassMethods::New#test_incompatible_scalar - minitest:AUOMTest::ClassMethods::New#test_integer - minitest:AUOMTest::ClassMethods::New#test_sorted_numerator - minitest:AUOMTest::ClassMethods::New#test_unknown_unit - minitest:AUOMTest::ClassMethods::New#test_rational - minitest:AUOMTest::ClassMethods::New#test_normalized_numerator_scalar - minitest:AUOMTest::ClassMethods::New#test_sorted_denominator - minitest:AUOMTest::ClassMethods::New#test_normalized_denominator_unit evil:AUOM::Unit.new:/home/mrh-dev/auom/lib/auom/unit.rb:172:cd9ee @@ -1,9 +1,7 @@ def self.new(scalar, numerators = nil, denominators = nil) - if true - scalar = rational(scalar) - end + scalar = rational(scalar) scalar, numerators = resolve([*numerators], scalar, :*) scalar, denominators = resolve([*denominators], scalar, :/) super(scalar, *[numerators, denominators].map(&:sort)).freeze end ----------------------- Mutant configuration: Matcher: # Integration: Mutant::Integration::Minitest Jobs: 8 Includes: ["lib"] Requires: ["auom"] Subjects: 23 Mutations: 1009 Results: 1009 Kills: 1008 Alive: 1 Runtime: 9.38s Killtime: 3.47s Overhead: 170.06% Mutations/s: 107.60 Coverage: 99.90% ``` This shows mutant detected the redundant alive conditional. Feel free to also remove some tests. Or do other modifications to either tests or code.