example_group_timer 0.0.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/.gitignore +18 -0
- data/Gemfile +2 -0
- data/HISTORY.md +5 -0
- data/LICENSE +22 -0
- data/README.md +98 -0
- data/Rakefile +1 -0
- data/example_group_timer.gemspec +26 -0
- data/lib/example_group_timer/formatter.rb +53 -0
- data/lib/example_group_timer/root_timed_group.rb +15 -0
- data/lib/example_group_timer/timed_group.rb +32 -0
- data/lib/example_group_timer/timed_item.rb +35 -0
- data/lib/example_group_timer/version.rb +3 -0
- data/lib/example_group_timer.rb +8 -0
- metadata +93 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Arjan van der Gaag
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# ExampleGroupTimer
|
2
|
+
|
3
|
+
A very simple formatter for RSpec 2 that outputs the time it took to run each
|
4
|
+
example and example group in your spec suite, including its share in the total
|
5
|
+
duration of its parent example group. Results are output sorted by share of
|
6
|
+
total runtime. This allows you to find what parts of the spec suite take a long
|
7
|
+
time to run, and where you should focus your efforts to optimize them.
|
8
|
+
|
9
|
+
This gem is still very much a work-in-progress and I am still looking into a
|
10
|
+
suitable report format. Also, the timing results are not as accurate as they
|
11
|
+
could be, but exact timing or profiling is not really the point -- the point is
|
12
|
+
to find spec suite bottlenecks.
|
13
|
+
|
14
|
+
## Example output
|
15
|
+
|
16
|
+
This is the output from using this formatter to run the specs of the
|
17
|
+
[Rpub](http://avdgaag.github.com/rpub) gem. For brevity's sake, the output has
|
18
|
+
been trimmed a little with `...`.
|
19
|
+
|
20
|
+
Total suite: 0.44007
|
21
|
+
Rpub::Epub::Content 0.10308 23.4%
|
22
|
+
with an empty book 0.05358 52.0%
|
23
|
+
should have xpath "/xmlns:package/xmlns:metadata/dc:ri 0.02777 51.8%
|
24
|
+
should have xpath "/xmlns:package[@unique-identifier=\ 0.00328 6.1%
|
25
|
+
should have xpath "/xmlns:package/xmlns:metadata/dc:ti 0.00325 6.1%
|
26
|
+
should have xpath "/xmlns:package/xmlns:metadata/dc:pu 0.00320 6.0%
|
27
|
+
...
|
28
|
+
when the book has a cover 0.02155 20.9%
|
29
|
+
should have xpath "/xmlns:package/xmlns:metadata/xmlns 0.00440 20.4%
|
30
|
+
should have xpath "/xmlns:package/xmlns:guide/xmlns:re 0.00433 20.1%
|
31
|
+
should have xpath "/xmlns:package/xmlns:manifest/xmlns 0.00431 20.0%
|
32
|
+
...
|
33
|
+
when the book has chapters 0.00813 7.9%
|
34
|
+
should have xpath "/xmlns:package/xmlns:manifest/xmlns 0.00412 50.7%
|
35
|
+
should have xpath "/xmlns:package/xmlns:spine[@toc=\"n 0.00386 47.5%
|
36
|
+
...
|
37
|
+
Rpub::Chapter 0.10110 23.0%
|
38
|
+
markdown parsing 0.07441 73.6%
|
39
|
+
to_html 0.07436 99.9%
|
40
|
+
should == "<p>foo</p>\n" 0.07425 99.9%
|
41
|
+
#outline 0.00912 9.0%
|
42
|
+
when there are no headings 0.00487 53.4%
|
43
|
+
outline 0.00374 76.8%
|
44
|
+
should be empty 0.00364 97.3%
|
45
|
+
outline 0.00105 21.6%
|
46
|
+
should have 0 elements 0.00097 92.4%
|
47
|
+
...
|
48
|
+
|
49
|
+
## Installation
|
50
|
+
|
51
|
+
Add these lines to your application's Gemfile:
|
52
|
+
|
53
|
+
group :test do
|
54
|
+
gem 'example_group_timer'
|
55
|
+
end
|
56
|
+
|
57
|
+
And then execute:
|
58
|
+
|
59
|
+
$ bundle
|
60
|
+
|
61
|
+
Or install it yourself as:
|
62
|
+
|
63
|
+
$ gem install example_group_timer
|
64
|
+
|
65
|
+
## Usage
|
66
|
+
|
67
|
+
From the command line or in your `.rspec` file, if you have added it to your Gemfile:
|
68
|
+
|
69
|
+
bundle exec rspec -f ExampleGroupTimer::Formatter
|
70
|
+
|
71
|
+
If installed manually, you will need to require the gem first:
|
72
|
+
|
73
|
+
rspec -r example_group_timer -f ExampleGroupTimer::Formatter
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
1. Fork it
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
80
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
81
|
+
5. Create new Pull Request
|
82
|
+
|
83
|
+
### Issues
|
84
|
+
|
85
|
+
Please report any issues, defects or suggestions in the [Github issue
|
86
|
+
tracker](https://github.com/avdgaag/example_group_timer/issues).
|
87
|
+
|
88
|
+
### What has changed?
|
89
|
+
|
90
|
+
See the [HISTORY](https://github.com/avdgaag/example_group_timer/blob/master/HISTORY.md) file for a detailed changelog.
|
91
|
+
|
92
|
+
### Credits
|
93
|
+
|
94
|
+
Created by: Arjan van der Gaag
|
95
|
+
URL: [http://arjanvandergaag.nl](http://arjanvandergaag.nl)
|
96
|
+
Project homepage: [https://github.com/avdgaag/example_group_timer](https://github.com/avdgaag/example_group_timer)
|
97
|
+
Date: april 2012
|
98
|
+
License: [MIT-license](https://github.com/avdgaag/example_group_timer/blob/master/LICENSE) (same as Ruby)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'example_group_timer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'example_group_timer'
|
8
|
+
gem.version = ExampleGroupTimer::VERSION
|
9
|
+
gem.authors = ['Arjan van der Gaag']
|
10
|
+
gem.email = ['arjan@arjanvandergaag.nl']
|
11
|
+
gem.description = %q{RSpec formatter to measure run times of individual example groups}
|
12
|
+
gem.summary = <<-EOS
|
13
|
+
Report the time it takes to run each example group in your spec suite, and what
|
14
|
+
share of its parent group runtime it represents. Useful for finding where to
|
15
|
+
optimize your spec suite first.
|
16
|
+
EOS
|
17
|
+
gem.homepage = 'https://github.com/avdgaag/example_group_timer'
|
18
|
+
|
19
|
+
gem.files = `git ls-files`.split($/)
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
|
+
gem.require_paths = ['lib']
|
23
|
+
|
24
|
+
gem.add_development_dependency 'rake'
|
25
|
+
gem.add_dependency 'rspec'
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ExampleGroupTimer
|
2
|
+
class Formatter < RSpec::Core::Formatters::ProgressFormatter
|
3
|
+
attr_reader :groups
|
4
|
+
attr_accessor :current_group
|
5
|
+
|
6
|
+
def initialize(output)
|
7
|
+
super
|
8
|
+
self.current_group = RootTimedGroup.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def example_group_started(group)
|
12
|
+
super
|
13
|
+
g = current_group.add_group(group)
|
14
|
+
self.current_group = g
|
15
|
+
end
|
16
|
+
|
17
|
+
def example_group_finished(group)
|
18
|
+
super
|
19
|
+
current_group.finish
|
20
|
+
self.current_group = current_group.parent
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_started(example)
|
24
|
+
super
|
25
|
+
current_group.add_example example
|
26
|
+
end
|
27
|
+
|
28
|
+
def example_pending(example)
|
29
|
+
super
|
30
|
+
current_group.finish_current_example
|
31
|
+
end
|
32
|
+
|
33
|
+
def example_failed(example)
|
34
|
+
super
|
35
|
+
current_group.finish_current_example
|
36
|
+
end
|
37
|
+
|
38
|
+
def example_passed(example)
|
39
|
+
super
|
40
|
+
current_group.finish_current_example
|
41
|
+
end
|
42
|
+
|
43
|
+
def stop
|
44
|
+
super
|
45
|
+
current_group.finish
|
46
|
+
end
|
47
|
+
|
48
|
+
def dump_summary(*args)
|
49
|
+
current_group.report
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ExampleGroupTimer
|
2
|
+
class TimedGroup < TimedItem
|
3
|
+
attr_reader :subgroups, :examples, :current_example
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
super
|
7
|
+
@subgroups, @examples = [], []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_group(group)
|
11
|
+
g = TimedGroup.new(group, self)
|
12
|
+
@subgroups << g
|
13
|
+
g
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_example(example)
|
17
|
+
@current_example = TimedItem.new(example, self)
|
18
|
+
examples << @current_example
|
19
|
+
end
|
20
|
+
|
21
|
+
def finish_current_example
|
22
|
+
@current_example.finish
|
23
|
+
@current_example = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def report
|
27
|
+
report_header
|
28
|
+
examples.sort_by { |o| o.duration }.reverse.each(&:report_header)
|
29
|
+
subgroups.sort_by { |o| o.duration }.reverse.each(&:report)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ExampleGroupTimer
|
2
|
+
class TimedItem
|
3
|
+
attr_reader :item, :parent
|
4
|
+
|
5
|
+
def initialize(item, parent = nil)
|
6
|
+
@item, @parent = item, parent
|
7
|
+
start
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
@started_at = Time.now
|
12
|
+
end
|
13
|
+
|
14
|
+
def finish
|
15
|
+
@finished_at = Time.now
|
16
|
+
end
|
17
|
+
|
18
|
+
def duration
|
19
|
+
'%.5f' % [@finished_at - @started_at]
|
20
|
+
end
|
21
|
+
|
22
|
+
def indent
|
23
|
+
parent.indent + 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def percentage
|
27
|
+
('%.1f%' % [(duration.to_f / parent.duration.to_f) * 100]).rjust(5)
|
28
|
+
end
|
29
|
+
|
30
|
+
def report_header
|
31
|
+
truncated = ((' ' * indent) + item.description.strip)[0..59].ljust(60)
|
32
|
+
puts "#{truncated} #{duration} #{percentage}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: example_group_timer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Arjan van der Gaag
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: RSpec formatter to measure run times of individual example groups
|
47
|
+
email:
|
48
|
+
- arjan@arjanvandergaag.nl
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- HISTORY.md
|
56
|
+
- LICENSE
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- example_group_timer.gemspec
|
60
|
+
- lib/example_group_timer.rb
|
61
|
+
- lib/example_group_timer/formatter.rb
|
62
|
+
- lib/example_group_timer/root_timed_group.rb
|
63
|
+
- lib/example_group_timer/timed_group.rb
|
64
|
+
- lib/example_group_timer/timed_item.rb
|
65
|
+
- lib/example_group_timer/version.rb
|
66
|
+
homepage: https://github.com/avdgaag/example_group_timer
|
67
|
+
licenses: []
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.8.24
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Report the time it takes to run each example group in your spec suite, and
|
90
|
+
what share of its parent group runtime it represents. Useful for finding where to
|
91
|
+
optimize your spec suite first.
|
92
|
+
test_files: []
|
93
|
+
has_rdoc:
|