Skip to content

Commit 2d8a348

Browse files
committed
Move Console Report out of Status Reporter
The status reporter has a different purpuse in the RubyCritic gem, they also have the specific usage of the Console Report and now we are following the same patters that gem created. - Added support for a new console output format in the FormatValidator module. - Refactored the StatusReporter to provide a simplified status message upon completion of analysis. - Introduced ConsoleReport and Simple classes for generating detailed console reports of analysed modules. - Updated tests to validate new console reporting functionality and ensure expected outputs. - Adjusted existing tests to reflect changes in the status reporting method.
1 parent 59fb32d commit 2d8a348

File tree

11 files changed

+229
-136
lines changed

11 files changed

+229
-136
lines changed

lib/skunk/commands/status_reporter.rb

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# frozen_string_literal: true
22

3-
require "erb"
43
require "rubycritic/commands/status_reporter"
5-
require "terminal-table"
64

75
module Skunk
86
module Command
@@ -14,78 +12,9 @@ def initialize(options = {})
1412
super(options)
1513
end
1614

17-
HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze
18-
HEADINGS_WITHOUT_FILE = HEADINGS - %w[file]
19-
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
20-
21-
TEMPLATE = ERB.new(<<-TEMPL
22-
<%= _ttable %>\n
23-
SkunkScore Total: <%= total_skunk_score %>
24-
Modules Analysed: <%= analysed_modules_count %>
25-
SkunkScore Average: <%= skunk_score_average %>
26-
<% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %>
27-
28-
Generated with Skunk v<%= Skunk::VERSION %>
29-
TEMPL
30-
)
31-
32-
# Returns a status message with a table of all analysed_modules and
33-
# a skunk score average
15+
# Returns a simple status message indicating the analysis is complete
3416
def update_status_message
35-
opts = table_options.merge(headings: HEADINGS, rows: table)
36-
37-
_ttable = Terminal::Table.new(opts)
38-
39-
@status_message = TEMPLATE.result(binding)
40-
end
41-
42-
private
43-
44-
def analysed_modules_count
45-
analysed_modules.analysed_modules_count
46-
end
47-
48-
def worst
49-
analysed_modules.worst_module
50-
end
51-
52-
def sorted_modules
53-
analysed_modules.sorted_modules
54-
end
55-
56-
def total_skunk_score
57-
analysed_modules.skunk_score_total
58-
end
59-
60-
def total_churn_times_cost
61-
analysed_modules.total_churn_times_cost
62-
end
63-
64-
def skunk_score_average
65-
analysed_modules.skunk_score_average
66-
end
67-
68-
def table_options
69-
max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length }
70-
width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH
71-
{
72-
style: {
73-
width: width
74-
}
75-
}
76-
end
77-
78-
def table
79-
sorted_modules.map do |a_mod|
80-
[
81-
a_mod.pathname,
82-
a_mod.skunk_score,
83-
a_mod.churn_times_cost,
84-
a_mod.churn,
85-
a_mod.cost.round(2),
86-
a_mod.coverage.round(2)
87-
]
88-
end
17+
@status_message = "Skunk analysis complete. Use --format console to see detailed output."
8918
end
9019
end
9120
end

lib/skunk/config.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module Skunk
44
# Utility module for format validation
55
module FormatValidator
66
# Supported output formats
7-
SUPPORTED_FORMATS = %i[json html].freeze
7+
SUPPORTED_FORMATS = %i[json html console].freeze
88

99
# Check if a format is supported
1010
# @param format [Symbol] Format to check
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# frozen_string_literal: true
2+
3+
require "erb"
4+
require "terminal-table"
5+
6+
module Skunk
7+
module Generator
8+
module Console
9+
# Generates a console report for the analysed modules.
10+
class Simple
11+
def initialize(analysed_modules)
12+
@analysed_modules = analysed_modules
13+
end
14+
15+
HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze
16+
HEADINGS_WITHOUT_FILE = HEADINGS - %w[file]
17+
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
18+
19+
TEMPLATE = ERB.new(<<-TEMPL
20+
<%= _ttable %>
21+
22+
SkunkScore Total: <%= total_skunk_score %>
23+
Modules Analysed: <%= analysed_modules_count %>
24+
SkunkScore Average: <%= skunk_score_average %>
25+
<% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %>
26+
27+
Generated with Skunk v<%= Skunk::VERSION %>
28+
TEMPL
29+
)
30+
31+
def render
32+
opts = table_options.merge(headings: HEADINGS, rows: table)
33+
_ttable = Terminal::Table.new(opts)
34+
TEMPLATE.result(binding)
35+
end
36+
37+
private
38+
39+
def analysed_modules_count
40+
@analysed_modules.analysed_modules_count
41+
end
42+
43+
def worst
44+
@analysed_modules.worst_module
45+
end
46+
47+
def sorted_modules
48+
@analysed_modules.sorted_modules
49+
end
50+
51+
def total_skunk_score
52+
@analysed_modules.skunk_score_total
53+
end
54+
55+
def total_churn_times_cost
56+
@analysed_modules.total_churn_times_cost
57+
end
58+
59+
def skunk_score_average
60+
@analysed_modules.skunk_score_average
61+
end
62+
63+
def table_options
64+
return { style: { width: 100 } } if sorted_modules.empty?
65+
66+
max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length }
67+
width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH
68+
{
69+
style: {
70+
width: width
71+
}
72+
}
73+
end
74+
75+
def table
76+
sorted_modules.map do |a_mod|
77+
[
78+
a_mod.pathname,
79+
a_mod.skunk_score,
80+
a_mod.churn_times_cost,
81+
a_mod.churn,
82+
a_mod.cost.round(2),
83+
a_mod.coverage.round(2)
84+
]
85+
end
86+
end
87+
end
88+
end
89+
end
90+
end
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
require "erb"
4+
require "terminal-table"
5+
6+
require "skunk/generators/console/simple"
7+
8+
module Skunk
9+
module Generator
10+
# Generates a console report for the analysed modules.
11+
class ConsoleReport
12+
def initialize(analysed_modules)
13+
@analysed_modules = analysed_modules
14+
end
15+
16+
def generate_report
17+
puts generator.render
18+
end
19+
20+
private
21+
22+
def generator
23+
@generator ||= Skunk::Generator::Console::Simple.new(@analysed_modules)
24+
end
25+
end
26+
end
27+
end

