rubycritic 0.0.5 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/README.md +72 -11
- data/bin/rubycritic +2 -0
- data/lib/rubycritic/adapters/complexity/flog.rb +22 -0
- data/lib/rubycritic/adapters/smell/flay.rb +68 -0
- data/lib/rubycritic/adapters/smell/flog.rb +62 -0
- data/lib/rubycritic/adapters/smell/reek.rb +44 -0
- data/lib/rubycritic/analysers/churn.rb +19 -0
- data/lib/rubycritic/analysers/config.reek +8 -0
- data/lib/rubycritic/analysers/flay.rb +15 -0
- data/lib/rubycritic/analysers/flog.rb +1 -2
- data/lib/rubycritic/analysers/stats.rb +31 -0
- data/lib/rubycritic/analysers_runner.rb +15 -14
- data/lib/rubycritic/cli.rb +35 -14
- data/lib/rubycritic/configuration.rb +24 -0
- data/lib/rubycritic/core/analysed_file.rb +50 -0
- data/lib/rubycritic/{location.rb → core/location.rb} +6 -2
- data/lib/rubycritic/core/rating.rb +22 -0
- data/lib/rubycritic/{smell.rb → core/smell.rb} +5 -12
- data/lib/rubycritic/files_initializer.rb +15 -0
- data/lib/rubycritic/orchestrator.rb +23 -0
- data/lib/rubycritic/report_generators/assets/javascripts/application.js +87 -8
- data/lib/rubycritic/report_generators/assets/javascripts/highcharts.src-4.0.1.js +17672 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.floatThead-v1.2.7.js +754 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.scrollTo-1.4.11.js +186 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.tablesorter-2.0.js +1031 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
- data/lib/rubycritic/report_generators/assets/stylesheets/application.css +204 -1
- data/lib/rubycritic/report_generators/assets/stylesheets/prettify.custom_theme.css +1 -4
- data/lib/rubycritic/report_generators/base.rb +49 -0
- data/lib/rubycritic/report_generators/code_file.rb +38 -0
- data/lib/rubycritic/report_generators/code_index.rb +24 -0
- data/lib/rubycritic/report_generators/current_code_file.rb +17 -0
- data/lib/rubycritic/report_generators/line.rb +31 -0
- data/lib/rubycritic/report_generators/overview.rb +25 -0
- data/lib/rubycritic/report_generators/smells_index.rb +24 -0
- data/lib/rubycritic/report_generators/templates/code_file.html.erb +36 -0
- data/lib/rubycritic/report_generators/templates/code_index.html.erb +26 -0
- data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +27 -16
- data/lib/rubycritic/report_generators/templates/overview.html.erb +5 -0
- data/lib/rubycritic/report_generators/templates/smells_index.html.erb +20 -0
- data/lib/rubycritic/report_generators/view_helpers.rb +28 -9
- data/lib/rubycritic/reporters/base.rb +24 -0
- data/lib/rubycritic/reporters/main.rb +52 -0
- data/lib/rubycritic/reporters/mini.rb +30 -0
- data/lib/rubycritic/revision_comparator.rb +21 -28
- data/lib/rubycritic/serializer.rb +32 -0
- data/lib/rubycritic/smells_status_setter.rb +7 -16
- data/lib/rubycritic/source_control_systems/base.rb +60 -0
- data/lib/rubycritic/source_control_systems/double.rb +19 -0
- data/lib/rubycritic/source_control_systems/git.rb +47 -37
- data/lib/rubycritic/source_locator.rb +8 -12
- data/lib/rubycritic/turbulence.rb +17 -0
- data/lib/rubycritic/version.rb +1 -1
- data/lib/rubycritic.rb +2 -27
- data/rubycritic.gemspec +3 -0
- data/test/lib/rubycritic/adapters/complexity/flog_test.rb +18 -0
- data/test/lib/rubycritic/adapters/smell/flay_test.rb +34 -0
- data/test/lib/rubycritic/adapters/smell/flog_test.rb +26 -0
- data/test/lib/rubycritic/adapters/smell/reek_test.rb +35 -0
- data/test/lib/rubycritic/analysers/churn_test.rb +38 -0
- data/test/lib/rubycritic/configuration_test.rb +17 -0
- data/test/lib/rubycritic/core/analysed_file_test.rb +71 -0
- data/test/lib/rubycritic/{location_test.rb → core/location_test.rb} +8 -4
- data/test/lib/rubycritic/core/smell_test.rb +73 -0
- data/test/lib/rubycritic/{smells_array_test.rb → core/smells_array_test.rb} +1 -1
- data/test/lib/rubycritic/smells_status_setter_test.rb +5 -5
- data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +5 -11
- data/test/lib/rubycritic/source_locator_test.rb +26 -17
- data/test/lib/rubycritic/turbulence_test.rb +17 -0
- data/test/lib/rubycritic/version_test.rb +1 -0
- data/test/samples/flay/smelly.rb +17 -0
- data/test/samples/flog/complex.rb +11 -0
- data/test/samples/flog/smelly.rb +7 -2
- data/test/samples/reek/not_smelly.rb +31 -3
- data/test/test_helper.rb +1 -0
- metadata +97 -32
- data/SPEC.md +0 -58
- data/lib/rubycritic/report_generators/base_generator.rb +0 -42
- data/lib/rubycritic/report_generators/file_generator.rb +0 -42
- data/lib/rubycritic/report_generators/index_generator.rb +0 -28
- data/lib/rubycritic/report_generators/line_generator.rb +0 -27
- data/lib/rubycritic/report_generators/reporter.rb +0 -45
- data/lib/rubycritic/report_generators/templates/file.html.erb +0 -3
- data/lib/rubycritic/report_generators/templates/index.html.erb +0 -14
- data/lib/rubycritic/smell_adapters/flog.rb +0 -41
- data/lib/rubycritic/smell_adapters/reek.rb +0 -35
- data/lib/rubycritic/smells_aggregator.rb +0 -29
- data/lib/rubycritic/smelly_pathnames_serializer.rb +0 -34
- data/lib/rubycritic/source_control_systems/source_control_system.rb +0 -42
- data/test/lib/rubycritic/metric_adapters/flog_adapter_test.rb +0 -25
- data/test/lib/rubycritic/metric_adapters/reek_adapter_test.rb +0 -34
- data/test/lib/rubycritic/smell_test.rb +0 -71
- data/test/lib/rubycritic/smells_aggregator_test.rb +0 -47
- /data/lib/rubycritic/report_generators/assets/javascripts/{prettify.js → prettify-4-Mar-2013.js} +0 -0
data/lib/rubycritic.rb
CHANGED
|
@@ -1,27 +1,2 @@
|
|
|
1
|
-
require "rubycritic/
|
|
2
|
-
require "rubycritic/
|
|
3
|
-
require "rubycritic/smells_aggregator"
|
|
4
|
-
require "rubycritic/source_control_systems/source_control_system"
|
|
5
|
-
require "rubycritic/revision_comparator"
|
|
6
|
-
require "rubycritic/report_generators/reporter"
|
|
7
|
-
|
|
8
|
-
module Rubycritic
|
|
9
|
-
|
|
10
|
-
class Rubycritic
|
|
11
|
-
def initialize
|
|
12
|
-
@source_control_system = SourceControlSystem.create
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def critique(paths)
|
|
16
|
-
source = SourceLocator.new(paths)
|
|
17
|
-
if @source_control_system.has_revision?
|
|
18
|
-
smelly_pathnames = RevisionComparator.new(source.paths, @source_control_system).compare
|
|
19
|
-
else
|
|
20
|
-
smell_adapters = AnalysersRunner.new(source.paths).run
|
|
21
|
-
smelly_pathnames = SmellsAggregator.new(smell_adapters).smelly_pathnames
|
|
22
|
-
end
|
|
23
|
-
Reporter.new(source.pathnames, smelly_pathnames).generate_report
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
end
|
|
1
|
+
require "rubycritic/configuration"
|
|
2
|
+
require "rubycritic/orchestrator"
|
data/rubycritic.gemspec
CHANGED
|
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.summary = "Ruby code smell detector"
|
|
15
15
|
spec.homepage = "https://github.com/whitesmith/rubycritic"
|
|
16
16
|
spec.license = "MIT"
|
|
17
|
+
spec.required_ruby_version = ">= 1.9.3"
|
|
17
18
|
|
|
18
19
|
spec.files = `git ls-files`.split("\n")
|
|
19
20
|
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
@@ -21,8 +22,10 @@ Gem::Specification.new do |spec|
|
|
|
21
22
|
spec.require_path = "lib"
|
|
22
23
|
|
|
23
24
|
spec.add_runtime_dependency "virtus", "~> 1.0"
|
|
25
|
+
spec.add_runtime_dependency "flay", "2.4.0"
|
|
24
26
|
spec.add_runtime_dependency "flog", "4.2.0"
|
|
25
27
|
spec.add_runtime_dependency "reek", "1.3.6"
|
|
28
|
+
spec.add_runtime_dependency "code_analyzer", "0.4.5"
|
|
26
29
|
|
|
27
30
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
28
31
|
spec.add_development_dependency "rake"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/analysers/flog"
|
|
3
|
+
require "rubycritic/adapters/complexity/flog"
|
|
4
|
+
|
|
5
|
+
describe Rubycritic::ComplexityAdapter::Flog do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_files = [AnalysedFileDouble.new(:path => "test/samples/flog/complex.rb")]
|
|
8
|
+
Rubycritic::ComplexityAdapter::Flog.new(@analysed_files).complexity
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "#complexity" do
|
|
12
|
+
it "calculates the complexity of each file and adds it to analysed_files" do
|
|
13
|
+
@analysed_files.each do |analysed_file|
|
|
14
|
+
analysed_file.complexity.must_be_kind_of Numeric
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/adapters/smell/flay"
|
|
3
|
+
require "rubycritic/core/analysed_file"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
describe Rubycritic::SmellAdapter::Flay do
|
|
7
|
+
before do
|
|
8
|
+
@analysed_file = Rubycritic::AnalysedFile.new(
|
|
9
|
+
:pathname => Pathname.new("test/samples/flay/smelly.rb"),
|
|
10
|
+
:smells => [],
|
|
11
|
+
:duplication => 0
|
|
12
|
+
)
|
|
13
|
+
analysed_files = [@analysed_file]
|
|
14
|
+
Rubycritic::SmellAdapter::Flay.new(analysed_files).smells
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "detects smells and adds them to analysed_files" do
|
|
18
|
+
@analysed_file.smells.length.must_equal 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "creates smells with messages" do
|
|
22
|
+
smell = @analysed_file.smells.first
|
|
23
|
+
smell.message.must_be_instance_of String
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "creates smells with scores" do
|
|
27
|
+
smell = @analysed_file.smells.first
|
|
28
|
+
smell.score.must_be_kind_of Numeric
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "calculates the mass of duplicate code and adds it to analysed_files" do
|
|
32
|
+
@analysed_file.duplication.must_be(:>, 0)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/adapters/smell/flog"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::SmellAdapter::Flog do
|
|
5
|
+
before do
|
|
6
|
+
@analysed_file = AnalysedFileDouble.new(:path => "test/samples/flog/smelly.rb", :smells => [])
|
|
7
|
+
analysed_files = [@analysed_file]
|
|
8
|
+
Rubycritic::SmellAdapter::Flog.new(analysed_files).smells
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "detects smells and adds them to analysed_files" do
|
|
12
|
+
@analysed_file.smells.length.must_equal 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "creates smells with messages" do
|
|
16
|
+
smell = @analysed_file.smells.first
|
|
17
|
+
smell.message.must_be_instance_of String
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "creates smells with scores" do
|
|
21
|
+
smell = @analysed_file.smells.first
|
|
22
|
+
smell.score.must_be_kind_of Numeric
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class AnalysedFileDouble < OpenStruct; end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/adapters/smell/reek"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::SmellAdapter::Reek do
|
|
5
|
+
context "when analysing a smelly file" do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_file = AnalysedFileDouble.new(:path => "test/samples/reek/smelly.rb", :smells => [])
|
|
8
|
+
analysed_files = [@analysed_file]
|
|
9
|
+
Rubycritic::SmellAdapter::Reek.new(analysed_files).smells
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "detects smells and adds them to analysed_files" do
|
|
13
|
+
@analysed_file.smells.length.must_equal 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "creates smells with messages" do
|
|
17
|
+
smell = @analysed_file.smells.first
|
|
18
|
+
smell.message.must_equal "has boolean parameter 'reek'"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when analysing a file with smells ignored in config.reek" do
|
|
23
|
+
before do
|
|
24
|
+
@analysed_file = AnalysedFileDouble.new(:path => "test/samples/reek/not_smelly.rb", :smells => [])
|
|
25
|
+
analysed_files = [@analysed_file]
|
|
26
|
+
Rubycritic::SmellAdapter::Reek.new(analysed_files)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "does not detect smells and does not add them to analysed files" do
|
|
30
|
+
@analysed_file.smells.must_be_empty
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class AnalysedFileDouble < OpenStruct; end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/analysers/churn"
|
|
3
|
+
require "rubycritic/source_control_systems/base"
|
|
4
|
+
|
|
5
|
+
describe Rubycritic::Analyser::Churn do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_files = [AnalysedFileDouble.new(:path => "path_to_some_file.rb")]
|
|
8
|
+
@source_control_system = SourceControlSystemDouble.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "#churn" do
|
|
12
|
+
it "calculates the churn of each file and adds it to analysed_files" do
|
|
13
|
+
Rubycritic::Analyser::Churn.new(@analysed_files, @source_control_system).churn
|
|
14
|
+
@analysed_files.each do |analysed_file|
|
|
15
|
+
analysed_file.churn.must_equal 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "calculates the date of the last commit of each file and adds it to analysed_files" do
|
|
20
|
+
Rubycritic::Analyser::Churn.new(@analysed_files, @source_control_system).churn
|
|
21
|
+
@analysed_files.each do |analysed_file|
|
|
22
|
+
analysed_file.committed_at.must_equal "2013-10-09 12:52:49 +0100"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class AnalysedFileDouble < OpenStruct; end
|
|
29
|
+
|
|
30
|
+
class SourceControlSystemDouble < Rubycritic::SourceControlSystem::Base
|
|
31
|
+
def revisions_count(path)
|
|
32
|
+
1 # churn
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def date_of_last_commit(path)
|
|
36
|
+
"2013-10-09 12:52:49 +0100"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/configuration"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Configuration do
|
|
5
|
+
describe "#root" do
|
|
6
|
+
it "has a default" do
|
|
7
|
+
Rubycritic.configuration.root.wont_be_empty
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "can be configured" do
|
|
11
|
+
default = Rubycritic.configuration.root
|
|
12
|
+
Rubycritic.configuration.root = "foo"
|
|
13
|
+
Rubycritic.configuration.root.must_equal File.expand_path("foo")
|
|
14
|
+
Rubycritic.configuration.root = default
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/core/analysed_file"
|
|
3
|
+
require "rubycritic/core/smell"
|
|
4
|
+
require "rubycritic/core/location"
|
|
5
|
+
|
|
6
|
+
describe Rubycritic::AnalysedFile do
|
|
7
|
+
describe "attribute readers" do
|
|
8
|
+
before do
|
|
9
|
+
@pathname = Pathname.new("foo/bar.rb")
|
|
10
|
+
@smells = []
|
|
11
|
+
@churn = 1
|
|
12
|
+
@complexity = 2
|
|
13
|
+
@analysed_file = Rubycritic::AnalysedFile.new(
|
|
14
|
+
:pathname => @pathname,
|
|
15
|
+
:smells => @smells,
|
|
16
|
+
:churn => @churn,
|
|
17
|
+
:complexity => @complexity
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "has a pathname reader" do
|
|
22
|
+
@analysed_file.pathname.must_equal @pathname
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "has a smells reader" do
|
|
26
|
+
@analysed_file.smells.must_equal @smells
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "has a churn reader" do
|
|
30
|
+
@analysed_file.churn.must_equal @churn
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "has a complexity reader" do
|
|
34
|
+
@analysed_file.complexity.must_equal @complexity
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "has a name reader" do
|
|
38
|
+
@analysed_file.name.must_equal "bar"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "has a path reader" do
|
|
42
|
+
@analysed_file.path.must_equal @pathname.to_s
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#cost" do
|
|
47
|
+
it "returns the remediation cost of fixing the analysed_file" do
|
|
48
|
+
smells = [SmellDouble.new(:cost => 1), SmellDouble.new(:cost => 2)]
|
|
49
|
+
analysed_file = Rubycritic::AnalysedFile.new(:smells => smells, :complexity => 0)
|
|
50
|
+
analysed_file.cost.must_equal 3
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "#has_smells?" do
|
|
55
|
+
it "returns true if the analysed_file has at least one smell" do
|
|
56
|
+
analysed_file = Rubycritic::AnalysedFile.new(:smells => [SmellDouble.new])
|
|
57
|
+
analysed_file.has_smells?.must_equal true
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#smells_at_location" do
|
|
62
|
+
it "returns the smells of an analysed_file at a certain location" do
|
|
63
|
+
location = Rubycritic::Location.new("./foo", "42")
|
|
64
|
+
smells = [Rubycritic::Smell.new(:locations => [location])]
|
|
65
|
+
analysed_file = Rubycritic::AnalysedFile.new(:smells => smells)
|
|
66
|
+
analysed_file.smells_at_location(location).must_equal smells
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class SmellDouble < OpenStruct; end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
|
-
require "rubycritic/location"
|
|
2
|
+
require "rubycritic/core/location"
|
|
3
3
|
|
|
4
4
|
describe Rubycritic::Location do
|
|
5
5
|
describe "attribute readers" do
|
|
6
6
|
before do
|
|
7
|
-
@path = "./foo"
|
|
8
|
-
@line = 42
|
|
7
|
+
@path = "./foo.rb"
|
|
8
|
+
@line = "42"
|
|
9
9
|
@location = Rubycritic::Location.new(@path, @line)
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -14,7 +14,11 @@ describe Rubycritic::Location do
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "has a line number" do
|
|
17
|
-
@location.line.must_equal @line
|
|
17
|
+
@location.line.must_equal @line.to_i
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "has a file name" do
|
|
21
|
+
@location.file_name.must_equal "foo"
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/core/smell"
|
|
3
|
+
require "rubycritic/core/location"
|
|
4
|
+
|
|
5
|
+
describe Rubycritic::Smell do
|
|
6
|
+
describe "attribute readers" do
|
|
7
|
+
before do
|
|
8
|
+
@locations = [Rubycritic::Location.new("./foo", "42")]
|
|
9
|
+
@context = "#bar"
|
|
10
|
+
@message = "This smells"
|
|
11
|
+
@score = 0
|
|
12
|
+
@type = :complexity
|
|
13
|
+
@smell = Rubycritic::Smell.new(
|
|
14
|
+
:locations => @locations,
|
|
15
|
+
:context => @context,
|
|
16
|
+
:message => @message,
|
|
17
|
+
:score => @score,
|
|
18
|
+
:type => @type
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "has a context reader" do
|
|
23
|
+
@smell.context.must_equal @context
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "has a locations reader" do
|
|
27
|
+
@smell.locations.must_equal @locations
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "has a message reader" do
|
|
31
|
+
@smell.message.must_equal @message
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "has a score reader" do
|
|
35
|
+
@smell.score.must_equal @score
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "has a type reader" do
|
|
39
|
+
@smell.type.must_equal @type
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#at_location?" do
|
|
44
|
+
it "returns true if the smell has a location that matches the location passed as argument" do
|
|
45
|
+
location = Rubycritic::Location.new("./foo", "42")
|
|
46
|
+
smell = Rubycritic::Smell.new(:locations => [location])
|
|
47
|
+
smell.at_location?(location).must_equal true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "#has_multiple_locations?" do
|
|
52
|
+
it "returns true if the smell has more than one location" do
|
|
53
|
+
location1 = Rubycritic::Location.new("./foo", "42")
|
|
54
|
+
location2 = Rubycritic::Location.new("./foo", "23")
|
|
55
|
+
smell = Rubycritic::Smell.new(:locations => [location1, location2])
|
|
56
|
+
smell.has_multiple_locations?.must_equal true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#==" do
|
|
61
|
+
it "returns true if two smells have the same base attributes" do
|
|
62
|
+
attributes = {
|
|
63
|
+
:context => "#bar",
|
|
64
|
+
:message => "This smells",
|
|
65
|
+
:score => 0,
|
|
66
|
+
:type => :complexity
|
|
67
|
+
}
|
|
68
|
+
smell1 = Rubycritic::Smell.new(attributes)
|
|
69
|
+
smell2 = Rubycritic::Smell.new(attributes)
|
|
70
|
+
smell1.must_equal smell2
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
|
-
require "rubycritic/smell"
|
|
2
|
+
require "rubycritic/core/smell"
|
|
3
3
|
require "rubycritic/smells_status_setter"
|
|
4
4
|
|
|
5
5
|
describe Rubycritic::SmellsStatusSetter do
|
|
6
|
-
describe "#
|
|
6
|
+
describe "#smells" do
|
|
7
7
|
before do
|
|
8
8
|
@smell = Rubycritic::Smell.new(:context => "#bar")
|
|
9
|
-
@
|
|
9
|
+
@smells = [@smell]
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "marks old smells" do
|
|
13
|
-
Rubycritic::SmellsStatusSetter.
|
|
13
|
+
Rubycritic::SmellsStatusSetter.set(@smells, @smells)
|
|
14
14
|
@smell.status.must_equal :old
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it "marks new smells" do
|
|
18
|
-
Rubycritic::SmellsStatusSetter.
|
|
18
|
+
Rubycritic::SmellsStatusSetter.set([], @smells)
|
|
19
19
|
@smell.status.must_equal :new
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
|
-
require "rubycritic/source_control_systems/
|
|
2
|
+
require "rubycritic/source_control_systems/base"
|
|
3
3
|
|
|
4
4
|
describe Rubycritic::SourceControlSystem do
|
|
5
5
|
before do
|
|
6
|
-
Rubycritic::SourceControlSystem.systems.each do |system|
|
|
6
|
+
Rubycritic::SourceControlSystem::Base.systems.each do |system|
|
|
7
7
|
system.stubs(:supported?).returns(false)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
@@ -11,15 +11,9 @@ describe Rubycritic::SourceControlSystem do
|
|
|
11
11
|
describe "::create" do
|
|
12
12
|
describe "when a source control system is found" do
|
|
13
13
|
it "creates an instance of that source control system" do
|
|
14
|
-
Rubycritic::Git.stubs(:supported?).returns(true)
|
|
15
|
-
system = Rubycritic::SourceControlSystem.create
|
|
16
|
-
system.must_be_instance_of Rubycritic::Git
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
describe "when no source control system is found" do
|
|
21
|
-
it "raises an error" do
|
|
22
|
-
proc { Rubycritic::SourceControlSystem.create }.must_raise RuntimeError
|
|
14
|
+
Rubycritic::SourceControlSystem::Git.stubs(:supported?).returns(true)
|
|
15
|
+
system = Rubycritic::SourceControlSystem::Base.create
|
|
16
|
+
system.must_be_instance_of Rubycritic::SourceControlSystem::Git
|
|
23
17
|
end
|
|
24
18
|
end
|
|
25
19
|
end
|
|
@@ -3,12 +3,12 @@ require "rubycritic/source_locator"
|
|
|
3
3
|
|
|
4
4
|
describe Rubycritic::SourceLocator do
|
|
5
5
|
before do
|
|
6
|
-
@original_dir = Dir.
|
|
6
|
+
@original_dir = Dir.getwd
|
|
7
7
|
Dir.chdir("test/samples/location")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
describe "#paths" do
|
|
11
|
-
it "finds a single
|
|
11
|
+
it "finds a single file" do
|
|
12
12
|
paths = ["file0.rb"]
|
|
13
13
|
Rubycritic::SourceLocator.new(paths).paths.must_equal paths
|
|
14
14
|
end
|
|
@@ -18,33 +18,42 @@ describe Rubycritic::SourceLocator do
|
|
|
18
18
|
Rubycritic::SourceLocator.new(paths).paths.must_equal paths
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
it "finds all the
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
it "finds all the files inside a given directory" do
|
|
22
|
+
initial_paths = ["dir1"]
|
|
23
|
+
final_paths = ["dir1/file1.rb"]
|
|
24
|
+
Rubycritic::SourceLocator.new(initial_paths).paths.must_equal final_paths
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
it "finds all the files
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
it "finds all the files" do
|
|
28
|
+
initial_paths = ["."]
|
|
29
|
+
final_paths = ["dir1/file1.rb", "file0.rb"]
|
|
30
|
+
Rubycritic::SourceLocator.new(initial_paths).paths.must_equal final_paths
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "cleans paths of consecutive slashes and useless dots" do
|
|
34
|
+
initial_paths = [".//file0.rb"]
|
|
35
|
+
final_paths = ["file0.rb"]
|
|
36
|
+
Rubycritic::SourceLocator.new(initial_paths).paths.must_equal final_paths
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
it "ignores paths to non-existent files" do
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
initial_paths = ["non_existent_dir1/non_existent_file1.rb", "non_existent_file0.rb"]
|
|
41
|
+
final_paths = []
|
|
42
|
+
Rubycritic::SourceLocator.new(initial_paths).paths.must_equal final_paths
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
it "ignores paths to files that do not match the Ruby extension" do
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
initial_paths = ["file_with_no_extension", "file_with_different_extension.py"]
|
|
47
|
+
final_paths = []
|
|
48
|
+
Rubycritic::SourceLocator.new(initial_paths).paths.must_equal final_paths
|
|
39
49
|
end
|
|
40
50
|
end
|
|
41
51
|
|
|
42
52
|
describe "#pathnames" do
|
|
43
|
-
it "finds a single
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Rubycritic::SourceLocator.new(paths).pathnames.must_equal result
|
|
53
|
+
it "finds a single file" do
|
|
54
|
+
initial_paths = ["file0.rb"]
|
|
55
|
+
final_pathnames = [Pathname.new("file0.rb")]
|
|
56
|
+
Rubycritic::SourceLocator.new(initial_paths).pathnames.must_equal final_pathnames
|
|
48
57
|
end
|
|
49
58
|
end
|
|
50
59
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/turbulence"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Turbulence do
|
|
5
|
+
describe "#data" do
|
|
6
|
+
it "returns json data that maps pathname, churn and complexity to name, x and y" do
|
|
7
|
+
files = [AnalysedFileDouble.new(:pathname => "./foo.rb", :churn => 1, :complexity => 2)]
|
|
8
|
+
turbulence_data = Rubycritic::Turbulence.data(files)
|
|
9
|
+
instance_parsed_json = JSON.parse(turbulence_data).first
|
|
10
|
+
instance_parsed_json["name"].must_equal "./foo.rb"
|
|
11
|
+
instance_parsed_json["x"].must_equal 1
|
|
12
|
+
instance_parsed_json["y"].must_equal 2
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class AnalysedFileDouble < OpenStruct; end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AllTheMethods
|
|
2
|
+
def method_missing(method, *args, &block)
|
|
3
|
+
message = "I"
|
|
4
|
+
eval "message = ' did not'"
|
|
5
|
+
eval "message << ' exist,'"
|
|
6
|
+
eval "message << ' but now'"
|
|
7
|
+
eval "message << ' I do.'"
|
|
8
|
+
self.class.send(:define_method, method) { "I did not exist, but now I do." }
|
|
9
|
+
self.send(method)
|
|
10
|
+
end
|
|
11
|
+
end
|
data/test/samples/flog/smelly.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
class AllTheMethods
|
|
2
2
|
def method_missing(method, *args, &block)
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
message = "I"
|
|
4
|
+
eval "message = ' did not'"
|
|
5
|
+
eval "message << ' exist,'"
|
|
6
|
+
eval "message << ' but now'"
|
|
7
|
+
eval "message << ' I do.'"
|
|
8
|
+
self.class.send(:define_method, method) { "I did not exist, but now I do." }
|
|
9
|
+
self.send(method)
|
|
5
10
|
end
|
|
6
11
|
end
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
class
|
|
2
|
-
attr_reader :
|
|
1
|
+
class Perfume
|
|
2
|
+
attr_reader :perfumed
|
|
3
3
|
|
|
4
|
-
def
|
|
4
|
+
def ignoreRubyStyle(oneParameter)
|
|
5
5
|
oneVariable = oneParameter
|
|
6
6
|
end
|
|
7
|
+
|
|
8
|
+
def allow_nesting_iterators_two_levels_deep
|
|
9
|
+
loop do
|
|
10
|
+
loop do
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def method_with_too_many_statements
|
|
16
|
+
do_something
|
|
17
|
+
do_something
|
|
18
|
+
do_something
|
|
19
|
+
do_something
|
|
20
|
+
do_something
|
|
21
|
+
do_something
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def allow_up_to_two_duplicate_method_calls
|
|
25
|
+
respond_to do |format|
|
|
26
|
+
if success
|
|
27
|
+
format.html { redirect_to some_path }
|
|
28
|
+
format.js { head :ok }
|
|
29
|
+
else
|
|
30
|
+
format.html { redirect_to :back, status: :bad_request }
|
|
31
|
+
format.js { render status: :bad_request }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
7
35
|
end
|