defect-density-heatmap 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defect-density-heatmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-04 00:00:00.000000000Z
12
+ date: 2011-10-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70110389272640 !ruby/object:Gem::Requirement
16
+ requirement: &70143080302440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70110389272640
24
+ version_requirements: *70143080302440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: guard
27
- requirement: &70110389272220 !ruby/object:Gem::Requirement
27
+ requirement: &70143080302020 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,31 +32,15 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70110389272220
35
+ version_requirements: *70143080302020
36
36
  description: Generates a tag cloud based on project file churn.
37
37
  email:
38
38
  - bcarlso@gmail.com
39
- executables:
40
- - heatmap
39
+ executables: []
41
40
  extensions: []
42
41
  extra_rdoc_files: []
43
42
  files:
44
- - .gitignore
45
- - Gemfile
46
- - Guardfile
47
- - Rakefile
48
- - bin/heatmap
49
- - defect-density-heatmap.gemspec
50
- - lib/command_line_runner.rb
51
- - lib/defect-density-heatmap.rb
52
- - lib/heatmap.rb
53
- - lib/heatmap/version.rb
54
- - lib/heatmap_formatter.rb
55
- - readme.markdown
56
- - screenshot.png
57
- - spec/example-data.csv
58
- - spec/heatmap_formatter_spec.rb
59
- - spec/spec_helper.rb
43
+ - heatmap
60
44
  homepage: http://github.com/bcarlso/defect-density-heatmap
61
45
  licenses: []
62
46
  post_install_message:
@@ -81,7 +65,4 @@ rubygems_version: 1.8.6
81
65
  signing_key:
82
66
  specification_version: 3
83
67
  summary: Generates a 'heatmap' from files changed in the SCM system.