test/lib/skunk/application_test.rb

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,6 @@
3535
end
3636
end
3737

38-
context "when passing --out option with a file" do
39-
require "fileutils"
40-
41-
let(:argv) { ["--out=tmp/generated_report.txt", "samples/rubycritic"] }
42-
let(:success_code) { 0 }
43-
44-
it "writes output to the file" do
45-
FileUtils.rm("tmp/generated_report.txt", force: true)
46-
FileUtils.mkdir_p("tmp")
47-
48-
RubyCritic::AnalysedModule.stub_any_instance(:churn, 1) do
49-
RubyCritic::AnalysedModule.stub_any_instance(:coverage, 100.0) do
50-
result = application.execute
51-
_(result).must_equal success_code
52-
end
53-
end
54-
55-
_(File.read("tmp/generated_report.txt"))
56-
.must_include File.read("test/samples/console_output.txt")
57-
end
58-
end
59-
6038
context "when comparing two branches" do
6139
let(:argv) { ["-b main", "samples/rubycritic"] }
6240
let(:success_code) { 0 }

test/lib/skunk/commands/status_reporter_test.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ def analysed_module.churn
3232
example.call
3333
end
3434

35-
it "reports the SkunkScore" do
36-
_(reporter.update_status_message).must_include output
37-
_(reporter.update_status_message).must_include "Generated with Skunk v#{Skunk::VERSION}"
35+
it "reports a simple status message" do
36+
_(reporter.update_status_message).must_equal "Skunk analysis complete. Use --format console to see detailed output."
3837
end
3938

4039
context "When there's nested spec files" do
4140
let(:paths) { "samples" }
42-
it "reports the SkunkScore" do
43-
_(reporter.update_status_message).must_include output
44-
_(reporter.update_status_message).must_include "Generated with Skunk v#{Skunk::VERSION}"
41+
it "reports a simple status message" do
42+
_(reporter.update_status_message).must_equal "Skunk analysis complete. Use --format console to see detailed output."
4543
end
4644
end
4745
end

test/lib/skunk/config_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def test_supported_format
7070
end
7171

7272
def test_supported_formats
73-
expected = %i[json html]
73+
expected = %i[json html console]
7474
assert_equal expected, Config.supported_formats
7575
end
7676

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
require "skunk/generators/console/simple"
6+
7+
module Skunk
8+
module Generator
9+
module Console
10+
class SimpleTest < Minitest::Test
11+
def setup
12+
@analysed_modules = create_simple_mock_collection
13+
@simple = Simple.new(@analysed_modules)
14+
end
15+
16+
def test_initializes_with_analysed_modules
17+
assert_equal @analysed_modules, @simple.instance_variable_get(:@analysed_modules)
18+
end
19+
20+
def test_render_includes_expected_content
21+
output = @simple.render
22+
23+
assert_includes output, "SkunkScore Total:"
24+
assert_includes output, "Modules Analysed:"
25+
assert_includes output, "SkunkScore Average:"
26+
assert_includes output, "Generated with Skunk"
27+
end
28+
29+
def test_render_includes_table_headers
30+
output = @simple.render
31+
32+
assert_includes output, "file"
33+
assert_includes output, "skunk_score"
34+
assert_includes output, "churn_times_cost"
35+
assert_includes output, "churn"
36+
assert_includes output, "cost"
37+
assert_includes output, "coverage"
38+
end
39+
40+
def test_headings_constant
41+
expected_headings = %w[file skunk_score churn_times_cost churn cost coverage]
42+
assert_equal expected_headings, Simple::HEADINGS
43+
end
44+
45+
end
46+
end
47+
end
48+
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
require "skunk/generators/console_report"
6+
7+
module Skunk
8+
module Generator
9+
class ConsoleReportTest < Minitest::Test
10+
def setup
11+
@analysed_modules = create_simple_mock_collection
12+
@console_report = ConsoleReport.new(@analysed_modules)
13+
end
14+
15+
def test_initializes_with_analysed_modules
16+
# Test that the console report was initialized with the analysed modules
17+
assert_equal @analysed_modules, @console_report.instance_variable_get(:@analysed_modules)
18+
end
19+
20+
def test_generator_returns_console_simple_instance
21+
generator = @console_report.send(:generator)
22+
assert_instance_of Skunk::Generator::Console::Simple, generator
23+
end
24+
25+
def test_generate_report_calls_generator_render
26+
# Test that generate_report calls the generator's render method
27+
generator = @console_report.send(:generator)
28+
29+
# Mock the generator to verify it's called
30+
mock_generator = Minitest::Mock.new
31+
mock_generator.expect :render, "test output"
32+
33+
@console_report.instance_variable_set(:@generator, mock_generator)
34+
35+
# Capture stdout to test the output
36+
output = capture_stdout do
37+
@console_report.generate_report
38+
end
39+
40+
assert_equal "test output\n", output
41+
mock_generator.verify
42+
end
43+
44+
end
45+
end
46+
end

0 commit comments

Comments
 (0)