teststats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 643dbc4cf307a2725c80e4269cf9447c25ccc518
4
+ data.tar.gz: 231167f3e71f14c8bc51aaa78c2b18b30769e120
5
+ SHA512:
6
+ metadata.gz: 7185d310751ba49eadd014f341539fa416b41f6543dda07bf05b0b4034ff1b15f1b920831e72652235fd5feca385933594d7ee0550ca748607430394685e66fa
7
+ data.tar.gz: 578d989ac8867828d428ec428b42b50422dff5277839d699ecc701b6975ebb8532fd981c3f731e88a4f6c40abfbd6b52ed335e02d5ebcb3d963592f16e66bfb3
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teststats.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Teststats
2
+
3
+ Test (history) analysis in a codebase.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'teststats'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install teststats
20
+
21
+ ## Usage
22
+
23
+ cd <your git repository root directory>
24
+ teststats count
25
+
26
+ instructions:
27
+
28
+ teststats
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
35
+
36
+ ## Contributing
37
+
38
+ Bug reports and pull requests are welcome on GitHub at https://github.com/xli/teststats.
39
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "teststats"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/teststats ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_path = File.expand_path('../../lib', __FILE__)
4
+ $:.unshift(lib_path)
5
+
6
+ require 'teststats/cli'
7
+ Teststats::CLI.start(ARGV)
@@ -0,0 +1,110 @@
1
+ require 'thor'
2
+ require 'teststats'
3
+ require 'json'
4
+ require 'erb'
5
+
6
+ module Teststats
7
+ class CLI < Thor
8
+ DEFAULTS = {
9
+ 'test_unit' => {
10
+ :pattern => '*_test.rb',
11
+ :directory => 'test',
12
+ :test_regex => /^\s+def test_/
13
+ },
14
+ 'rspec' => {
15
+ :pattern => '*_spec.rb',
16
+ :directory => 'spec',
17
+ :test_regex => /^\s+it ["']/
18
+ }
19
+ }
20
+ desc "count", "Test count growing stats. Notice, this command will checkout old revisions to count tests, recommend a clean repository to avoid problem."
21
+ option :framework, :banner => "Supports: test_unit and rspec, default to test_unit when root directory contains test directory, default to rspect when the root directory contains 'spec' directory"
22
+ option :pattern, :banner => "default to '*_test.rb' for test_unit, '*_spec.rb' for rspec"
23
+ option :directory, :banner => 'default to test for test_unit, spec for rspec'
24
+ option :repository, :default => Dir.pwd, :banner => "Your git repository root directory. Recommend run this script inside your git repository root directory"
25
+ option :output, :default => 'output', :banner => "Output file name"
26
+ option :output_format, :default => 'html', :banner => "html or text"
27
+ def count
28
+ Dir.chdir(options[:repository]) do
29
+ validate!
30
+ f = framework
31
+ current_branch = `git rev-parse --abbrev-ref HEAD`
32
+ puts "Working on branch #{current_branch}"
33
+ puts "List revisions"
34
+ rev_list = `git log --pretty=tformat:%H,%aI -- #{f.directory}`.split("\n")
35
+ puts "Found #{rev_list.size} revisions"
36
+
37
+ data = {}
38
+ rev_list.each do |rev|
39
+ hash, date = rev.split(',')
40
+ date = date.split('T')[0]
41
+ next if data.has_key?(date)
42
+
43
+ `git checkout -q -f #{hash}`
44
+ files = Dir[f.test_files]
45
+ puts "#{hash[0..8]} #{date} #{files.size} test files"
46
+ data[date] = files.map(&f.count).reduce(:+).to_i
47
+ end
48
+ `git checkout #{current_branch}`
49
+ output(data.to_a.sort_by{|d|d[0]})
50
+ end
51
+ end
52
+
53
+ private
54
+ def framework
55
+ name = options[:framework] || detect_framework
56
+ unless DEFAULTS.has_key?(name)
57
+ puts "Unsupported framework #{name.inspect}, options: #{DEFAULTS.keys.inspect}"
58
+ exit(1)
59
+ end
60
+ f = {:name => name}
61
+ DEFAULTS[name].each do |k, v|
62
+ f[k] = options[k] || v
63
+ end
64
+ f[:test_files] = [f[:directory], '**', f[:pattern]].join("/")
65
+ f[:count] = lambda {|file| File.read(file).split("\n").map {|l| l =~ f[:test_regex] ? 1 : 0}.reduce(:+).to_i}
66
+ OpenStruct.new(f)
67
+ end
68
+
69
+ def detect_framework
70
+ if File.directory?('test')
71
+ 'test_unit'
72
+ elsif File.directory?('spec') || File.directory?('specs')
73
+ 'rspec'
74
+ else
75
+ raise "Unknown test framework"
76
+ end
77
+ end
78
+
79
+ def output(data)
80
+ title = "#{Dir.pwd.split("/").last} Test Count History"
81
+ case options[:output_format]
82
+ when 'text'
83
+ output_data_file = "#{options[:output]}.txt"
84
+ puts "write data to file #{output_data_file}"
85
+ File.open(output_data_file, 'w') do |f|
86
+ f.write("##{title}\n")
87
+ f.write("#Date\tTest Count\n")
88
+ data.each do |date, count|
89
+ f.write("#{date}\t#{count}\n")
90
+ end
91
+ end
92
+ else
93
+ output_html_file = "#{options[:output]}.html"
94
+ puts "output #{output_html_file}"
95
+ data = data.map{|d| {:date => d[0], :count => d[1]}}
96
+ File.open(output_html_file, 'w') do |f|
97
+ erb = ERB.new(File.read(File.expand_path('../line_chart.html.erb', __FILE__)))
98
+ f.write(erb.result(binding))
99
+ end
100
+ end
101
+ end
102
+
103
+ def validate!
104
+ if !File.directory?('.git')
105
+ puts "#{options[:repository]} is not a Git repository root directory."
106
+ exit(1)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <style>
6
+ body {
7
+ font: 10px sans-serif;
8
+ }
9
+
10
+ .axis path,
11
+ .axis line {
12
+ fill: none;
13
+ stroke: #000;
14
+ shape-rendering: crispEdges;
15
+ }
16
+
17
+ .x.axis path {
18
+ display: none;
19
+ }
20
+
21
+ .line {
22
+ fill: none;
23
+ stroke: steelblue;
24
+ stroke-width: 1.5px;
25
+ }
26
+
27
+ </style>
28
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
29
+ </head>
30
+ <body>
31
+ <center><h1><%= title %></h1></center>
32
+ <script>
33
+ var yAxisLabel = 'Test Count';
34
+ var data = <%= data.to_json %>;
35
+ var margin = {top: 20, right: 50, bottom: 30, left: 50},
36
+ width = window.innerWidth - margin.left - margin.right,
37
+ height = 500 - margin.top - margin.bottom;
38
+
39
+ var parseDate = d3.time.format("%Y-%m-%d").parse;
40
+
41
+ var x = d3.time.scale()
42
+ .range([0, width]);
43
+
44
+ var y = d3.scale.linear()
45
+ .range([height, 0]);
46
+
47
+ var xAxis = d3.svg.axis()
48
+ .scale(x)
49
+ .orient("bottom");
50
+
51
+ var yAxis = d3.svg.axis()
52
+ .scale(y)
53
+ .orient("left");
54
+
55
+ var line = d3.svg.line()
56
+ .x(function(d) { return x(d.date); })
57
+ .y(function(d) { return y(d.count); });
58
+
59
+ var svg = d3.select("body").append("svg")
60
+ .attr("width", width + margin.left + margin.right)
61
+ .attr("height", height + margin.top + margin.bottom)
62
+ .append("g")
63
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
64
+
65
+ data.forEach(function(d) {
66
+ d.date = parseDate(d.date);
67
+ });
68
+
69
+ x.domain(d3.extent(data, function(d) { return d.date; }));
70
+ y.domain(d3.extent(data, function(d) { return d.count; }));
71
+
72
+ svg.append("g")
73
+ .attr("class", "x axis")
74
+ .attr("transform", "translate(0," + height + ")")
75
+ .call(xAxis);
76
+
77
+ svg.append("g")
78
+ .attr("class", "y axis")
79
+ .call(yAxis)
80
+ .append("text")
81
+ .attr("transform", "rotate(-90)")
82
+ .attr("y", 6)
83
+ .attr("dy", ".71em")
84
+ .style("text-anchor", "end")
85
+ .text(yAxisLabel);
86
+
87
+ svg.append("path")
88
+ .datum(data)
89
+ .attr("class", "line")
90
+ .attr("d", line);
91
+ </script>
92
+ </body>
93
+ </html>
@@ -0,0 +1,3 @@
1
+ module Teststats
2
+ VERSION = "0.1.0"
3
+ end
data/lib/teststats.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "teststats/version"
2
+
3
+ module Teststats
4
+ end
data/teststats.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'teststats/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "teststats"
8
+ spec.version = Teststats::VERSION
9
+ spec.authors = ["Xiao Li"]
10
+ spec.email = ["swing1979@gmail.com"]
11
+
12
+ spec.summary = %q{Test (history) analysis in a codebase.}
13
+ spec.homepage = 'https://github.com/xli/teststats'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "thor", "~> 0.19"
21
+ spec.add_dependency 'json', '~> 1.8.3'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.10"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: teststats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Xiao Li
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ description:
70
+ email:
71
+ - swing1979@gmail.com
72
+ executables:
73
+ - teststats
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - README.md
80
+ - Rakefile
81
+ - bin/console
82
+ - bin/setup
83
+ - exe/teststats
84
+ - lib/teststats.rb
85
+ - lib/teststats/cli.rb
86
+ - lib/teststats/line_chart.html.erb
87
+ - lib/teststats/version.rb
88
+ - teststats.gemspec
89
+ homepage: https://github.com/xli/teststats
90
+ licenses: []
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.4.5
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Test (history) analysis in a codebase.
112
+ test_files: []