rspec-profiler 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
@@ -0,0 +1,41 @@
1
+ h1. rspec-profiler
2
+
3
+ _Currently_ _tested_ _only_ _for_ _rspec-2.11_
4
+
5
+ The rspec-profiler is a custom formatter that adds functionality to the existing --profile option in
6
+ rspec. The rspec-profiler first groups tests together by their folder under the spec directory
7
+ (models, lib, controllers, etc...). Then the standard deviation is calculated. Any test within a
8
+ group that is 2 or more standard deviations away from the mean is listed.
9
+
10
+ There are downsides of course to doing it this way. For example, with a mean of .02 seconds and a
11
+ standard deviation of .01 seconds, a test that takes .04 seconds will be listed when perhaps one
12
+ wouldn't think a test that takes 0.04 seconds to complete to be in need of attention. I will simply
13
+ advise, as with any benchmark, to not take the results too seriously. Rather, you should use the
14
+ results as a way to identify tests that _may_ need to be looked at for performance issues. And, as
15
+ always, running the benchmark multiple times will give you a better sense of the tests that are
16
+ consistantly slow. A test may be benchmarked noticably slower in one trial due any number of reasons
17
+ but run faster in the next.
18
+
19
+ h2. Installation
20
+
21
+ 1. Put the profiler in your @Gemfile@
22
+
23
+ 2. When running your specs use:
24
+
25
+ bc. $ rspec --format Profiler -p spec
26
+
27
+ If for some reason rspec cannot find the Profiler, you case use the @-r@ option and provide the PATH
28
+ to @profiler.rb@.
29
+
30
+ Alternatively, you can make the Profiler formatter your default formatter by modifying your @.rspec@
31
+ file (the Profiler inherits from the Progress formatter, you know, the one that uses the green dots):
32
+
33
+ bc. --format Profiler
34
+
35
+ _Note_: The performance profile will not display unless you specify the @-p@ option when running
36
+ rspec. Additionally, when tests fail, the profile will not display which is consistant with how the
37
+ bundled profiler works as well.
38
+
39
+ _If you use Timecop_: If you use the timecop gem to freeze or change time be sure to also return the
40
+ time after each of your tests. Not doing so will make it appear as if your tests are taking either
41
+ far too long or have taken negative time to complete.
@@ -0,0 +1,6 @@
1
+ require 'rake'
2
+
3
+ task :default => :spec
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,90 @@
1
+ require 'rspec/core/formatters/progress_formatter'
2
+
3
+ module Math::Array
4
+ def sum
5
+ self.inject(0){ |accum, i| accum + i }
6
+ end
7
+
8
+ def mean
9
+ self.sum/self.length.to_f
10
+ end
11
+
12
+ def sample_variance
13
+ m = self.mean
14
+ sum = self.inject(0) { |accum, i| accum + (i - m) ** 2 }
15
+ sum / (self.length).to_f
16
+ end
17
+
18
+ def standard_deviation
19
+ return Math.sqrt(self.sample_variance)
20
+ end
21
+ end
22
+
23
+ class Profiler < RSpec::Core::Formatters::ProgressFormatter
24
+ def dump_profile
25
+ groups = {}
26
+ examples.each do |e|
27
+ e.location =~ /\/spec\//
28
+ key = $'.gsub(/\/.*$/,'').strip.to_sym
29
+ if groups.has_key? key
30
+ groups[key] = groups[key] << e
31
+ else
32
+ groups[key] = [e]
33
+ end
34
+ end
35
+
36
+ groups.each_key do |group_name|
37
+ print_report(groups[group_name.to_sym], group_name.to_s)
38
+ end
39
+ end
40
+
41
+ protected
42
+
43
+ def print_report(grouped_examples, group_name)
44
+ grouped_examples = grouped_examples.sort_by do |e|
45
+ e.execution_result[:run_time]
46
+ end.reverse
47
+
48
+ times = grouped_examples.map { |e| e.execution_result[:run_time] }
49
+ times.extend Math::Array
50
+ mean = times.mean
51
+ stddev = times.standard_deviation
52
+ k = 2
53
+ grouped_examples.reject! { |e| e.execution_result[:run_time] < (mean + k * stddev) }
54
+
55
+ output.puts "\n\nGroup: #{bold magenta(group_name.to_s.capitalize)}"
56
+ output.puts "#{bold red(grouped_examples.size)} of #{bold green(times.size)} spec(s) were 2 or greater standard deviations above the mean"
57
+ output.puts cyan "#{"Mean execution time:"} #{format_time(mean)}"
58
+ output.puts cyan "#{"Standard Deviation:"} #{"%.5f" % stddev}"
59
+
60
+ grouped_examples.each_with_index do |example, i|
61
+ location = example.location.match(/\/spec\/.*$/)[0]
62
+ output.puts cyan("#{i+1}.\t#{format_time(example.execution_result[:run_time])}") + white(" \t#{format_caller(location)}")
63
+ end
64
+ end
65
+
66
+ def format_time(duration)
67
+ if duration > 60
68
+ minutes = duration.to_i / 60
69
+ seconds = duration - minutes * 60
70
+
71
+ red "#{minutes}m #{format_seconds(seconds)}s"
72
+ elsif duration > 10
73
+ red "#{format_seconds(duration)}s"
74
+ elsif duration > 3
75
+ yellow "#{format_seconds(duration)}s"
76
+ else
77
+ "#{format_seconds(duration)}s"
78
+ end
79
+ end
80
+
81
+ def format_seconds(float)
82
+ precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION
83
+ sprintf("%.#{precision}f", float)
84
+ end
85
+
86
+ def cyan(text)
87
+ color(text, "\e[36m")
88
+ end
89
+
90
+ end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rspec-profiler"
3
+ s.version = "1.0.8"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.authors = ["Michael Blumberg"]
6
+ s.email = ["mblum14@gmail.com"]
7
+ s.homepage = "https://github.com/mblum14/rspec-profiler"
8
+ s.summary = %q{A better formatter for the rspec performance profile}
9
+ s.description = %q{A better formatter for the rspec performance profile}
10
+
11
+ s.rubyforge_project = "rspec-profiler"
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency('rspec', ["~> 2.8.0"])
19
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-profiler
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Blumberg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.8.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.8.0
30
+ description: A better formatter for the rspec performance profile
31
+ email:
32
+ - mblum14@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - README.textile
40
+ - Rakefile
41
+ - lib/profiler.rb
42
+ - rspec-profiler.gemspec
43
+ homepage: https://github.com/mblum14/rspec-profiler
44
+ licenses: []
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project: rspec-profiler
63
+ rubygems_version: 1.8.24
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: A better formatter for the rspec performance profile
67
+ test_files: []