Guest User

Untitled

a guest
Mar 8th, 2018
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.74 KB | None | 0 0
  1. namespace :spec do
  2. desc "Report code statistics on the application and specs code"
  3. task :stats => "spec:stats:setup" do
  4. stats_directories = {
  5. "Specs" => "spec",
  6. "Application" => "lib"
  7. }.map {|name, dir| [name, "#{Dir.pwd}/#{dir}"]}
  8. SpecStatistics.new(*stats_directories).to_s
  9. end
  10.  
  11. namespace :stats do
  12. task :setup do
  13. class CodeStatistics #:nodoc:
  14.  
  15. TEST_TYPES = %w(Units Functionals Unit\ tests Functional\ tests Integration\ tests)
  16.  
  17. def initialize(*pairs)
  18. @pairs = pairs
  19. @statistics = calculate_statistics
  20. @total = calculate_total if pairs.length > 1
  21. end
  22.  
  23. def to_s
  24. print_header
  25. @pairs.each { |pair| print_line(pair.first, @statistics[pair.first]) }
  26. print_splitter
  27.  
  28. if @total
  29. print_line("Total", @total)
  30. print_splitter
  31. end
  32.  
  33. print_code_test_stats
  34. end
  35.  
  36. private
  37. def calculate_statistics
  38. @pairs.inject({}) { |stats, pair| stats[pair.first] = calculate_directory_statistics(pair.last); stats }
  39. end
  40.  
  41. def calculate_directory_statistics(directory, pattern = /.*\.rb$/)
  42. stats = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
  43.  
  44. Dir.foreach(directory) do |file_name|
  45. if File.stat(directory + "/" + file_name).directory? and (/^\./ !~ file_name)
  46. newstats = calculate_directory_statistics(directory + "/" + file_name, pattern)
  47. stats.each { |k, v| stats[k] += newstats[k] }
  48. end
  49.  
  50. next unless file_name =~ pattern
  51.  
  52. f = File.open(directory + "/" + file_name)
  53.  
  54. while line = f.gets
  55. stats["lines"] += 1
  56. stats["classes"] += 1 if line =~ /class [A-Z]/
  57. stats["methods"] += 1 if line =~ /def [a-z]/
  58. stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
  59. end
  60. end
  61.  
  62. stats
  63. end
  64.  
  65. def calculate_total
  66. total = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
  67. @statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
  68. total
  69. end
  70.  
  71. def calculate_code
  72. code_loc = 0
  73. @statistics.each { |k, v| code_loc += v['codelines'] unless TEST_TYPES.include? k }
  74. code_loc
  75. end
  76.  
  77. def calculate_tests
  78. test_loc = 0
  79. @statistics.each { |k, v| test_loc += v['codelines'] if TEST_TYPES.include? k }
  80. test_loc
  81. end
  82.  
  83. def print_header
  84. print_splitter
  85. puts "| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |"
  86. print_splitter
  87. end
  88.  
  89. def print_splitter
  90. puts "+----------------------+-------+-------+---------+---------+-----+-------+"
  91. end
  92.  
  93. def print_line(name, statistics)
  94. m_over_c = (statistics["methods"] / statistics["classes"]) rescue m_over_c = 0
  95. loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue loc_over_m = 0
  96.  
  97. start = if TEST_TYPES.include? name
  98. "| #{name.ljust(20)} "
  99. else
  100. "| #{name.ljust(20)} "
  101. end
  102.  
  103. puts start +
  104. "| #{statistics["lines"].to_s.rjust(5)} " +
  105. "| #{statistics["codelines"].to_s.rjust(5)} " +
  106. "| #{statistics["classes"].to_s.rjust(7)} " +
  107. "| #{statistics["methods"].to_s.rjust(7)} " +
  108. "| #{m_over_c.to_s.rjust(3)} " +
  109. "| #{loc_over_m.to_s.rjust(5)} |"
  110. end
  111.  
  112. def print_code_test_stats
  113. code = calculate_code
  114. tests = calculate_tests
  115.  
  116. puts " Code LOC: #{code} Test LOC: #{tests} Code to Test Ratio: 1:#{sprintf("%.1f", tests.to_f/code)}"
  117. puts ""
  118. end
  119. end
  120. class SpecStatistics < CodeStatistics
  121.  
  122. TEST_TYPES << "Specs"
  123.  
  124. private
  125. def calculate_directory_statistics(directory, pattern = /.*\.rb$/)
  126. stats = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0, "specs" => 0, "behaviors" => 0 }
  127.  
  128. Dir.foreach(directory) do |file_name|
  129. if File.stat(directory + "/" + file_name).directory? and (/^\./ !~ file_name)
  130. newstats = calculate_directory_statistics(directory + "/" + file_name, pattern)
  131. stats.each { |k, v| stats[k] += newstats[k] }
  132. end
  133.  
  134. next unless file_name =~ pattern
  135.  
  136. f = File.open(directory + "/" + file_name)
  137.  
  138. while line = f.gets
  139. stats["lines"] += 1
  140. stats["classes"] += 1 if line =~ /class [A-Z]/
  141. stats["methods"] += 1 if line =~ /def [a-z]/
  142. stats["specs"] += 1 if line.strip =~ /^it.*(do|\{)$/
  143. stats["behaviors"] += 1 if line =~ /describe.*(do|\{)$/
  144. stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
  145. end
  146. end
  147.  
  148. stats
  149. end
  150.  
  151. def calculate_total
  152. total = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0, "specs" => 0, "behaviors" => 0 }
  153. @statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
  154. total
  155. end
  156.  
  157. def print_header
  158. print_splitter
  159. puts "| Name | Lines | LOC | Classes | Methods | Behaviors | Specifications | M/C | LOC/M | S/B |"
  160. print_splitter
  161. end
  162.  
  163. def print_splitter
  164. puts "+----------------------+-------+-------+---------+---------+-----------+----------------+-----+-------+-----+"
  165. end
  166.  
  167. def print_line(name, statistics)
  168. m_over_c = (statistics["methods"] / statistics["classes"]) rescue 0
  169. loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue 0
  170.  
  171. s_over_b = (statistics["specs"] / statistics["behaviors"]) rescue 0
  172.  
  173. start = TEST_TYPES.include?(name) ? "| #{name.ljust(20)} " : "| #{name.ljust(20)} "
  174.  
  175. puts start +
  176. "| #{statistics["lines"].to_s.rjust(5)} " +
  177. "| #{statistics["codelines"].to_s.rjust(5)} " +
  178. "| #{statistics["classes"].to_s.rjust(7)} " +
  179. "| #{statistics["methods"].to_s.rjust(7)} " +
  180. "| #{statistics["behaviors"].to_s.rjust(10)}" +
  181. "| #{statistics["specs"].to_s.rjust(15)}" +
  182. "| #{m_over_c.to_s.rjust(3)} " +
  183. "| #{loc_over_m.to_s.rjust(6)}" +
  184. "| #{s_over_b.to_s.rjust(3)} |"
  185. end
  186. end
  187. end
  188. end
  189. end
Add Comment
Please, Sign In to add comment