-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from mocktools/develop
RSpec::Mock v0.3.0
- Loading branch information
Showing
22 changed files
with
1,234 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ languageSettings: | |
- GithubUser | ||
|
||
words: | ||
- Flexmock | ||
- bagage | ||
- bagages | ||
- bestwebua | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ languageSettings: | |
|
||
words: | ||
- Commiting | ||
- Flexmock | ||
- Trotsenko | ||
- Vladislav | ||
- bestwebua | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,6 @@ | |
|
||
exclude_paths: | ||
- '.circleci/**/*.rb' | ||
|
||
speedups: | ||
each_with_index_vs_while: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#!/usr/bin/env ruby | ||
# frozen_string_literal: true | ||
|
||
require 'colorize' | ||
require 'terminal-table' | ||
|
||
module RSpec | ||
module Mock | ||
module MigrationAnalytics | ||
class Cli | ||
class << self | ||
def call | ||
if ::ARGV.empty? | ||
print_usage | ||
exit 1 | ||
end | ||
|
||
begin | ||
verify_path(::ARGV[0]) | ||
rescue => error | ||
puts("\n❌ Error: #{error.message}".red) | ||
puts(error.backtrace) if ENV['DEBUG'] | ||
end | ||
end | ||
|
||
def verify_path(path) | ||
case | ||
when ::File.directory?(path) then verify_directory(path) | ||
else verify_file(path) | ||
end | ||
end | ||
|
||
private | ||
|
||
def print_usage | ||
puts('Usage: ruby cli.rb <path_to_spec_file_or_directory>'.yellow) | ||
puts("\nExamples:".blue) | ||
puts(' ruby cli.rb spec/models/user_spec.rb') | ||
puts(' ruby cli.rb spec/models/') | ||
puts(' ruby cli.rb spec/') | ||
end | ||
|
||
def verify_directory(dir_path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength | ||
results = [] | ||
stats = { | ||
total_files: 0, | ||
files_with_mocks: 0, | ||
total_flexmock_occurrences: 0, | ||
total_rspec_mock_occurrences: 0, | ||
files_with_mixed_usage: 0 | ||
} | ||
|
||
::Dir.glob("#{dir_path}/**/*_spec.rb").each do |file| | ||
stats[:total_files] += 1 | ||
result = RSpec::Mock::MigrationAnalytics::FileAnalyzer.call(file) | ||
|
||
next unless result[:has_mocks] | ||
stats[:files_with_mocks] += 1 | ||
stats[:total_flexmock_occurrences] += result[:flexmock_count] | ||
stats[:total_rspec_mock_occurrences] += result[:rspec_mock_count] | ||
stats[:files_with_mixed_usage] += 1 if result[:has_mixed_usage] | ||
results << result | ||
end | ||
|
||
print_summary(results, stats) | ||
end | ||
|
||
def verify_file(file_path) | ||
return puts("File not found: #{file_path}".red) unless ::File.exist?(file_path) | ||
return puts("Not a Ruby spec file: #{file_path}".yellow) unless file_path.end_with?('_spec.rb') | ||
|
||
print_file_result(RSpec::Mock::MigrationAnalytics::FileAnalyzer.call(file_path)) | ||
end | ||
|
||
def print_file_result(result) | ||
puts("\n=== Mock Usage Analysis: #{result[:file_path]} ===".blue) | ||
|
||
if result[:has_mocks] | ||
print_mock_statistics(result) | ||
print_locations_table('Flexmock Usage', result[:flexmock_locations]) if result[:flexmock_locations].any? | ||
print_locations_table('RSpec Mock Usage', result[:rspec_mock_locations]) if result[:rspec_mock_locations].any? | ||
else | ||
puts('✅ No mocking usage found'.green) | ||
end | ||
end | ||
|
||
def print_summary(results, stats) | ||
puts("\n=== Migration Status Report ===".blue) | ||
|
||
total_mocks = stats[:total_flexmock_occurrences] + stats[:total_rspec_mock_occurrences] | ||
migration_progress = | ||
total_mocks.zero? ? 100 : (stats[:total_rspec_mock_occurrences].to_f / total_mocks * 100).round(2) | ||
|
||
print_summary_table(stats, migration_progress) | ||
print_files_table(results) if results.any? | ||
end | ||
|
||
def print_mock_statistics(result) | ||
total_mocks = result[:flexmock_count] + result[:rspec_mock_count] | ||
migration_progress = (result[:rspec_mock_count].to_f / total_mocks * 100).round(2) | ||
puts( | ||
Terminal::Table.new do |t| | ||
t.add_row(['Total Mocks', total_mocks]) | ||
t.add_row(['Flexmock Usage', result[:flexmock_count]]) | ||
t.add_row(['RSpec Mock Usage', result[:rspec_mock_count]]) | ||
t.add_row(['Migration Progress', "#{migration_progress}%"]) | ||
end | ||
) | ||
end | ||
|
||
def print_locations_table(title, locations) | ||
return if locations.empty? | ||
|
||
puts("\n#{title}:".yellow) | ||
puts( | ||
Terminal::Table.new do |table| | ||
table.headings = %w[Line Type Content] | ||
locations.each do |loc| | ||
table.add_row(create_location_row(loc)) | ||
end | ||
end | ||
) | ||
end | ||
|
||
def create_location_row(loc) | ||
type_str = loc[:type].nil? ? 'unknown' : loc[:type] | ||
color = determine_color(loc[:type]) | ||
|
||
[ | ||
loc[:line_number].to_s.yellow, | ||
type_str.respond_to?(color) ? type_str.send(color) : type_str, | ||
loc[:content] | ||
] | ||
end | ||
|
||
def determine_color(type) | ||
case type | ||
when 'migration mock block' then :cyan | ||
when 'expect mock', 'allow mock' then :blue | ||
when 'verifying double' then :green | ||
else :light_white | ||
end | ||
end | ||
|
||
def print_summary_table(stats, migration_progress) | ||
puts( | ||
Terminal::Table.new do |table| | ||
table.add_row(['Total Spec Files', stats[:total_files]]) | ||
table.add_row(['Files with Mocks', stats[:files_with_mocks]]) | ||
table.add_row(['Files with Mixed Usage', stats[:files_with_mixed_usage]]) | ||
table.add_row(['Total Flexmock Occurrences', stats[:total_flexmock_occurrences]]) | ||
table.add_row(['Total RSpec Mock Occurrences', stats[:total_rspec_mock_occurrences]]) | ||
table.add_row(['Migration Progress', "#{migration_progress}%"]) | ||
end | ||
) | ||
end | ||
|
||
def print_files_table(results) | ||
puts("\n=== Files Requiring Migration ===".red) | ||
puts( | ||
Terminal::Table.new do |table| | ||
table.headings = ['File Path', 'Flexmock Count', 'RSpec Mock Count', 'Progress'] | ||
results.sort_by { |row| -row[:flexmock_count] }.each do |result| | ||
table.add_row(create_file_row(result)) | ||
end | ||
end | ||
) | ||
end | ||
|
||
def create_file_row(result) | ||
total = result[:flexmock_count] + result[:rspec_mock_count] | ||
progress = | ||
total.zero? ? 100 : (result[:rspec_mock_count].to_f / total * 100).round(2) | ||
[ | ||
result[:file_path], | ||
result[:flexmock_count], | ||
result[:rspec_mock_count], | ||
"#{progress}%" | ||
] | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# frozen_string_literal: true | ||
|
||
module RSpec | ||
module Mock | ||
module MigrationAnalytics | ||
class FileAnalyzer | ||
def self.call( | ||
file_path, | ||
flexmock_tracker = RSpec::Mock::MigrationAnalytics::Tracker::Flexmock.new, | ||
rspec_tracker = RSpec::Mock::MigrationAnalytics::Tracker::Rspec.new | ||
) | ||
new(file_path, flexmock_tracker, rspec_tracker).call | ||
end | ||
|
||
def initialize(file_path, flexmock_tracker, rspec_tracker) | ||
@file_path = file_path | ||
@flexmock_tracker = flexmock_tracker | ||
@rspec_tracker = rspec_tracker | ||
end | ||
|
||
def call | ||
build_analytics | ||
generate_report | ||
end | ||
|
||
private | ||
|
||
attr_reader :file_path, :flexmock_tracker, :rspec_tracker | ||
|
||
def build_analytics | ||
::File.read(file_path).split("\n").each_with_index do |line, index| | ||
line_number = index + 1 | ||
flexmock_tracker.scan_line(line, line_number) | ||
rspec_tracker.scan_line(line, line_number) | ||
end | ||
end | ||
|
||
%i[flexmock_tracker rspec_tracker].each do |method_name| | ||
target_method_name = :"#{method_name}_locations" | ||
define_method(target_method_name) { send(method_name).locations } | ||
define_method(:"#{target_method_name}_any?") { send(target_method_name).any? } | ||
end | ||
|
||
def generate_report | ||
{ | ||
file_path: file_path, | ||
flexmock_count: flexmock_tracker_locations.size, | ||
rspec_mock_count: rspec_tracker_locations.size, | ||
flexmock_locations: flexmock_tracker_locations, | ||
rspec_mock_locations: rspec_tracker_locations, | ||
has_mocks: flexmock_tracker_locations_any? || rspec_tracker_locations_any?, | ||
has_mixed_usage: flexmock_tracker_locations_any? && rspec_tracker_locations_any? | ||
} | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.