myronmarston-test_benchmarker 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/Manifest.txt +14 -0
- data/README.rdoc +48 -0
- data/Rakefile +42 -0
- data/lib/test_benchmarker.rb +7 -0
- data/lib/test_benchmarker/core_ext.rb +25 -0
- data/lib/test_benchmarker/test_benchmarks.rb +67 -0
- data/lib/test_benchmarker/test_suite.rb +22 -0
- data/test/test_core_ext.rb +32 -0
- data/test/test_helper.rb +3 -0
- data/test/test_test_benchmarker.rb +117 -0
- metadata +74 -0
data/CHANGELOG
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest.txt
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
lib
|
6
|
+
lib/test_benchmarker
|
7
|
+
lib/test_benchmarker.rb
|
8
|
+
lib/test_benchmarker/core_ext.rb
|
9
|
+
lib/test_benchmarker/test_benchmarks.rb
|
10
|
+
lib/test_benchmarker/test_suite.rb
|
11
|
+
test
|
12
|
+
test/test_core_ext.rb
|
13
|
+
test/test_helper.rb
|
14
|
+
test/test_test_benchmarker.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= test_benchmarker
|
2
|
+
|
3
|
+
* FIX (url)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
FIX (describe your package)
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIX (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
FIX (code sample of usage)
|
16
|
+
|
17
|
+
== REQUIREMENTS:
|
18
|
+
|
19
|
+
* FIX (list of requirements)
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
* FIX (sudo gem install, anything else)
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
(The MIT License)
|
28
|
+
|
29
|
+
Copyright (c) 2009 Myron Marston, Kashless.org
|
30
|
+
|
31
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
32
|
+
a copy of this software and associated documentation files (the
|
33
|
+
'Software'), to deal in the Software without restriction, including
|
34
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
35
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
36
|
+
permit persons to whom the Software is furnished to do so, subject to
|
37
|
+
the following conditions:
|
38
|
+
|
39
|
+
The above copyright notice and this permission notice shall be
|
40
|
+
included in all copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
43
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
44
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
45
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
46
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
47
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
48
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc "Run All Tests"
|
9
|
+
Rake::TestTask.new :test do |test|
|
10
|
+
test.test_files = ["test/**/*.rb"]
|
11
|
+
test.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc %{Update ".manifest" with the latest list of project filenames. Respect\
|
15
|
+
.gitignore by excluding everything that git ignores. Update `files` and\
|
16
|
+
`test_files` arrays in "*.gemspec" file if it's present.}
|
17
|
+
task :manifest do
|
18
|
+
list = Dir['**/*'].sort
|
19
|
+
spec_file = Dir['*.gemspec'].first
|
20
|
+
list -= [spec_file] if spec_file
|
21
|
+
|
22
|
+
if File.exist?('.gitignore')
|
23
|
+
File.read('.gitignore').each_line do |glob|
|
24
|
+
glob = glob.chomp.sub(/^\//, '')
|
25
|
+
list -= Dir[glob]
|
26
|
+
list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob)
|
27
|
+
puts "excluding #{glob}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if spec_file
|
32
|
+
spec = File.read spec_file
|
33
|
+
spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
|
34
|
+
assignment = $1
|
35
|
+
bunch = $2 ? list.grep(/^test\//) : list
|
36
|
+
'%s%%w(%s)' % [assignment, bunch.join(' ')]
|
37
|
+
end
|
38
|
+
|
39
|
+
File.open(spec_file, 'w') {|f| f << spec }
|
40
|
+
end
|
41
|
+
File.open('manifest.txt', 'w') {|f| f << list.join("\n") }
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class TestBenchmarker::ClassNotFoundError < StandardError
|
2
|
+
attr_accessor :class_str
|
3
|
+
def initialize(class_str)
|
4
|
+
@class_str = class_str
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class String
|
9
|
+
# similar to ActiveSupports constantize, but doesn't require the use of active support.
|
10
|
+
def to_class
|
11
|
+
ObjectSpace.each_object(Class) do |klass|
|
12
|
+
return klass if klass.to_s == self
|
13
|
+
end
|
14
|
+
|
15
|
+
raise TestBenchmarker::ClassNotFoundError.new(self), "A class matching '#{self}' could not be found"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Class
|
20
|
+
def is_subclass_of?(klass)
|
21
|
+
return false if self == Object && klass != Object
|
22
|
+
return true if self == klass
|
23
|
+
return self.superclass.is_subclass_of?(klass)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module TestBenchmarker
|
4
|
+
class TestBenchmark
|
5
|
+
attr_reader :test_class, :test_name, :benchmark
|
6
|
+
|
7
|
+
def initialize(test_class, test_name, benchmark)
|
8
|
+
@test_class, @test_name, @benchmark = test_class, test_name, benchmark
|
9
|
+
TestBenchmarks.add(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestBenchmarks
|
14
|
+
def self.clear
|
15
|
+
@@classes = {}
|
16
|
+
@@tests = []
|
17
|
+
end
|
18
|
+
|
19
|
+
self.clear
|
20
|
+
|
21
|
+
def self.add(benchmark)
|
22
|
+
test_class = benchmark.test_class
|
23
|
+
|
24
|
+
# ignore some bogus test classes that get passed here when run in the context of a rails app...
|
25
|
+
return if test_class =~ /(rake_test_loader|::TestCase|::IntegrationTest)/
|
26
|
+
|
27
|
+
begin
|
28
|
+
test_class = test_class.to_class
|
29
|
+
rescue TestBenchmarker::ClassNotFoundError
|
30
|
+
return
|
31
|
+
end
|
32
|
+
return unless test_class.is_subclass_of?(Test::Unit::TestCase)
|
33
|
+
|
34
|
+
@@classes[test_class] ||= OpenStruct.new
|
35
|
+
@@classes[test_class].benchmarks ||= []
|
36
|
+
@@classes[test_class].benchmarks << benchmark
|
37
|
+
@@tests << benchmark
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.print_results
|
41
|
+
return if @@classes.nil? || @@classes.size == 0
|
42
|
+
|
43
|
+
benchmark_attr = :real
|
44
|
+
|
45
|
+
class_benchmarks = []
|
46
|
+
@@classes.each do |test_class, obj|
|
47
|
+
obj.test_count = obj.benchmarks.size
|
48
|
+
obj.sum = obj.benchmarks.inject(0) {|sum, bmark| sum + bmark.benchmark.send(benchmark_attr)}
|
49
|
+
obj.avg = obj.sum / obj.test_count
|
50
|
+
obj.test_class = test_class
|
51
|
+
class_benchmarks << obj unless obj.benchmarks.nil? || obj.benchmarks.size == 0
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "\n\n#{'=' * 27} Class Benchmark Results #{'=' * 27}"
|
55
|
+
class_benchmarks.sort {|a, b| b.avg <=> a.avg}.each_with_index do |cb, i|
|
56
|
+
puts "#{i + 1}.#{' ' * (4 - (i + 1).to_s.length)} #{format("%.3f", cb.avg)} secs avg time, #{format("%.3f", cb.sum)} secs total time, #{cb.test_count} tests for: #{cb.test_class.to_s}"
|
57
|
+
end
|
58
|
+
puts "#{'=' * 79}\n\n"
|
59
|
+
|
60
|
+
puts "\n\n#{'=' * 28} Test Benchmark Results #{'=' * 28}"
|
61
|
+
@@tests.sort {|a, b| b.benchmark.send(benchmark_attr) <=> a.benchmark.send(benchmark_attr)}.each_with_index do |t, i|
|
62
|
+
puts "#{i + 1}.#{' ' * (4 - (i + 1).to_s.length)} #{format("%.3f", t.benchmark.real)} secs total time for: #{t.test_name}"
|
63
|
+
end
|
64
|
+
puts "#{'=' * 80}\n\n"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
if ENV['BENCHMARK_TESTS']
|
4
|
+
class Test::Unit::TestSuite
|
5
|
+
@@run_count = 0
|
6
|
+
|
7
|
+
def run(result, &progress_block)
|
8
|
+
@@run_count += 1
|
9
|
+
begin
|
10
|
+
yield(STARTED, name)
|
11
|
+
@tests.each do |test|
|
12
|
+
TestBenchmarker::TestBenchmark.new(self.name, test.name, Benchmark.measure { test.run(result, &progress_block) })
|
13
|
+
end
|
14
|
+
yield(FINISHED, name)
|
15
|
+
ensure
|
16
|
+
@@run_count -= 1
|
17
|
+
# print the results as we're exiting the very last test run...
|
18
|
+
TestBenchmarker::TestBenchmarks.print_results if @@run_count == 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class Foo; end
|
4
|
+
class FooSubclass < Foo; end
|
5
|
+
class FooSubSubclass < FooSubclass; end
|
6
|
+
class Bar; end
|
7
|
+
|
8
|
+
class TestCoreExt < Test::Unit::TestCase
|
9
|
+
def test_string_to_class
|
10
|
+
assert_equal TestCoreExt, 'TestCoreExt'.to_class
|
11
|
+
assert_equal FooSubSubclass, 'FooSubSubclass'.to_class
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_string_to_class_not_found
|
15
|
+
assert_raise TestBenchmarker::ClassNotFoundError do
|
16
|
+
'This it not the name of a class!'.to_class
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_class_is_subclass_of
|
21
|
+
assert FooSubclass.is_subclass_of?(Foo)
|
22
|
+
assert FooSubclass.is_subclass_of?(Object)
|
23
|
+
|
24
|
+
assert FooSubSubclass.is_subclass_of?(FooSubclass)
|
25
|
+
assert FooSubSubclass.is_subclass_of?(Foo)
|
26
|
+
assert FooSubSubclass.is_subclass_of?(Object)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_class_is_not_subclass_of
|
30
|
+
assert !Bar.is_subclass_of?(Foo)
|
31
|
+
end
|
32
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class Foo; end
|
4
|
+
class Class1 < Test::Unit::TestCase
|
5
|
+
def test_truth; end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Class2 < Test::Unit::TestCase
|
9
|
+
def test_truth; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Class3 < Test::Unit::TestCase
|
13
|
+
def test_truth; end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Class4; end
|
17
|
+
|
18
|
+
class TestTestBenchmarker < Test::Unit::TestCase
|
19
|
+
def setup
|
20
|
+
1.upto(3) do |class_speed|
|
21
|
+
1.upto(3) do |test_speed|
|
22
|
+
speed = class_speed * 0.01 + test_speed * 0.001
|
23
|
+
TestBenchmarker::TestBenchmark.new("Class#{class_speed}", "test_#{test_speed} (Class#{class_speed})", ::Benchmark.measure { sleep speed })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
TestBenchmarker::TestBenchmark.new("Class4", "test_1 (Class4)", ::Benchmark.measure { sleep 0.01 })
|
28
|
+
|
29
|
+
@benchmarked_classes = TestBenchmarker::TestBenchmarks.send(:class_variable_get, '@@classes')
|
30
|
+
@benchmarked_tests = TestBenchmarker::TestBenchmarks.send(:class_variable_get, '@@tests').map{ |t| t.test_name }
|
31
|
+
@out, @err = util_capture { TestBenchmarker::TestBenchmarks.print_results }
|
32
|
+
end
|
33
|
+
|
34
|
+
def teardown
|
35
|
+
TestBenchmarker::TestBenchmarks.clear
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_has_expected_benchmarked_classes
|
39
|
+
assert_equal 3, @benchmarked_classes.keys.size
|
40
|
+
|
41
|
+
assert @benchmarked_classes.keys.include?(Class1)
|
42
|
+
assert @benchmarked_classes.keys.include?(Class2)
|
43
|
+
assert @benchmarked_classes.keys.include?(Class3)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_does_not_have_classes_not_descended_from_test_unit_testcase
|
47
|
+
assert !@benchmarked_classes.keys.include?(Class4)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_has_expected_benchmarked_tests
|
51
|
+
assert_equal 9, @benchmarked_tests.size
|
52
|
+
|
53
|
+
assert @benchmarked_tests.include?('test_1 (Class1)')
|
54
|
+
assert @benchmarked_tests.include?('test_2 (Class1)')
|
55
|
+
assert @benchmarked_tests.include?('test_3 (Class1)')
|
56
|
+
assert @benchmarked_tests.include?('test_1 (Class2)')
|
57
|
+
assert @benchmarked_tests.include?('test_2 (Class2)')
|
58
|
+
assert @benchmarked_tests.include?('test_3 (Class2)')
|
59
|
+
assert @benchmarked_tests.include?('test_1 (Class3)')
|
60
|
+
assert @benchmarked_tests.include?('test_2 (Class3)')
|
61
|
+
assert @benchmarked_tests.include?('test_3 (Class3)')
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_does_not_have_tests_not_descended_from_test_unit_testcase
|
65
|
+
assert !@benchmarked_tests.include?("test_1 (Class4)")
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_class_benchmark_results
|
69
|
+
# should be in order from slowest to fastest
|
70
|
+
assert_match class_benchmark_regex('Class3', 1), @out
|
71
|
+
assert_match class_benchmark_regex('Class2', 2), @out
|
72
|
+
assert_match class_benchmark_regex('Class1', 3), @out
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_test_benchmark_results
|
76
|
+
# should be in order from slowest to fastest
|
77
|
+
assert_match test_benchmark_regex('test_3 (Class3)', 1), @out
|
78
|
+
assert_match test_benchmark_regex('test_2 (Class3)', 2), @out
|
79
|
+
assert_match test_benchmark_regex('test_1 (Class3)', 3), @out
|
80
|
+
assert_match test_benchmark_regex('test_3 (Class2)', 4), @out
|
81
|
+
assert_match test_benchmark_regex('test_2 (Class2)', 5), @out
|
82
|
+
assert_match test_benchmark_regex('test_1 (Class2)', 6), @out
|
83
|
+
assert_match test_benchmark_regex('test_3 (Class1)', 7), @out
|
84
|
+
assert_match test_benchmark_regex('test_2 (Class1)', 8), @out
|
85
|
+
assert_match test_benchmark_regex('test_1 (Class1)', 9), @out
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# borrowed from zentest assertions...
|
91
|
+
def util_capture
|
92
|
+
require 'stringio'
|
93
|
+
orig_stdout = $stdout.dup
|
94
|
+
orig_stderr = $stderr.dup
|
95
|
+
captured_stdout = StringIO.new
|
96
|
+
captured_stderr = StringIO.new
|
97
|
+
$stdout = captured_stdout
|
98
|
+
$stderr = captured_stderr
|
99
|
+
yield
|
100
|
+
captured_stdout.rewind
|
101
|
+
captured_stderr.rewind
|
102
|
+
return captured_stdout.string, captured_stderr.string
|
103
|
+
ensure
|
104
|
+
$stdout = orig_stdout
|
105
|
+
$stderr = orig_stderr
|
106
|
+
end
|
107
|
+
|
108
|
+
def class_benchmark_regex(class_name, slowness_ranking)
|
109
|
+
# http://rubular.com/regexes/6815
|
110
|
+
/^#{slowness_ranking}\.\s+[\d\.]+ secs avg time, [\d\.]+ secs total time, [\d]+ tests for: #{Regexp.escape(class_name)}$/
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_benchmark_regex(test_name, slowness_ranking)
|
114
|
+
# http://rubular.com/regexes/6816
|
115
|
+
/^#{slowness_ranking}.\s+[\d\.]+ secs total time for: #{Regexp.escape(test_name)}$/
|
116
|
+
end
|
117
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: myronmarston-test_benchmarker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Myron Marston
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-27 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: myron.marston@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- CHANGELOG
|
27
|
+
- Manifest.txt
|
28
|
+
- README.rdoc
|
29
|
+
- Rakefile
|
30
|
+
- lib
|
31
|
+
- lib/test_benchmarker
|
32
|
+
- lib/test_benchmarker.rb
|
33
|
+
- lib/test_benchmarker/core_ext.rb
|
34
|
+
- lib/test_benchmarker/test_benchmarks.rb
|
35
|
+
- lib/test_benchmarker/test_suite.rb
|
36
|
+
- test
|
37
|
+
- test/test_core_ext.rb
|
38
|
+
- test/test_helper.rb
|
39
|
+
- test/test_test_benchmarker.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/myronmarston/test_benchmarker
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- --main
|
45
|
+
- README.rdoc
|
46
|
+
- --title
|
47
|
+
- TestBenchmarker Documentation
|
48
|
+
- --charset
|
49
|
+
- utf-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.2.0
|
68
|
+
signing_key:
|
69
|
+
specification_version: 2
|
70
|
+
summary: A tool for benchmarking ruby Test::Unit tests
|
71
|
+
test_files:
|
72
|
+
- test/test_core_ext.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
- test/test_test_benchmarker.rb
|