rubycritic 0.0.5 → 1.4.0
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/.rubocop.yml +593 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +45 -0
- data/CONTRIBUTING.md +67 -15
- data/README.md +105 -14
- data/Rakefile +9 -6
- data/bin/rubycritic +3 -1
- data/lib/rubycritic/analysers/attributes.rb +21 -0
- data/lib/rubycritic/analysers/churn.rb +21 -0
- data/lib/rubycritic/analysers/complexity.rb +22 -0
- data/lib/rubycritic/analysers/helpers/ast_node.rb +69 -0
- data/lib/rubycritic/analysers/{config.reek → helpers/config.reek} +8 -0
- data/lib/rubycritic/analysers/helpers/flay.rb +13 -0
- data/lib/rubycritic/analysers/helpers/flog.rb +17 -0
- data/lib/rubycritic/analysers/helpers/methods_counter.rb +25 -0
- data/lib/rubycritic/analysers/helpers/modules_locator.rb +43 -0
- data/lib/rubycritic/analysers/helpers/parser.rb +12 -0
- data/lib/rubycritic/analysers/helpers/reek.rb +17 -0
- data/lib/rubycritic/analysers/smells/flay.rb +68 -0
- data/lib/rubycritic/analysers/smells/flog.rb +62 -0
- data/lib/rubycritic/analysers/smells/reek.rb +44 -0
- data/lib/rubycritic/analysers_runner.rb +21 -10
- data/lib/rubycritic/cli/application.rb +24 -0
- data/lib/rubycritic/cli/options.rb +79 -0
- data/lib/rubycritic/commands/ci.rb +26 -0
- data/lib/rubycritic/commands/default.rb +28 -0
- data/lib/rubycritic/commands/help.rb +13 -0
- data/lib/rubycritic/commands/version.rb +11 -0
- data/lib/rubycritic/configuration.rb +33 -0
- data/lib/rubycritic/core/analysed_module.rb +66 -0
- data/lib/rubycritic/{location.rb → core/location.rb} +17 -2
- data/lib/rubycritic/core/rating.rb +30 -0
- data/lib/rubycritic/{smell.rb → core/smell.rb} +22 -13
- data/lib/rubycritic/generators/html/assets/javascripts/application.js +104 -0
- data/lib/rubycritic/generators/html/assets/javascripts/highcharts.src-4.0.1.js +17672 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.floatThead-v1.2.7.js +754 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.scrollTo-1.4.11.js +186 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.tablesorter.js +2089 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
- data/lib/rubycritic/generators/html/assets/stylesheets/application.css +303 -0
- data/lib/rubycritic/{report_generators → generators/html}/assets/stylesheets/prettify.custom_theme.css +1 -4
- data/lib/rubycritic/generators/html/base.rb +52 -0
- data/lib/rubycritic/generators/html/code_file.rb +40 -0
- data/lib/rubycritic/generators/html/code_index.rb +26 -0
- data/lib/rubycritic/generators/html/line.rb +37 -0
- data/lib/rubycritic/generators/html/overview.rb +27 -0
- data/lib/rubycritic/generators/html/smells_index.rb +38 -0
- data/lib/rubycritic/generators/html/templates/code_file.html.erb +38 -0
- data/lib/rubycritic/generators/html/templates/code_index.html.erb +30 -0
- data/lib/rubycritic/generators/html/templates/layouts/application.html.erb +34 -0
- data/lib/rubycritic/generators/html/templates/overview.html.erb +5 -0
- data/lib/rubycritic/generators/html/templates/smells_index.html.erb +26 -0
- data/lib/rubycritic/{report_generators → generators/html}/templates/smelly_line.html.erb +1 -1
- data/lib/rubycritic/generators/html/turbulence.rb +17 -0
- data/lib/rubycritic/generators/html/view_helpers.rb +43 -0
- data/lib/rubycritic/generators/html_report.rb +66 -0
- data/lib/rubycritic/generators/json/simple.rb +30 -0
- data/lib/rubycritic/generators/json_report.rb +23 -0
- data/lib/rubycritic/reporter.rb +20 -0
- data/lib/rubycritic/revision_comparator.rb +27 -29
- data/lib/rubycritic/serializer.rb +32 -0
- data/lib/rubycritic/smells_status_setter.rb +7 -16
- data/lib/rubycritic/source_control_systems/base.rb +37 -0
- data/lib/rubycritic/source_control_systems/double.rb +18 -0
- data/lib/rubycritic/source_control_systems/git.rb +41 -37
- data/lib/rubycritic/source_control_systems/mercurial.rb +29 -0
- data/lib/rubycritic/source_locator.rb +25 -13
- data/lib/rubycritic/version.rb +1 -1
- data/lib/rubycritic.rb +17 -22
- data/rubycritic.gemspec +10 -7
- data/test/analysers_test_helper.rb +3 -0
- data/test/lib/rubycritic/analysers/churn_test.rb +33 -0
- data/test/lib/rubycritic/analysers/complexity_test.rb +16 -0
- data/test/lib/rubycritic/analysers/helpers/methods_counter_test.rb +29 -0
- data/test/lib/rubycritic/analysers/helpers/modules_locator_test.rb +53 -0
- data/test/lib/rubycritic/analysers/smells/flay_test.rb +39 -0
- data/test/lib/rubycritic/analysers/smells/flog_test.rb +26 -0
- data/test/lib/rubycritic/analysers/smells/reek_test.rb +33 -0
- data/test/lib/rubycritic/configuration_test.rb +29 -0
- data/test/lib/rubycritic/core/analysed_module_test.rb +88 -0
- data/test/lib/rubycritic/{location_test.rb → core/location_test.rb} +8 -4
- data/test/lib/rubycritic/core/smell_test.rb +72 -0
- data/test/lib/rubycritic/{smells_array_test.rb → core/smells_array_test.rb} +1 -1
- data/test/lib/rubycritic/report_generators/turbulence_test.rb +17 -0
- data/test/lib/rubycritic/report_generators/view_helpers_test.rb +83 -0
- data/test/lib/rubycritic/smells_status_setter_test.rb +5 -5
- data/test/lib/rubycritic/source_control_systems/base_test.rb +29 -0
- data/test/lib/rubycritic/source_control_systems/double_test.rb +11 -0
- data/test/lib/rubycritic/source_control_systems/git_test.rb +13 -0
- data/test/lib/rubycritic/source_control_systems/interfaces/basic.rb +7 -0
- data/test/lib/rubycritic/source_control_systems/interfaces/time_travel.rb +7 -0
- data/test/lib/rubycritic/source_control_systems/mercurial_test.rb +11 -0
- data/test/lib/rubycritic/source_locator_test.rb +42 -18
- data/test/lib/rubycritic/version_test.rb +1 -0
- data/test/samples/empty.rb +0 -0
- data/test/samples/flay/smelly.rb +8 -0
- data/test/samples/flay/smelly2.rb +8 -0
- data/test/samples/flog/complex.rb +11 -0
- data/test/samples/flog/smelly.rb +7 -2
- data/test/samples/location/file0_symlink.rb +0 -0
- data/test/samples/methods_count.rb +7 -0
- data/test/samples/module_names.rb +18 -0
- data/test/samples/reek/not_smelly.rb +31 -3
- data/test/samples/unparsable.rb +1 -0
- data/test/test_helper.rb +39 -0
- metadata +178 -53
- data/SPEC.md +0 -58
- data/lib/rubycritic/analysers/flog.rb +0 -20
- data/lib/rubycritic/analysers/reek.rb +0 -15
- data/lib/rubycritic/cli.rb +0 -25
- data/lib/rubycritic/report_generators/assets/javascripts/application.js +0 -25
- data/lib/rubycritic/report_generators/assets/stylesheets/application.css +0 -26
- 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/report_generators/templates/layouts/application.html.erb +0 -19
- data/lib/rubycritic/report_generators/view_helpers.rb +0 -26
- 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/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +0 -26
- /data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery-2.1.0.js +0 -0
- /data/lib/rubycritic/{report_generators/assets/javascripts/prettify.js → generators/html/assets/javascripts/prettify-4-Mar-2013.js} +0 -0
- /data/lib/rubycritic/{report_generators → generators/html}/templates/line.html.erb +0 -0
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
module Rubycritic
|
|
2
|
+
module SourceControlSystem
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
class Git < Base
|
|
5
|
+
register_system
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
def self.supported?
|
|
8
|
+
`git branch 2>&1` && $?.success?
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
def self.to_s
|
|
12
|
+
"Git"
|
|
13
|
+
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
def revisions_count(path)
|
|
16
|
+
`git log --follow --format=%h #{path.shellescape}`.count("\n")
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
def date_of_last_commit(path)
|
|
20
|
+
`git log -1 --date=iso --format=%ad #{path.shellescape}`.chomp!
|
|
21
|
+
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
ensure
|
|
26
|
-
travel_to_original_state if stash_successful
|
|
27
|
-
end
|
|
23
|
+
def revision?
|
|
24
|
+
head_reference && $?.success?
|
|
25
|
+
end
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
def head_reference
|
|
28
|
+
`git rev-parse --verify HEAD`.chomp!
|
|
29
|
+
end
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
def travel_to_head
|
|
32
|
+
stash_successful = stash_changes
|
|
33
|
+
yield
|
|
34
|
+
ensure
|
|
35
|
+
travel_to_original_state if stash_successful
|
|
36
|
+
end
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
`git stash`
|
|
36
|
-
stashes_count_after = stashes_count
|
|
37
|
-
stashes_count_after > stashes_count_before
|
|
38
|
-
end
|
|
38
|
+
private
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
def stash_changes
|
|
41
|
+
stashes_count_before = stashes_count
|
|
42
|
+
`git stash`
|
|
43
|
+
stashes_count_after = stashes_count
|
|
44
|
+
stashes_count_after > stashes_count_before
|
|
45
|
+
end
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
def stashes_count
|
|
48
|
+
`git stash list --format=%h`.count("\n")
|
|
49
|
+
end
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
def travel_to_original_state
|
|
52
|
+
`git stash pop`
|
|
53
|
+
end
|
|
50
54
|
end
|
|
51
|
-
end
|
|
52
55
|
|
|
56
|
+
end
|
|
53
57
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Rubycritic
|
|
2
|
+
module SourceControlSystem
|
|
3
|
+
|
|
4
|
+
class Mercurial < Base
|
|
5
|
+
register_system
|
|
6
|
+
|
|
7
|
+
def self.supported?
|
|
8
|
+
`hg verify 2>&1` && $?.success?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.to_s
|
|
12
|
+
"Mercurial"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def revisions_count(path)
|
|
16
|
+
`hg log #{path.shellescape} --template '1'`.size
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def date_of_last_commit(path)
|
|
20
|
+
`hg log #{path.shellescape} --template '{date|isodate}' --limit 1`.chomp
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def revision?
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -7,32 +7,44 @@ module Rubycritic
|
|
|
7
7
|
RUBY_FILES = File.join("**", "*#{RUBY_EXTENSION}")
|
|
8
8
|
|
|
9
9
|
def initialize(paths)
|
|
10
|
-
@
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def pathnames
|
|
14
|
-
@pathnames ||= expand_paths
|
|
10
|
+
@initial_paths = Array(paths)
|
|
15
11
|
end
|
|
16
12
|
|
|
17
13
|
def paths
|
|
18
14
|
@paths ||= pathnames.map(&:to_s)
|
|
19
15
|
end
|
|
20
16
|
|
|
17
|
+
def pathnames
|
|
18
|
+
@pathnames ||= expand_paths
|
|
19
|
+
end
|
|
20
|
+
|
|
21
21
|
private
|
|
22
22
|
|
|
23
|
+
def deduplicate_symlinks(path_list)
|
|
24
|
+
# sort the symlinks to the end so files are preferred
|
|
25
|
+
path_list.sort_by! { |path| File.symlink?(path.cleanpath) ? "z" : "a" }
|
|
26
|
+
if defined?(JRUBY_VERSION)
|
|
27
|
+
require "java"
|
|
28
|
+
path_list.uniq! do |path|
|
|
29
|
+
java.io.File.new(path.realpath.to_s).canonical_path
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
path_list.uniq!(&:realpath)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
23
36
|
def expand_paths
|
|
24
|
-
@
|
|
37
|
+
path_list = @initial_paths.flat_map do |path|
|
|
25
38
|
if File.directory?(path)
|
|
26
|
-
Pathname.glob(
|
|
27
|
-
elsif File.
|
|
39
|
+
Pathname.glob(File.join(path, RUBY_FILES))
|
|
40
|
+
elsif File.exist?(path) && File.extname(path) == RUBY_EXTENSION
|
|
28
41
|
Pathname.new(path)
|
|
29
42
|
end
|
|
30
|
-
end.
|
|
31
|
-
|
|
43
|
+
end.compact
|
|
44
|
+
|
|
45
|
+
deduplicate_symlinks(path_list) if Config.deduplicate_symlinks
|
|
32
46
|
|
|
33
|
-
|
|
34
|
-
(path == ".") ? RUBY_FILES : File.join(path, RUBY_FILES)
|
|
47
|
+
path_list.map(&:cleanpath)
|
|
35
48
|
end
|
|
36
49
|
end
|
|
37
|
-
|
|
38
50
|
end
|
data/lib/rubycritic/version.rb
CHANGED
data/lib/rubycritic.rb
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
require "rubycritic/
|
|
2
|
-
require "rubycritic/analysers_runner"
|
|
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"
|
|
1
|
+
require "rubycritic/configuration"
|
|
7
2
|
|
|
8
3
|
module Rubycritic
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
4
|
+
def self.create(options = {})
|
|
5
|
+
options_hash = options.to_h
|
|
6
|
+
Config.set(options_hash)
|
|
7
|
+
case Config.mode
|
|
8
|
+
when :version
|
|
9
|
+
require "rubycritic/commands/version"
|
|
10
|
+
Command::Version.new
|
|
11
|
+
when :help
|
|
12
|
+
require "rubycritic/commands/help"
|
|
13
|
+
Command::Help.new(options.help_text)
|
|
14
|
+
when :ci
|
|
15
|
+
require "rubycritic/commands/ci"
|
|
16
|
+
Command::Ci.new(options_hash[:paths])
|
|
17
|
+
else
|
|
18
|
+
require "rubycritic/commands/default"
|
|
19
|
+
Command::Default.new(options_hash[:paths])
|
|
24
20
|
end
|
|
25
21
|
end
|
|
26
|
-
|
|
27
22
|
end
|
data/rubycritic.gemspec
CHANGED
|
@@ -8,24 +8,27 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.version = Rubycritic::VERSION
|
|
9
9
|
spec.authors = ["Guilherme Simoes"]
|
|
10
10
|
spec.email = ["guilherme.rdems@gmail.com"]
|
|
11
|
-
spec.description =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
spec.summary = "Ruby code smell detector"
|
|
11
|
+
spec.description = "RubyCritic is a tool that wraps around various static analysis gems "\
|
|
12
|
+
"to provide a quality report of your Ruby code."
|
|
13
|
+
spec.summary = "RubyCritic is a Ruby code quality reporter"
|
|
15
14
|
spec.homepage = "https://github.com/whitesmith/rubycritic"
|
|
16
15
|
spec.license = "MIT"
|
|
16
|
+
spec.required_ruby_version = ">= 1.9.3"
|
|
17
17
|
|
|
18
18
|
spec.files = `git ls-files`.split("\n")
|
|
19
|
-
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
20
20
|
spec.test_files = `git ls-files -- test/*`.split("\n")
|
|
21
21
|
spec.require_path = "lib"
|
|
22
22
|
|
|
23
23
|
spec.add_runtime_dependency "virtus", "~> 1.0"
|
|
24
|
-
spec.add_runtime_dependency "
|
|
25
|
-
spec.add_runtime_dependency "
|
|
24
|
+
spec.add_runtime_dependency "flay", "2.4.0"
|
|
25
|
+
spec.add_runtime_dependency "flog", "4.2.1"
|
|
26
|
+
spec.add_runtime_dependency "reek", "1.6.5"
|
|
27
|
+
spec.add_runtime_dependency "parser", ">= 2.2.0", "< 3.0"
|
|
26
28
|
|
|
27
29
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
28
30
|
spec.add_development_dependency "rake"
|
|
29
31
|
spec.add_development_dependency "minitest", "~> 5.3"
|
|
30
32
|
spec.add_development_dependency "mocha", "~> 1.0"
|
|
33
|
+
spec.add_development_dependency "rubocop", "0.28.0"
|
|
31
34
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "analysers_test_helper"
|
|
2
|
+
require "rubycritic/analysers/churn"
|
|
3
|
+
require "rubycritic/source_control_systems/base"
|
|
4
|
+
|
|
5
|
+
describe Rubycritic::Analyser::Churn do
|
|
6
|
+
context "when analysing a file" do
|
|
7
|
+
before do
|
|
8
|
+
@analysed_module = AnalysedModuleDouble.new(:path => "path_to_some_file.rb")
|
|
9
|
+
analysed_modules = [@analysed_module]
|
|
10
|
+
analyser = Rubycritic::Analyser::Churn.new(analysed_modules)
|
|
11
|
+
analyser.source_control_system = SourceControlSystemDouble.new
|
|
12
|
+
analyser.run
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "calculates its churn" do
|
|
16
|
+
@analysed_module.churn.must_equal 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "determines the date of its last commit" do
|
|
20
|
+
@analysed_module.committed_at.must_equal "2013-10-09 12:52:49 +0100"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class SourceControlSystemDouble < Rubycritic::SourceControlSystem::Base
|
|
26
|
+
def revisions_count(_path)
|
|
27
|
+
1 # churn
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def date_of_last_commit(_path)
|
|
31
|
+
"2013-10-09 12:52:49 +0100"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "analysers_test_helper"
|
|
2
|
+
require "rubycritic/analysers/complexity"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Analyser::Complexity do
|
|
5
|
+
context "when analysing a file" do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_module = AnalysedModuleDouble.new(:path => "test/samples/flog/complex.rb", :smells => [])
|
|
8
|
+
analysed_modules = [@analysed_module]
|
|
9
|
+
Rubycritic::Analyser::Complexity.new(analysed_modules).run
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "calculates its complexity" do
|
|
13
|
+
@analysed_module.complexity.must_be :>, 0
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "analysers_test_helper"
|
|
2
|
+
require "rubycritic/analysers/helpers/methods_counter"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::MethodsCounter do
|
|
5
|
+
describe "#count" do
|
|
6
|
+
context "when a file contains Ruby code" do
|
|
7
|
+
it "calculates the number of methods" do
|
|
8
|
+
analysed_module = AnalysedModuleDouble.new(:path => "test/samples/methods_count.rb")
|
|
9
|
+
Rubycritic::MethodsCounter.new(analysed_module).count.must_equal 2
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "when a file is empty" do
|
|
14
|
+
it "returns 0 as the number of methods" do
|
|
15
|
+
analysed_module = AnalysedModuleDouble.new(:path => "test/samples/empty.rb")
|
|
16
|
+
Rubycritic::MethodsCounter.new(analysed_module).count.must_equal 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when a file is unparsable" do
|
|
21
|
+
it "does not blow up and returns 0 as the number of methods" do
|
|
22
|
+
analysed_module = AnalysedModuleDouble.new(:path => "test/samples/unparsable.rb")
|
|
23
|
+
capture_output_streams do
|
|
24
|
+
Rubycritic::MethodsCounter.new(analysed_module).count.must_equal 0
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/analysers/helpers/modules_locator"
|
|
3
|
+
require "rubycritic/core/analysed_module"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
describe Rubycritic::ModulesLocator do
|
|
7
|
+
describe "#names" do
|
|
8
|
+
context "when a file contains Ruby code" do
|
|
9
|
+
it "returns the names of all the classes and modules inside the file" do
|
|
10
|
+
analysed_module = Rubycritic::AnalysedModule.new(
|
|
11
|
+
:pathname => Pathname.new("test/samples/module_names.rb"),
|
|
12
|
+
:methods_count => 1
|
|
13
|
+
)
|
|
14
|
+
Rubycritic::ModulesLocator.new(analysed_module).names
|
|
15
|
+
.must_equal ["Foo", "Foo::Bar", "Foo::Baz", "Foo::Qux", "Foo::Quux::Corge"]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context "when a file is empty" do
|
|
20
|
+
it "returns the name of the file titleized" do
|
|
21
|
+
analysed_module = Rubycritic::AnalysedModule.new(
|
|
22
|
+
:pathname => Pathname.new("test/samples/empty.rb"),
|
|
23
|
+
:methods_count => 1
|
|
24
|
+
)
|
|
25
|
+
Rubycritic::ModulesLocator.new(analysed_module).names.must_equal ["Empty"]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "when a file is unparsable" do
|
|
30
|
+
it "does not blow up and returns the name of the file titleized" do
|
|
31
|
+
analysed_module = Rubycritic::AnalysedModule.new(
|
|
32
|
+
:pathname => Pathname.new("test/samples/unparsable.rb"),
|
|
33
|
+
:methods_count => 1
|
|
34
|
+
)
|
|
35
|
+
capture_output_streams do
|
|
36
|
+
Rubycritic::ModulesLocator.new(analysed_module).names.must_equal ["Unparsable"]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "when a file has no methods" do
|
|
42
|
+
it "returns the name of the file titleized" do
|
|
43
|
+
analysed_module = Rubycritic::AnalysedModule.new(
|
|
44
|
+
:pathname => Pathname.new("test/samples/no_methods.rb"),
|
|
45
|
+
:methods_count => 0
|
|
46
|
+
)
|
|
47
|
+
capture_output_streams do
|
|
48
|
+
Rubycritic::ModulesLocator.new(analysed_module).names.must_equal ["NoMethods"]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/analysers/smells/flay"
|
|
3
|
+
require "rubycritic/core/analysed_module"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
describe Rubycritic::Analyser::FlaySmells do
|
|
7
|
+
context "when analysing a bunch of files with duplicate code" do
|
|
8
|
+
before do
|
|
9
|
+
@analysed_modules = [
|
|
10
|
+
Rubycritic::AnalysedModule.new(:pathname => Pathname.new("test/samples/flay/smelly.rb")),
|
|
11
|
+
Rubycritic::AnalysedModule.new(:pathname => Pathname.new("test/samples/flay/smelly2.rb"))
|
|
12
|
+
]
|
|
13
|
+
Rubycritic::Analyser::FlaySmells.new(@analysed_modules).run
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "detects its smells" do
|
|
17
|
+
@analysed_modules.first.smells?.must_equal true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "creates smells with messages" do
|
|
21
|
+
smell = @analysed_modules.first.smells.first
|
|
22
|
+
smell.message.must_be_instance_of String
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "creates smells with scores" do
|
|
26
|
+
smell = @analysed_modules.first.smells.first
|
|
27
|
+
smell.score.must_be_kind_of Numeric
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "creates smells with more than one location" do
|
|
31
|
+
smell = @analysed_modules.first.smells.first
|
|
32
|
+
smell.multiple_locations?.must_equal true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "calculates the mass of duplicate code" do
|
|
36
|
+
@analysed_modules.first.duplication.must_be(:>, 0)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "analysers_test_helper"
|
|
2
|
+
require "rubycritic/analysers/smells/flog"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Analyser::FlogSmells do
|
|
5
|
+
context "when analysing a complex file" do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_module = AnalysedModuleDouble.new(:path => "test/samples/flog/smelly.rb", :smells => [])
|
|
8
|
+
analysed_modules = [@analysed_module]
|
|
9
|
+
Rubycritic::Analyser::FlogSmells.new(analysed_modules).run
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "detects its smells" do
|
|
13
|
+
@analysed_module.smells.length.must_equal 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "creates smells with messages" do
|
|
17
|
+
smell = @analysed_module.smells.first
|
|
18
|
+
smell.message.must_be_instance_of String
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "creates smells with scores" do
|
|
22
|
+
smell = @analysed_module.smells.first
|
|
23
|
+
smell.score.must_be :>, 0
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "analysers_test_helper"
|
|
2
|
+
require "rubycritic/analysers/smells/reek"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Analyser::ReekSmells do
|
|
5
|
+
context "when analysing a smelly file" do
|
|
6
|
+
before do
|
|
7
|
+
@analysed_module = AnalysedModuleDouble.new(:path => "test/samples/reek/smelly.rb", :smells => [])
|
|
8
|
+
analysed_modules = [@analysed_module]
|
|
9
|
+
Rubycritic::Analyser::ReekSmells.new(analysed_modules).run
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "detects its smells" do
|
|
13
|
+
@analysed_module.smells.length.must_equal 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "creates smells with messages" do
|
|
17
|
+
smell = @analysed_module.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_module = AnalysedModuleDouble.new(:path => "test/samples/reek/not_smelly.rb", :smells => [])
|
|
25
|
+
analysed_modules = [@analysed_module]
|
|
26
|
+
Rubycritic::Analyser::ReekSmells.new(analysed_modules).run
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "does not detect those smells" do
|
|
30
|
+
@analysed_module.smells.must_be_empty
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/configuration"
|
|
3
|
+
|
|
4
|
+
describe Rubycritic::Configuration do
|
|
5
|
+
describe "#root" do
|
|
6
|
+
before do
|
|
7
|
+
Rubycritic::Config.set
|
|
8
|
+
@default = Rubycritic::Config.root
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "has a default" do
|
|
12
|
+
Rubycritic::Config.root.must_be_instance_of String
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "can be set to a relative path" do
|
|
16
|
+
Rubycritic::Config.root = "foo"
|
|
17
|
+
Rubycritic::Config.root.must_equal File.expand_path("foo")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "can be set to an absolute path" do
|
|
21
|
+
Rubycritic::Config.root = "/foo"
|
|
22
|
+
Rubycritic::Config.root.must_equal "/foo"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
after do
|
|
26
|
+
Rubycritic::Config.root = @default
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "rubycritic/core/analysed_module"
|
|
3
|
+
require "rubycritic/core/smell"
|
|
4
|
+
|
|
5
|
+
describe Rubycritic::AnalysedModule do
|
|
6
|
+
describe "attribute readers" do
|
|
7
|
+
before do
|
|
8
|
+
@name = "Foo"
|
|
9
|
+
@pathname = Pathname.new("foo.rb")
|
|
10
|
+
@smells = []
|
|
11
|
+
@churn = 1
|
|
12
|
+
@complexity = 2
|
|
13
|
+
@analysed_module = Rubycritic::AnalysedModule.new(
|
|
14
|
+
:name => @name,
|
|
15
|
+
:pathname => @pathname,
|
|
16
|
+
:smells => @smells,
|
|
17
|
+
:churn => @churn,
|
|
18
|
+
:complexity => @complexity
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "has a name reader" do
|
|
23
|
+
@analysed_module.name.must_equal @name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "has a pathname reader" do
|
|
27
|
+
@analysed_module.pathname.must_equal @pathname
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "has a path reader" do
|
|
31
|
+
@analysed_module.path.must_equal @pathname.to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "has a smells reader" do
|
|
35
|
+
@analysed_module.smells.must_equal @smells
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "has a churn reader" do
|
|
39
|
+
@analysed_module.churn.must_equal @churn
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "has a complexity reader" do
|
|
43
|
+
@analysed_module.complexity.must_equal @complexity
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#cost" do
|
|
48
|
+
it "returns the remediation cost of fixing the analysed_module" do
|
|
49
|
+
smells = [SmellDouble.new(:cost => 1), SmellDouble.new(:cost => 2)]
|
|
50
|
+
analysed_module = Rubycritic::AnalysedModule.new(:smells => smells, :complexity => 0)
|
|
51
|
+
analysed_module.cost.must_equal 3
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "#complexity_per_method" do
|
|
56
|
+
context "when the file has no methods" do
|
|
57
|
+
it "returns a placeholder" do
|
|
58
|
+
analysed_module = Rubycritic::AnalysedModule.new(:complexity => 0, :methods_count => 0)
|
|
59
|
+
analysed_module.complexity_per_method.must_equal "N/A"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "when the file has at least one method" do
|
|
64
|
+
it "returns the average complexity per method" do
|
|
65
|
+
analysed_module = Rubycritic::AnalysedModule.new(:complexity => 10, :methods_count => 2)
|
|
66
|
+
analysed_module.complexity_per_method.must_equal 5
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "#smells?" do
|
|
72
|
+
it "returns true if the analysed_module has at least one smell" do
|
|
73
|
+
analysed_module = Rubycritic::AnalysedModule.new(:smells => [SmellDouble.new])
|
|
74
|
+
analysed_module.smells?.must_equal true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#smells_at_location" do
|
|
79
|
+
it "returns the smells of an analysed_module at a certain location" do
|
|
80
|
+
location = Rubycritic::Location.new("./foo", "42")
|
|
81
|
+
smells = [Rubycritic::Smell.new(:locations => [location])]
|
|
82
|
+
analysed_module = Rubycritic::AnalysedModule.new(:smells => smells)
|
|
83
|
+
analysed_module.smells_at_location(location).must_equal smells
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
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
|
|