diff --git a/Gemfile.devtools b/Gemfile.devtools index 9696b9fa..91c7518d 100644 --- a/Gemfile.devtools +++ b/Gemfile.devtools @@ -3,7 +3,7 @@ group :development do gem 'rake', '~> 10.0.4' gem 'rspec', '~> 2.13.0' - gem 'yard', '~> 0.8.5.2' + gem 'yard', '~> 0.8.6' end group :yard do @@ -13,7 +13,7 @@ end group :guard do gem 'guard', '~> 1.7.0' gem 'guard-bundler', '~> 1.0.0' - gem 'guard-rspec', '~> 2.5.2' + gem 'guard-rspec', '~> 2.5.3' # file system change event handling gem 'listen', '~> 0.7.3' @@ -29,12 +29,12 @@ end group :metrics do gem 'backports', '~> 3.3', '>= 3.3.0' - gem 'coveralls', '~> 0.6.4' - gem 'flay', '~> 2.1.0' + gem 'coveralls', '~> 0.6.5' + gem 'flay', '~> 2.2.0' gem 'flog', '~> 3.2.3' gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git' gem 'simplecov', '~> 0.7.1' - gem 'yardstick', '~> 0.9.5' + gem 'yardstick', '~> 0.9.6' gem 'yard-spellcheck', '~> 0.1.5' platforms :rbx do diff --git a/config/flay.yml b/config/flay.yml index 1fbb7d1a..e5817985 100644 --- a/config/flay.yml +++ b/config/flay.yml @@ -1,3 +1,3 @@ --- -threshold: 25 # Todo bring down to ~20 -total_score: 914 +threshold: 16 +total_score: 577 diff --git a/config/flog.yml b/config/flog.yml index 5704a723..0b91a104 100644 --- a/config/flog.yml +++ b/config/flog.yml @@ -1,2 +1,2 @@ --- -threshold: 44.0 +threshold: 37.6 diff --git a/config/reek.yml b/config/reek.yml new file mode 100644 index 00000000..66fc2169 --- /dev/null +++ b/config/reek.yml @@ -0,0 +1,196 @@ +--- +Attribute: + enabled: true + exclude: + - Mutant::CLI::Classifier + - Mutant::Context + - Mutant::Context::Scope + - Mutant::Killer + - Mutant::Killer::Forking + - Mutant::Matcher::Chain + - Mutant::Matcher::Method + - Mutant::Matcher::Methods + - Mutant::Matcher::Namespace + - Mutant::Mutation + - Mutant::Mutation::Filter::Code + - Mutant::Mutation::Filter::Whitelist + - Mutant::Mutator + - Mutant::Reporter + - Mutant::Reporter::CLI + - Mutant::Reporter::Stats + - Mutant::Reporter::Stats::Counter + - Mutant::Runner + - Mutant::Runner::Config + - Mutant::Runner::Mutation + - Mutant::Runner::Subject + - Mutant::Strategy + - Mutant::Strategy::Rspec::DM2::Lookup + - Mutant::Subject +BooleanParameter: + enabled: true + exclude: [] +ClassVariable: + enabled: true + exclude: [] +ControlParameter: + enabled: true + exclude: [] +DataClump: + enabled: true + exclude: [] + max_copies: 2 + min_clump_size: 2 +DuplicateMethodCall: + enabled: true + exclude: + - Mutant::CLI::Classifier::Method#method + - Mutant::Killer#run_with_benchmark + - Mutant::Mutator::Node::FormalArguments19::DefaultMutations#dispatch + - Mutant::Mutator::Node::FormalArguments19::RequireDefaults#dispatch + - Mutant::Mutator::Node::Literal::Hash#emit_element_presence + - Mutant::Mutator::Node::Send::WithArguments#emit_argument_mutations + - Mutant::Reporter::CLI#colorized_diff + - Mutant::Reporter::CLI#report_killer + - Mutant::Runner::Config#run + max_calls: 1 + allow_calls: [] +FeatureEnvy: + enabled: true + exclude: + - Mutant::Matcher::Method::Instance#match? + - Mutant::Matcher::Namespace#emit_scope_matches + - Mutant::Mutation::Evil#success? + - Mutant::Mutation::Neutral#success? + - Mutant::Mutator::Node::DefaultArguments#dispatch + - Mutant::Mutator::Node::FormalArguments19#emit_required_mutations + - Mutant::Mutator::Node::FormalArguments19::DefaultMutations#dispatch + - Mutant::Mutator::Node::FormalArguments19::RequireDefaults#dispatch + - Mutant::Mutator::Node::PatternArguments#allow? + - Mutant::Reporter::CLI#report_killer + - Mutant::Reporter::CLI#start +IrresponsibleModule: + enabled: true + exclude: + - Mutant::Matcher::Methods::Instance + - Mutant::Mutator::Node::Define + - Mutant::Mutator::Node::DefineSingleton + - Mutant::Strategy::Rspec::DM2::Lookup::Method + - Mutant::Strategy::Rspec::DM2::Lookup::Method::Instance + - Mutant::Strategy::Rspec::DM2::Lookup::Method::Singleton +LongParameterList: + enabled: true + exclude: + - Mutant::Mutator::Node#new_send_with_arguments + max_params: 2 + overrides: + initialize: + max_params: 3 +LongYieldList: + enabled: true + exclude: [] + max_params: 2 +NestedIterators: + enabled: true + exclude: + - Mutant#self.define_singleton_subclass + - Mutant::Mutator::Node::FormalArguments19::PatternArgumentExpansion#dispatch + - Mutant::Mutator::Node::FormalArguments19::RequireDefaults#dispatch + - Mutant::Mutator::Node::ReceiverCase#emit_when_branch_mutations + - Mutant::Mutator::Util::Array::Element#dispatch + max_allowed_nesting: 1 + ignore_iterators: [] +NilCheck: + enabled: true + exclude: + - Mutant::Matcher::Method#skip? +RepeatedConditional: + enabled: true + exclude: + - Mutant::Reporter::CLI + max_ifs: 1 +TooManyInstanceVariables: + enabled: true + exclude: + - Mutant::CLI + - Mutant::Killer + max_instance_variables: 3 +TooManyMethods: + enabled: true + exclude: + - Mutant::CLI + - Mutant::Matcher::Method + - Mutant::Reporter::CLI + max_methods: 10 +TooManyStatements: + enabled: true + exclude: + - Mutant#self.define_singleton_subclass + - Mutant::CLI#self.run + - Mutant::Differ#diff + - Mutant::Killer::Forked#run + - Mutant::Mutator::Node#emit_attribute_mutations + - Mutant::Mutator::Node::FormalArguments19::DefaultMutations#dispatch + - Mutant::Mutator::Node::FormalArguments19::PatternArgumentExpansion#dispatch + - Mutant::Mutator::Node::FormalArguments19::RequireDefaults#dispatch + - Mutant::Mutator::Node::If#dispatch + - Mutant::Reporter::CLI#colorized_diff + - Mutant::Reporter::CLI#report_killer + - Mutant::Reporter::CLI#start + - each + max_statements: 5 +UncommunicativeMethodName: + enabled: true + exclude: + - Mutant::Mutation#sha1 + reject: + - !ruby/regexp /^[a-z]$/ + - !ruby/regexp /[0-9]$/ + - !ruby/regexp /[A-Z]/ + accept: [] +UncommunicativeModuleName: + enabled: true + exclude: + - Mutant::Mutator::Node::FormalArguments19 + - Mutant::Mutator::Node::Iter19 + - Mutant::Strategy::Rspec::DM2 + reject: + - !ruby/regexp /^.$/ + - !ruby/regexp /[0-9]$/ + accept: [] +UncommunicativeParameterName: + enabled: true + exclude: [] + reject: + - !ruby/regexp /^.$/ + - !ruby/regexp /[0-9]$/ + - !ruby/regexp /[A-Z]/ + accept: [] +UncommunicativeVariableName: + enabled: true + exclude: [] + reject: + - !ruby/regexp /^.$/ + - !ruby/regexp /[0-9]$/ + - !ruby/regexp /[A-Z]/ + accept: [] +UnusedParameters: + enabled: true + exclude: + - Mutant::Mutation::Filter#match? + - Mutant::Mutation::Filter#self.handle + - Mutant::Mutator#allow? + - Mutant::Strategy::Rspec::Full#spec_files + - Mutant::Strategy::Rspec::Integration#spec_files + - Mutant::Strategy::Rspec::Unit#spec_files +UtilityFunction: + enabled: true + exclude: + - Mutant::Matcher::Namespace#emit_scope_matches + - Mutant::Mutation::Evil#success? + - Mutant::Mutation::Neutral#success? + - Mutant::Mutator::Node::PatternArguments#allow? + - Mutant::Strategy::Rspec::DM2#spec_files + - Mutant::Strategy::Rspec::Full#spec_files + - Mutant::Strategy::Rspec::Integration#spec_files + - Mutant::Strategy::Rspec::Unit#spec_files + max_helper_calls: 0 diff --git a/config/roodi.yml b/config/roodi.yml deleted file mode 100644 index 522e1fe3..00000000 --- a/config/roodi.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -AbcMetricMethodCheck: - score: 12.2 -AssignmentInConditionalCheck: {} -CaseMissingElseCheck: {} -ClassLineCountCheck: - line_count: 324 -ClassNameCheck: - pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ -ClassVariableCheck: {} -CyclomaticComplexityBlockCheck: - complexity: 2 -CyclomaticComplexityMethodCheck: - complexity: 4 -EmptyRescueBodyCheck: {} -ForLoopCheck: {} -MethodLineCountCheck: - line_count: 9 -MethodNameCheck: - pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/ -ModuleLineCountCheck: - line_count: 327 -ModuleNameCheck: - pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ -ParameterNumberCheck: - parameter_count: 3 diff --git a/config/site.reek b/config/site.reek deleted file mode 100644 index 2406b1c4..00000000 --- a/config/site.reek +++ /dev/null @@ -1,104 +0,0 @@ ---- -UncommunicativeParameterName: - accept: [] - exclude: [] - enabled: true - reject: - - !ruby/regexp /^.$/ - - !ruby/regexp /[0-9]$/ - - !ruby/regexp /[A-Z]/ -LargeClass: - max_methods: 10 - exclude: - - "Mutant::Reporter::CLI" # 16 methods TODO Reduce! - - "Mutant::Reporter::Stats" # 6 ivars TODO Reduce! - - "Mutant::CLI" # 19 methods and 7 ivars, TODO Reduce! - enabled: true - max_instance_variables: 3 -UncommunicativeMethodName: - accept: - - sha1 - exclude: [] - enabled: true - reject: - - !ruby/regexp /^[a-z]$/ - - !ruby/regexp /[0-9]$/ - - !ruby/regexp /[A-Z]/ -LongParameterList: - max_params: 2 - exclude: - - "Mutant::Mutator::Node#new_send_with_arguments" # 3 params - - "Mutant::Context::Constant#initialize" # 3 params - - "Mutant::Subject#initialize" # 3 params - enabled: true - overrides: {} -FeatureEnvy: - exclude: [] - enabled: true -ClassVariable: - exclude: [] - enabled: true -BooleanParameter: - exclude: [] - enabled: true -IrresponsibleModule: - exclude: [] - enabled: true -UncommunicativeModuleName: - accept: - - Mutant::Mutator::Node::Iter19 - - Mutant::Strategy::Rspec::DM2 - exclude: [] - enabled: true - reject: - - !ruby/regexp /^.$/ - - !ruby/regexp /[0-9]$/ -NestedIterators: - ignore_iterators: [] - exclude: - - Mutant#self.define_singleton_subclass - - Mutant::Mutator::Util::Array::Element#dispatch - - Mutant::Mutator::Node::ReceiverCase#emit_when_branch_mutation - enabled: true - max_allowed_nesting: 1 -LongMethod: - max_statements: 6 - exclude: [] - enabled: true -Duplication: - allow_calls: [] - exclude: - - Mutant::Mutator::Node::Literal::Hash#emit_element_presence - enabled: true - max_calls: 1 -UtilityFunction: - max_helper_calls: 0 - exclude: [] - enabled: true -Attribute: - exclude: [] - enabled: false -UncommunicativeVariableName: - accept: [] - exclude: [] - enabled: true - reject: - - !ruby/regexp /^.$/ - - !ruby/regexp /[0-9]$/ - - !ruby/regexp /[A-Z]/ -SimulatedPolymorphism: - exclude: [] - enabled: true - max_ifs: 1 -DataClump: - exclude: [] - enabled: true - max_copies: 2 - min_clump_size: 2 -ControlCouple: - exclude: [] - enabled: true -LongYieldList: - max_params: 1 - exclude: [] - enabled: true diff --git a/lib/mutant/cli.rb b/lib/mutant/cli.rb index 4cd89880..2f27cfe2 100644 --- a/lib/mutant/cli.rb +++ b/lib/mutant/cli.rb @@ -157,7 +157,8 @@ module Mutant def dispatch_matcher argument = current_argument consume(1) - @matchers << Classifier.build(argument) + matcher = Classifier.build(argument) + @matchers << matcher if matcher end # Process option argument diff --git a/lib/mutant/killer/forked.rb b/lib/mutant/killer/forked.rb index fe839d04..4f790ddb 100644 --- a/lib/mutant/killer/forked.rb +++ b/lib/mutant/killer/forked.rb @@ -33,7 +33,7 @@ module Mutant fork do begin killer = @killer.new(strategy, mutation) - Kernel.exit(killer.fail? ? 1 : 0) + Kernel.exit(killer.success? ? 0 : 1) rescue Kernel.exit(1) end diff --git a/lib/mutant/killer/rspec.rb b/lib/mutant/killer/rspec.rb index efb05908..80c2c901 100644 --- a/lib/mutant/killer/rspec.rb +++ b/lib/mutant/killer/rspec.rb @@ -17,7 +17,10 @@ module Mutant # def run mutation.insert - !!::RSpec::Core::Runner.run(command_line_arguments, strategy.error_stream, strategy.output_stream).nonzero? + # TODO: replace with real streams from configuration + require 'stringio' + null = StringIO.new + !::RSpec::Core::Runner.run(command_line_arguments, null, null).zero? end # Return command line arguments diff --git a/lib/mutant/mutation.rb b/lib/mutant/mutation.rb index a3fa6b49..98e54ae4 100644 --- a/lib/mutant/mutation.rb +++ b/lib/mutant/mutation.rb @@ -97,7 +97,7 @@ module Mutant # @api private # def sha1 - Digest::SHA1.hexdigest(subject.identification + source) + Digest::SHA1.hexdigest(subject.identification + 0.chr + source) end memoize :sha1 diff --git a/lib/mutant/reporter/stats.rb b/lib/mutant/reporter/stats.rb index 73a6595b..7b0afc9f 100644 --- a/lib/mutant/reporter/stats.rb +++ b/lib/mutant/reporter/stats.rb @@ -8,6 +8,12 @@ module Mutant class Counter include Equalizer.new(:count, :fails) + # Return count + # + # @return [Fixnum] + # + # @api private + # attr_reader :count # Return fail count @@ -105,6 +111,8 @@ module Mutant # @return [false] # otherwise # + # @api private + # def success? @counts[:subject].nonzero? && !errors? end @@ -131,6 +139,8 @@ module Mutant # @return [false] # otherwise # + # @api private + # def errors? @killers.values.any? do |counter| counter.nonzero? diff --git a/lib/mutant/runner/subject.rb b/lib/mutant/runner/subject.rb index 1352f522..d6e40d37 100644 --- a/lib/mutant/runner/subject.rb +++ b/lib/mutant/runner/subject.rb @@ -68,7 +68,7 @@ module Mutant # @api private # def run - @mutations = subject.mutations.map do |mutation| + @mutations = subject.map do |mutation| Mutation.run(config, mutation) end end diff --git a/spec/unit/mutant/runner/subject/mutations_spec.rb b/spec/unit/mutant/runner/subject/mutations_spec.rb deleted file mode 100644 index d46b857f..00000000 --- a/spec/unit/mutant/runner/subject/mutations_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'spec_helper' - -describe Mutant::Runner::Subject, '#mutations' do - let(:object) { described_class.run(config, mutation_subject) } - - subject { object.mutations } - - let(:config) { mock('Config') } - let(:mutation) { mock('Mutation') } - let(:mutation_subject) { mock('Subject', :mutations => [mutation]) } - - class DummyRunner - include Concord.new(:config, :mutation) - def self.run(*args); new(*args); end - end - - before do - stub_const('Mutant::Runner::Mutation', DummyRunner) - end - - it { should eql([DummyRunner.new(config, mutation)]) } - - it_should_behave_like 'an idempotent method' -end diff --git a/spec/unit/mutant/runner/subject/success_predicate_spec.rb b/spec/unit/mutant/runner/subject/success_predicate_spec.rb index 05e14a4e..916a1ded 100644 --- a/spec/unit/mutant/runner/subject/success_predicate_spec.rb +++ b/spec/unit/mutant/runner/subject/success_predicate_spec.rb @@ -5,11 +5,11 @@ describe Mutant::Runner::Subject, '#success?' do let(:object) { described_class.run(config, mutation_subject) } - let(:mutation_subject) { mock('Subject', :mutations => mutations) } - let(:config) { mock('Config') } - let(:mutation_a) { mock('Mutation A', :fails? => false) } - let(:mutation_b) { mock('Mutation B', :fails? => false) } - let(:mutations) { [mutation_a, mutation_b] } + let(:mutation_subject) { mock('Subject', :map => mutations) } + let(:config) { mock('Config') } + let(:mutation_a) { mock('Mutation A', :failed? => false) } + let(:mutation_b) { mock('Mutation B', :failed? => false) } + let(:mutations) { [mutation_a, mutation_b] } class DummyMutationRunner include Concord.new(:config, :mutation) @@ -19,7 +19,7 @@ describe Mutant::Runner::Subject, '#success?' do end def failed? - @mutation.fails? + @mutation.failed? end end @@ -36,7 +36,7 @@ describe Mutant::Runner::Subject, '#success?' do context 'with failing evil mutations' do before do - mutation_a.stub(:fails? => true) + mutation_a.stub(:failed? => true) end it { should be(false) }