84
- test_files:
85
- - spec/example-data.csv
86
- - spec/heatmap_formatter_spec.rb
87
- - spec/spec_helper.rb
68
+ test_files: []
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.gem
2
- .bundle
3
- Gemfile.lock
4
- pkg/*
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in defect-density-heatmap.gemspec
4
- gemspec
data/Guardfile DELETED
@@ -1,8 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard 'rspec', :version => 2 do
5
- watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
8
- end
data/Rakefile DELETED
@@ -1,7 +0,0 @@
1
- require "bundler/gem_tasks"
2
-
3
- desc "Run all specs"
4
- Spec::Rake::SpecTask.new(:spec) do |t|
5
- t.spec_files = FileList['spec/**/*_spec.rb']
6
- t.spec_opts = ['--color']
7
- end
@@ -1,25 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "heatmap/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "defect-density-heatmap"
7
- s.version = Heatmap::VERSION
8
- s.authors = ["Brandon Carlson"]
9
- s.email = ["bcarlso@gmail.com"]
10
- s.homepage = "http://github.com/bcarlso/defect-density-heatmap"
11
- s.summary = %q{Generates a 'heatmap' from files changed in the SCM system.}
12
- s.description = %q{Generates a tag cloud based on project file churn.}
13
-
14
- s.rubyforge_project = "defect-density-heatmap"
15
-
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
20
-
21
- # specify any dependencies here; for example:
22
- s.add_development_dependency "rspec"
23
- s.add_development_dependency "guard"
24
- # s.add_runtime_dependency "rest-client"
25
- end
@@ -1,34 +0,0 @@
1
- require 'optparse'
2
- require 'heatmap_formatter'
3
-
4
- class CommandLineRunner
5
- def self.run
6
- options = {
7
- :input_stream => STDIN,
8
- :output_stream => STDOUT,
9
- :regular_expression => "(?<total>(\\d+)),(?<defects>(\\d+)),(?<filename>(.+))"
10
- }
11
-
12
- OptionParser.new do | opts |
13
- opts.banner = "Usage: heatmap [options]"
14
-
15
- opts.on("-r", "--record-format pattern", "Regular expression with named captures describing the record") do | regex |
16
- options[:regular_expression] = regex
17
- end
18
-
19
- opts.on("-f", "--file inputfile", "File containing commit data") do | filename, f2 |
20
- options[:input_stream] = File.new(filename, 'r')
21
- end
22
-
23
- opts.on("-o", "--outfile outputfile", "File to write output to") do | filename |
24
- options[:output_stream] = File.new(filename, 'w')
25
- end
26
- end.parse!
27
-
28
- formatter = HeatmapFormatter.new(options[:regular_expression],
29
- options[:input_stream],
30
- options[:output_stream])
31
-
32
- formatter.render
33
- end
34
- end
@@ -1,5 +0,0 @@
1
- require 'heatmap/version'
2
-
3
- module Heatmap
4
- # Your code goes here...
5
- end
@@ -1,5 +0,0 @@
1
- require "heatmap/version"
2
-
3
- module Heatmap
4
- # Your code goes here...
5
- end
@@ -1,3 +0,0 @@
1
- module Heatmap
2
- VERSION = "0.0.3"
3
- end
@@ -1,71 +0,0 @@
1
- class HeatmapFormatter
2
- def initialize(line_format, input_stream, output_stream)
3
- @output_stream = output_stream
4
-
5
- format = Regexp.new(line_format)
6
-
7
- items_to_render = parse(input_stream, format)
8
- @entries = items_to_render.sort do | first, second |
9
- File.basename(first[:filename]) <=> File.basename(second[:filename])
10
- end
11
-
12
- @floor, ceiling = (@entries.collect { | e | e[:total].to_i }).minmax
13
- @range = (ceiling - @floor)
14
- end
15
-
16
- def render
17
- tags = @entries.inject("") do | result, e |
18
- result + format_entry(e[:filename], e[:total].to_i, e[:defects])
19
- end
20
-
21
- html = <<-EOS
22
- <html>
23
- <head>
24
- <title>SCM Heatmap</title>
25
- <style type='text/css'>
26
- body { font-family: sans-serif; }
27
- ol li { display: inline; margin: 2px; }
28
- </style>
29
- </head>
30
- <body>
31
- <ol>
32
- #{tags}
33
- </ol>
34
- </body>
35
- </html>
36
- EOS
37
-
38
- @output_stream << html
39
- end
40
-
41
- def format_entry(filename, changes, defects)
42
- style = compute_style(changes, defects)
43
- title = "#{File.dirname(filename)} Changes: #{changes} Defects: #{defects}"
44
- "<li style='#{style}' title='#{title}'>#{File.basename(filename)} </li>"
45
- end
46
-
47
- def size_for(number)
48
- ((((number - @floor).to_f / @range) * 10).to_i * 3) + 6
49
- end
50
-
51
- private
52
-
53
- def parse(stream, format)
54
- stream.collect() do | line |
55
- format.match(line)
56
- end
57
- end
58
-
59
- def calculate_filename_color(total_changes, total_defects)
60
- percent_of_defects = total_defects.to_f / total_changes.to_f
61
- (percent_of_defects * 255).to_i
62
- end
63
-
64
- def compute_style(total_changes, total_defects)
65
- "font-size: #{size_for(total_changes)}; color: rgb(#{calculate_filename_color(total_changes,total_defects)}, 0, 0);"
66
- end
67
-
68
- def determine_relative_size_for(value)
69
- @size_calculator.size_for(value)
70
- end
71
- end
@@ -1,36 +0,0 @@
1
- Defect Density Heatmap - Visualizing Code Churn
2
- -----------------------------------------------
3
-
4
- This is the defect density heatmap and it is used to identify files in your codebase that change often as a result of working on features and fixing defects. Before using the heatmap generator some background information is needed.
5
-
6
- In our day to day development efforts we often commit code to our repository and give it a commit message. What if we add an additional piece of information to our commit message, such as a discriminator, identifying whether this change was related to a feature or defect? It can be anything, like starting the commit message with an 'F' or 'D'. If you're in corporate IT, your auditors would love it if you put ticket numbers in your commits (such as FEA-1234, DEF-1234)
7
-
8
- Take a simple example:
9
-
10
- # ListController.java, ColumnSorter.js, ListView.jsp, ListRepository.java
11
- git commit -m 'f Adding clickable column headings for sorting'
12
-
13
- # ListController.java, ColumnSorter.js
14
- git commit -m 'd Prevented NPE when invalid product code filter entered'
15
-
16
- # ListController.java, ListView.jsp
17
- git commit -m 'd Fix spelling error'
18
-
19
- This simple practice can give us some interesting insights into our code. Doing a bit of log crunching we can end up with a list of total changes and total defects a given file is associated with:
20
-
21
- # change-data.csv
22
- 1,0,src/main/java/com/example/ListRepository.java
23
- 3,2,src/main/java/com/example/ListController.java
24
- 2,1,src/main/webapp/ListView.jsp
25
- 2,1,src/main/webapp/js/ColumnSorter.js
26
-
27
- In this example, the first column is the total number of changes and the second column is the number of defects this file was involved with.
28
-
29
- Using the heatmap generator, we can create a tag cloud giving us a visualization of our code over time. The heatmap can be invoked in the usual ways:
30
-
31
- cat change-data.csv | heatmap > results.html
32
- heatmap -f change-data.csv -o results.html
33
-
34
- The command renders a tag cloud formatted as HTML. The larger the text, the more that source file has changed. The text color changes from black to red based on the ratio of defects to changes. The more defects, the more red you see. Big + Red = Bad
35
-
36
- ![Heatmap Screenshot](./screenshot.png)
Binary file
@@ -1,56 +0,0 @@
1
- 21,15,src/main/java/com/example/File1.java
2
- 8,2,src/main/java/com/example/File2.java
3
- 3,0,src/main/java/com/example/File3.java
4
- 23,10,src/main/java/com/example/File4.java
5
- 22,17,src/main/java/com/example/File5.java
6
- 21,13,src/main/java/com/example/File6.java
7
- 20,12,src/main/java/com/example/File7.java
8
- 16,8,src/main/java/com/example/File8.java
9
- 20,12,src/main/java/com/example/File9.java
10
- 15,9,src/main/java/com/example/File10.java
11
- 3,1,src/main/java/com/example/File11.java
12
- 3,3,src/main/java/com/example/File12.java
13
- 11,1,src/main/java/com/example/File13.java
14
- 9,7,src/main/java/com/example/File14.java
15
- 9,6,src/main/java/com/example/File15.java
16
- 15,1,src/main/java/com/example/File16.java
17
- 4,4,src/main/java/com/example/File17.java
18
- 2,0,src/main/java/com/example/File18.java
19
- 20,20,src/main/java/com/example/File19.java
20
- 4,0,src/main/java/com/example/File20.java
21
- 1,0,src/main/java/com/example/File21.java
22
- 11,0,src/main/java/com/example/File22.java
23
- 21,6,src/main/java/com/example/File23.java
24
- 8,5,src/main/java/com/example/File24.java
25
- 20,2,src/main/java/com/example/File25.java
26
- 11,8,src/main/java/com/example/File26.java
27
- 1,0,src/main/java/com/example/File27.java
28
- 22,14,src/main/java/com/example/File28.java
29
- 22,0,src/main/java/com/example/File29.java
30
- 17,5,src/main/java/com/example/File30.java
31
- 17,8,src/main/java/com/example/File31.java
32
- 24,7,src/main/java/com/example/File32.java
33
- 8,4,src/main/java/com/example/File33.java
34
- 9,0,src/main/java/com/example/File34.java
35
- 1,0,src/main/java/com/example/File35.java
36
- 14,1,src/main/java/com/example/File36.java
37
- 12,3,src/main/java/com/example/File37.java
38
- 24,5,src/main/java/com/example/File38.java
39
- 11,2,src/main/java/com/example/File39.java
40
- 8,4,src/main/java/com/example/File40.java
41
- 10,10,src/main/java/com/example/File41.java
42
- 19,4,src/main/java/com/example/File42.java
43
- 8,1,src/main/java/com/example/File43.java
44
- 8,2,src/main/java/com/example/File44.java
45
- 11,7,src/main/java/com/example/File45.java
46
- 21,4,src/main/java/com/example/File46.java
47
- 22,19,src/main/java/com/example/File47.java
48
- 12,8,src/main/java/com/example/File48.java
49
- 5,0,src/main/java/com/example/File49.java
50
- 19,6,src/main/java/com/example/File50.java
51
- 16,12,src/main/java/com/example/File51.java
52
- 3,1,src/main/java/com/example/File52.java
53
- 1,0,src/main/java/com/example/File53.java
54
- 1,1,src/main/java/com/example/File54.java
55
- 16,2,src/main/java/com/example/File55.java
56
- 5,3,src/main/java/com/example/File56.java
@@ -1,59 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe HeatmapFormatter do
4
- before(:each) do
5
- example_data = <<-EOS
6
- 3:0 src/main/resources/com/example/SomeFile.java: DE3981,DE4386
7
- 12:6 src/main/java/com/example/AnotherFile.java: US11743
8
- 6:6 src/main/java/com/example/YetAnotherFile.java: DE3317,DE4077,US12070
9
- EOS
10
-
11
- @input_stream = StringIO.new(example_data)
12
- @output_stream = StringIO.new
13
-
14
- @formatter = HeatmapFormatter.new("(?<total>(\\d+)):(?<defects>(\\d+)) (?<filename>(.+)):.+",
15
- @input_stream,
16
- @output_stream)
17
- end
18
-
19
- it "Orders the tag cloud based on filename" do
20
- @formatter.render
21
- @output_stream.string.should match(".*AnotherFile.*SomeFile.*YetAnotherFile")
22
- end
23
-
24
-
25
- it "Renders each file as a tag" do
26
- results = @formatter.format_entry 'path/to/SomeFile.java', 3, 0
27
- results.should match("<li style='.+'>SomeFile.java </li>")
28
- end
29
-
30
- it "Adds file details to the title attribute for display when hovered over" do
31
- results = @formatter.format_entry 'src/main/java/com/example/SomeFile.java', 3, 2
32
- results.should have_title_containing("src/main/java/com/example Changes: 3 Defects: 2")
33
- end
34
-
35
- it "Adjusts the font size of each tag relative to the number of changes in the file" do
36
- file_with( :changes => 3 ).should have_font_size(6)
37
- file_with( :changes => 6 ).should have_font_size(15)
38
- file_with( :changes => 12 ).should have_font_size(36)
39
- end
40
-
41
- it "Adjusts the font color of each tag based on the number of changes that were defects" do
42
- file_with( :changes => 3 ).should have_color('0, 0, 0')
43
-
44
- file_with( :changes => 3,
45
- :defects => 3 ).should have_color('255, 0, 0')
46
-
47
- file_with( :changes => 7,
48
- :defects => 5 ).should have_color('182, 0, 0')
49
- end
50
-
51
- it "Generates a range of font sizes based on a min/max" do
52
- @formatter.size_for(12).should == 36
53
- @formatter.size_for(11).should == 30
54
- @formatter.size_for(8).should == 21
55
- @formatter.size_for(7).should == 18
56
- @formatter.size_for(4).should == 9
57
- @formatter.size_for(3).should == 6
58
- end
59
- end
@@ -1,33 +0,0 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
-
4
- require 'rspec'
5
- require 'heatmap_formatter'
6
- require 'command_line_runner'
7
-
8
- RSpec.configure do | config |
9
- config.color_enabled = true
10
- end
11
-
12
- RSpec::Matchers.define :have_font_size do | expected |
13
- match do | actual |
14
- actual =~ Regexp.new(".*font-size: #{expected};.*")
15
- end
16
- end
17
-
18
- RSpec::Matchers.define :have_color do | expected |
19
- match do | actual |
20
- actual =~ Regexp.new(".*color: rgb\\(#{expected}\\);.*")
21
- end
22
- end
23
-
24
- RSpec::Matchers.define :have_title_containing do | expected |
25
- match do | actual |
26
- actual =~ Regexp.new(".*title='.*#{expected}.*'.*")
27
- end
28
- end
29
-
30
- def file_with(details)
31
- @formatter.format_entry 'SomeFile.java', details[:changes], details[:defects] || 0
32
- end
33
-