myronmarston-test_benchmarker 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|