elapse 0.1.0
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 +12 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -0
- data/MIT-LICENSE +20 -0
- data/README.md +119 -0
- data/Rakefile +7 -0
- data/elapse.gemspec +22 -0
- data/lib/elapse.rb +88 -0
- data/lib/elapse/instance.rb +112 -0
- data/lib/elapse/stopwatch.rb +68 -0
- data/lib/elapse/version.rb +4 -0
- data/spec/elapse/instance_spec.rb +29 -0
- data/spec/elapse/spec_helper.rb +3 -0
- data/spec/elapse/stopwatch_spec.rb +104 -0
- data/spec/elapse_spec.rb +14 -0
- data/spec/shared_examples.rb +169 -0
- data/spec/spec_helper.rb +30 -0
- metadata +86 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
elapse (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
rspec (2.8.0)
|
11
|
+
rspec-core (~> 2.8.0)
|
12
|
+
rspec-expectations (~> 2.8.0)
|
13
|
+
rspec-mocks (~> 2.8.0)
|
14
|
+
rspec-core (2.8.0)
|
15
|
+
rspec-expectations (2.8.0)
|
16
|
+
diff-lcs (~> 1.1.2)
|
17
|
+
rspec-mocks (2.8.0)
|
18
|
+
yard (0.7.5)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
elapse!
|
25
|
+
rspec
|
26
|
+
yard
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Alex Fortuna
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
Elapsed time measurement tool
|
3
|
+
=============================
|
4
|
+
|
5
|
+
Introduction
|
6
|
+
------------
|
7
|
+
|
8
|
+
`Elapse` is a simple tool to measure time taken by various parts of your program.
|
9
|
+
|
10
|
+
|
11
|
+
Setup
|
12
|
+
-----
|
13
|
+
|
14
|
+
~~~
|
15
|
+
$ gem install elapse
|
16
|
+
~~~
|
17
|
+
|
18
|
+
, or via Bundler's `Gemfile`:
|
19
|
+
|
20
|
+
~~~
|
21
|
+
gem "elapse"
|
22
|
+
#gem "elapse", :git => "git://github.com/dadooda/elapse.git" # Edge version.
|
23
|
+
~~~
|
24
|
+
|
25
|
+
|
26
|
+
Usage
|
27
|
+
-----
|
28
|
+
|
29
|
+
The most common use is the "stacked" (or "unnamed") mode. In stacked mode you invoke `Elapse.start` and `Elapse.took` without arguments:
|
30
|
+
|
31
|
+
~~~
|
32
|
+
puts "Fetching page (url:'#{url}')"; Elapse.start
|
33
|
+
content = open(url).read
|
34
|
+
puts "Fetching page ok (took:%.2fs)" % Elapse.took
|
35
|
+
~~~
|
36
|
+
|
37
|
+
In stacked mode time is **pushed to the stack** on `Elapse.start` and **popped from the stack** on `Elapse.took`/`Elapse.stop`. Thus you can nest unnamed measurements as deep as you like:
|
38
|
+
|
39
|
+
~~~
|
40
|
+
puts "Processing"; Elapse.start
|
41
|
+
puts "Loading data"; Elapse.start
|
42
|
+
load_data
|
43
|
+
puts "Loading data ok (took:%.2fs)" % Elapse.took
|
44
|
+
|
45
|
+
puts "Converting data"; Elapse.start
|
46
|
+
process_data
|
47
|
+
puts "Converting data ok (took:%.2fs)" % Elapse.took
|
48
|
+
puts "Processing ok (took:%.2fs)" % Elapse.took
|
49
|
+
|
50
|
+
# Output:
|
51
|
+
|
52
|
+
Processing
|
53
|
+
Loading data
|
54
|
+
Loading data ok (took:2.00s)
|
55
|
+
Converting data
|
56
|
+
Converting data ok (took:3.00s)
|
57
|
+
Processing ok (took:5.00s)
|
58
|
+
~~~
|
59
|
+
|
60
|
+
"Named" mode. See the stopwatch name argument to `Elapse.start`, `Elapse.stop` and `Elapse.took`:
|
61
|
+
|
62
|
+
~~~
|
63
|
+
Elapse.start(:load_data)
|
64
|
+
load_data
|
65
|
+
Elapse.stop(:load_data)
|
66
|
+
|
67
|
+
Elapse.start(:process_data)
|
68
|
+
process_data
|
69
|
+
Elapse.stop(:process_data)
|
70
|
+
|
71
|
+
puts "Time took:"
|
72
|
+
[:load_data, :process_data].each do |stopwatch|
|
73
|
+
puts "* #{stopwatch}: %.2fs" % Elapse.took(stopwatch)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Output:
|
77
|
+
|
78
|
+
Time took:
|
79
|
+
* load_data: 2.00s
|
80
|
+
* process_data: 3.00s
|
81
|
+
~~~
|
82
|
+
|
83
|
+
In named mode you cat get **cumulative time** measured by the stopwatch:
|
84
|
+
|
85
|
+
~~~
|
86
|
+
filenames.each do |fn|
|
87
|
+
puts "Processing file (fn:'#{fn}')"; Elapse.start(:process_file)
|
88
|
+
process_file(fn)
|
89
|
+
puts "Processing file ok (took:%.2fs)" % Elapse.took(:process_file)
|
90
|
+
end
|
91
|
+
|
92
|
+
puts "Total file processing took %.2fs" % Elapse.cumulative(:process_file)
|
93
|
+
~~~
|
94
|
+
|
95
|
+
That's it for the basic intro. See the full [RDoc documentation](http://rubydoc.info/github/dadooda/elapse/master/frames) for more details.
|
96
|
+
|
97
|
+
|
98
|
+
Compatibility
|
99
|
+
-------------
|
100
|
+
|
101
|
+
Tested to run on:
|
102
|
+
|
103
|
+
* Ruby 1.9.2-p180, Linux, RVM
|
104
|
+
|
105
|
+
Compatibility issue reports will be greatly appreciated.
|
106
|
+
|
107
|
+
|
108
|
+
Copyright
|
109
|
+
---------
|
110
|
+
|
111
|
+
Copyright © 2012 Alex Fortuna.
|
112
|
+
|
113
|
+
Licensed under the MIT License.
|
114
|
+
|
115
|
+
|
116
|
+
Feedback
|
117
|
+
--------
|
118
|
+
|
119
|
+
Send bug reports, suggestions and criticisms through [project's page on GitHub](http://github.com/dadooda/elapse).
|
data/Rakefile
ADDED
data/elapse.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path("../lib/elapse/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "elapse"
|
5
|
+
s.version = Elapse::VERSION
|
6
|
+
s.authors = ["Alex Fortuna"]
|
7
|
+
s.email = ["alex.r@askit.org"]
|
8
|
+
s.homepage = "http://github.com/dadooda/elapse"
|
9
|
+
|
10
|
+
# Copy these from class's description, adjust markup.
|
11
|
+
s.summary = %q{Elapsed time measurement tool}
|
12
|
+
s.description = %q{Elapsed time measurement tool}
|
13
|
+
# end of s.description=
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map {|f| File.basename(f)}
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "yard"
|
22
|
+
end
|
data/lib/elapse.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
# Load all stuff.
|
3
|
+
[
|
4
|
+
"elapse/**/*.rb",
|
5
|
+
].each do |fmask|
|
6
|
+
Dir[File.expand_path("../#{fmask}", __FILE__)].each do |fn|
|
7
|
+
require fn
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# == Elapsed time measurement tool
|
12
|
+
#
|
13
|
+
# See {rubydoc documentation}[http://rubydoc.info/github/dadooda/elapse/master/frames] for basic usage examples.
|
14
|
+
module Elapse
|
15
|
+
# Clear everything.
|
16
|
+
def self.clear
|
17
|
+
instance.clear
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return sum of all measurements made by the stopwatch.
|
22
|
+
#
|
23
|
+
# Elapse.start(:mytime); sleep 0.01; Elapse.stop(:mytime)
|
24
|
+
# Elapse.cumulative(:mytime) # => 0.01
|
25
|
+
# Elapse.start(:mytime); sleep 0.02; Elapse.stop(:mytime)
|
26
|
+
# Elapse.cumulative(:mytime) # => 0.03
|
27
|
+
def self.cumulative(sw_key)
|
28
|
+
instance.cumulative(sw_key)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Reset the named stopwatch.
|
32
|
+
#
|
33
|
+
# Elapse.reset(:mytime)
|
34
|
+
def self.reset(sw_key)
|
35
|
+
instance.reset(sw_key)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Start the stopwatch. Return Time::now.
|
39
|
+
#
|
40
|
+
# start # Stacked mode.
|
41
|
+
# start(:mytime) # Named mode.
|
42
|
+
def self.start(sw_key = nil)
|
43
|
+
instance.start(sw_key)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Stop the stopwatch. Return Time::now.
|
47
|
+
#
|
48
|
+
# stop # Stacked mode.
|
49
|
+
# stop(:mytime) # Named mode.
|
50
|
+
def self.stop(sw_key = nil)
|
51
|
+
instance.stop(sw_key)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return time of the last stopwatch measurement. If the stopwatch is running, stop it.
|
55
|
+
#
|
56
|
+
# Stacked mode:
|
57
|
+
#
|
58
|
+
# start
|
59
|
+
# sleep 0.01
|
60
|
+
# took # => 0.01
|
61
|
+
#
|
62
|
+
# Named mode:
|
63
|
+
#
|
64
|
+
# start(:mytime)
|
65
|
+
# sleep 0.01
|
66
|
+
# took(:mytime) # => 0.01
|
67
|
+
#
|
68
|
+
# Block execution, stacked mode:
|
69
|
+
#
|
70
|
+
# took {sleep 0.01} # => 0.01
|
71
|
+
#
|
72
|
+
# Block execution, named mode:
|
73
|
+
#
|
74
|
+
# took(:mytime) {sleep 0.01} # => 0.01
|
75
|
+
def self.took(sw_key = nil, &block)
|
76
|
+
instance.took(sw_key, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
class << self
|
80
|
+
private
|
81
|
+
|
82
|
+
# Return Elapse::Instance.
|
83
|
+
def instance
|
84
|
+
# We need not publish the instance object. Everything should be made via the API methods.
|
85
|
+
@instance ||= Instance.new
|
86
|
+
end
|
87
|
+
end # class << self
|
88
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Elapse
|
2
|
+
# An instance of the system.
|
3
|
+
class Instance
|
4
|
+
# Stacked stopwatches.
|
5
|
+
attr_accessor :stack
|
6
|
+
|
7
|
+
# Named stopwatches.
|
8
|
+
attr_accessor :stopwatches
|
9
|
+
|
10
|
+
def initialize(attrs = {})
|
11
|
+
clear
|
12
|
+
attrs.each {|k, v| send("#{k}=", v)}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Clear everything.
|
16
|
+
def clear
|
17
|
+
@stack = []
|
18
|
+
@stopwatches = {}
|
19
|
+
self # By convention.
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return sum of all measurements made by the stopwatch.
|
23
|
+
#
|
24
|
+
# See Elapse::cumulative.
|
25
|
+
def cumulative(sw_key)
|
26
|
+
sw = find_stopwatch(sw_key)
|
27
|
+
|
28
|
+
begin
|
29
|
+
sw.cumulative
|
30
|
+
rescue RuntimeError => e
|
31
|
+
# Append stopwatch name.
|
32
|
+
raise "#{e.message}: #{sw_key.inspect}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Reset the named stopwatch.
|
37
|
+
#
|
38
|
+
# See Elapse::reset.
|
39
|
+
def reset(sw_key)
|
40
|
+
# Let's be strict.
|
41
|
+
find_stopwatch(sw_key).reset
|
42
|
+
end
|
43
|
+
|
44
|
+
# Start the stopwatch. Return Time::now.
|
45
|
+
#
|
46
|
+
# See Elapse::start.
|
47
|
+
def start(sw_key = nil)
|
48
|
+
sw = if sw_key
|
49
|
+
# Named mode.
|
50
|
+
@stopwatches[sw_key] ||= Stopwatch.new
|
51
|
+
else
|
52
|
+
# Stacked mode.
|
53
|
+
Stopwatch.new
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
out = sw.start
|
58
|
+
rescue RuntimeError => e
|
59
|
+
# Append stopwatch name.
|
60
|
+
raise "#{e.message}: #{sw_key.inspect}"
|
61
|
+
end
|
62
|
+
|
63
|
+
if not sw_key
|
64
|
+
# Stacked mode.
|
65
|
+
@stack.push(sw)
|
66
|
+
end
|
67
|
+
|
68
|
+
out
|
69
|
+
end
|
70
|
+
|
71
|
+
# Stop the stopwatch. Return Time::now.
|
72
|
+
#
|
73
|
+
# See Elapse::stop.
|
74
|
+
def stop(sw_key = nil)
|
75
|
+
fetch_stopwatch(sw_key).stop
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return time of the last stopwatch measurement. If the stopwatch is running, stop it.
|
79
|
+
#
|
80
|
+
# See Elapse::took.
|
81
|
+
def took(sw_key = nil, &block)
|
82
|
+
if block
|
83
|
+
start(sw_key)
|
84
|
+
yield
|
85
|
+
return took(sw_key)
|
86
|
+
end
|
87
|
+
|
88
|
+
fetch_stopwatch(sw_key).took
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Find or pop stopwatch for the given <tt>sw_key</tt>.
|
94
|
+
def fetch_stopwatch(sw_key)
|
95
|
+
if sw_key
|
96
|
+
# Named mode.
|
97
|
+
find_stopwatch(sw_key)
|
98
|
+
else
|
99
|
+
# Stacked mode.
|
100
|
+
@stack.pop or raise "Stopwatch stack underflow (you called `stop` more times than `start`)"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def find_stopwatch(sw_key)
|
105
|
+
# NOTES:
|
106
|
+
#
|
107
|
+
# * Message looks okay.
|
108
|
+
# * Error is actually more `RuntimeError` than `ArgumentError`.
|
109
|
+
@stopwatches[sw_key] or raise "Stopwatch not found: #{sw_key.inspect}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Elapse
|
2
|
+
# Our stopwatch class.
|
3
|
+
class Stopwatch
|
4
|
+
attr_reader :started_at
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
clear
|
8
|
+
end
|
9
|
+
|
10
|
+
# Clear object.
|
11
|
+
def clear
|
12
|
+
@cumulative = nil
|
13
|
+
@started_at = nil
|
14
|
+
@took = nil
|
15
|
+
self # By convention.
|
16
|
+
end
|
17
|
+
|
18
|
+
# Stop the stopwatch and return cumulative time.
|
19
|
+
def cumulative
|
20
|
+
stop
|
21
|
+
@cumulative
|
22
|
+
end
|
23
|
+
|
24
|
+
# Reset stopwatch.
|
25
|
+
def reset
|
26
|
+
clear
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return true if the stopwatch is running.
|
31
|
+
def running?
|
32
|
+
!!@started_at
|
33
|
+
end
|
34
|
+
|
35
|
+
# Start the stopwatch. Return Time::now.
|
36
|
+
def start
|
37
|
+
raise "Stopwatch already started" if @started_at
|
38
|
+
@started_at = Time.now
|
39
|
+
end
|
40
|
+
|
41
|
+
# Stop the stopwatch. Return Time::now.
|
42
|
+
def stop
|
43
|
+
now = Time.now
|
44
|
+
|
45
|
+
# We can stop multiple times. We cannot stop if never started.
|
46
|
+
if @started_at
|
47
|
+
@cumulative ||= 0.0
|
48
|
+
@took = now - @started_at
|
49
|
+
@cumulative += @took
|
50
|
+
@started_at = nil
|
51
|
+
elsif not @cumulative
|
52
|
+
raise "Stopwatch was never started"
|
53
|
+
end
|
54
|
+
|
55
|
+
now
|
56
|
+
end
|
57
|
+
|
58
|
+
# Stop the stopwatch and return the last measurement.
|
59
|
+
#
|
60
|
+
# start
|
61
|
+
# sleep 0.1
|
62
|
+
# took # => 0.100393978
|
63
|
+
def took
|
64
|
+
stop
|
65
|
+
@took
|
66
|
+
end
|
67
|
+
end # Stopwatch
|
68
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
describe Elapse::Instance do
|
4
|
+
before :each do
|
5
|
+
@r = described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
# Shared examples.
|
9
|
+
it_behaves_like Elapse::Instance
|
10
|
+
|
11
|
+
describe "#took block mode" do
|
12
|
+
it "should work stacked" do
|
13
|
+
took = @r.took {sleep 0.01}
|
14
|
+
@r.stack.should be_empty
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "stacked mode" do
|
19
|
+
describe "#start" do
|
20
|
+
it "should add a stopwatch to the stack" do
|
21
|
+
@r.stack.size.should == 0
|
22
|
+
@r.start
|
23
|
+
@r.stack.size.should == 1
|
24
|
+
@r.start
|
25
|
+
@r.stack.size.should == 2
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
describe Elapse::Stopwatch do
|
4
|
+
before :each do
|
5
|
+
@r = described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should generally work" do
|
9
|
+
@r.start
|
10
|
+
sleep 0.01
|
11
|
+
("%.2f" % @r.took).should == "0.01"
|
12
|
+
|
13
|
+
@r.start
|
14
|
+
sleep 0.01
|
15
|
+
@r.stop
|
16
|
+
("%.2f" % @r.took).should == "0.01"
|
17
|
+
|
18
|
+
@r.start
|
19
|
+
@r.reset
|
20
|
+
lambda do
|
21
|
+
@r.stop
|
22
|
+
end.should raise_error RuntimeError
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#cumulative" do
|
26
|
+
it "should generally work" do
|
27
|
+
@r.start; sleep 0.01; @r.stop
|
28
|
+
@r.start; sleep 0.02; @r.stop
|
29
|
+
("%.2f" % @r.cumulative).should == "0.03"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should stop the timer" do
|
33
|
+
@r.start
|
34
|
+
@r.cumulative
|
35
|
+
@r.running?.should == false
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should allow multimple invocations and retain the last value" do
|
39
|
+
@r.start
|
40
|
+
sleep 0.01
|
41
|
+
took1 = @r.cumulative
|
42
|
+
sleep 0.02
|
43
|
+
took2 = @r.cumulative
|
44
|
+
took1.should == took2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#start" do
|
49
|
+
it "should return a Time object" do
|
50
|
+
@r.start.should be_a Time
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should raise if already started" do
|
54
|
+
lambda do
|
55
|
+
@r.start
|
56
|
+
@r.start
|
57
|
+
end.should raise_error RuntimeError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#stop" do
|
62
|
+
it "should return a Time object" do
|
63
|
+
@r.start
|
64
|
+
@r.stop.should be_a Time
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should raise if never started" do
|
68
|
+
lambda do
|
69
|
+
@r.stop
|
70
|
+
end.should raise_error RuntimeError
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not raise if called more than once" do
|
74
|
+
lambda do
|
75
|
+
@r.start
|
76
|
+
@r.stop
|
77
|
+
@r.stop
|
78
|
+
end.should_not raise_error
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#took" do
|
83
|
+
it "should stop the timer" do
|
84
|
+
@r.start
|
85
|
+
@r.took
|
86
|
+
@r.running?.should == false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should allow multimple invocations and retain the last value" do
|
90
|
+
@r.start
|
91
|
+
sleep 0.01
|
92
|
+
took1 = @r.took
|
93
|
+
sleep 0.01
|
94
|
+
took2 = @r.took
|
95
|
+
took1.should == took2
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should raise if never started" do
|
99
|
+
lambda do
|
100
|
+
@r.took
|
101
|
+
end.should raise_error RuntimeError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/spec/elapse_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
describe Elapse do
|
4
|
+
before :each do
|
5
|
+
@r = described_class
|
6
|
+
@r.instance_eval {@instance = nil}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Shared examples.
|
10
|
+
it_behaves_like Elapse::Instance
|
11
|
+
|
12
|
+
it "should generally work" do
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
shared_examples_for Elapse::Instance do
|
2
|
+
describe "#took block mode" do
|
3
|
+
it "should work stacked" do
|
4
|
+
took = @r.took {sleep 0.01}
|
5
|
+
("%.2f" % took).should == "0.01"
|
6
|
+
|
7
|
+
took = @r.took {sleep 0.01; @r.took {sleep 0.02}}
|
8
|
+
("%.2f" % took).should == "0.03"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should work named" do
|
12
|
+
@r.took(:mytime) {sleep 0.01}
|
13
|
+
("%.2f" % @r.took(:mytime)).should == "0.01"
|
14
|
+
@r.took(:mytime) {sleep 0.02}
|
15
|
+
("%.2f" % @r.took(:mytime)).should == "0.02"
|
16
|
+
("%.2f" % @r.cumulative(:mytime)).should == "0.03"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "named mode" do
|
21
|
+
it "should generally work" do
|
22
|
+
@r.start(:mytime)
|
23
|
+
sleep 0.01
|
24
|
+
("%.2f" % @r.took(:mytime)).should == "0.01"
|
25
|
+
|
26
|
+
# Overlapping stopwatches.
|
27
|
+
@r.start(:sw1)
|
28
|
+
sleep 0.01
|
29
|
+
@r.start(:sw2)
|
30
|
+
sleep 0.02
|
31
|
+
("%.2f" % @r.took(:sw1)).should == "0.03"
|
32
|
+
("%.2f" % @r.took(:sw2)).should == "0.02"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#cumulative" do
|
36
|
+
it "should generally work" do
|
37
|
+
@r.start(:mytime); sleep 0.01; @r.stop(:mytime)
|
38
|
+
@r.took(:mytime) {sleep 0.02}
|
39
|
+
("%.2f" % @r.cumulative(:mytime)).should == "0.03"
|
40
|
+
|
41
|
+
@r.reset(:mytime)
|
42
|
+
lambda do
|
43
|
+
@r.cumulative(:mytime)
|
44
|
+
end.should raise_error RuntimeError # "Stopwatch was never started"
|
45
|
+
|
46
|
+
message = @r.cumulative(:mytime) rescue $!.message
|
47
|
+
message.should be_a String
|
48
|
+
message.should match /\s*:mytime\s*/
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should validate presence" do
|
52
|
+
lambda do
|
53
|
+
@r.cumulative(:mytime)
|
54
|
+
end.should raise_error RuntimeError
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should report name in exception message" do
|
58
|
+
message = @r.cumulative(:mytime) rescue $!.message
|
59
|
+
message.should be_a String
|
60
|
+
message.should match /\s*:mytime\s*/
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#reset" do
|
65
|
+
it "should validate presence" do
|
66
|
+
lambda do
|
67
|
+
@r.reset(:mytime)
|
68
|
+
end.should raise_error RuntimeError
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should report name in exception message" do
|
72
|
+
message = @r.reset(:mytime) rescue $!.message
|
73
|
+
message.should be_a String
|
74
|
+
message.should match /\s*:mytime\s*/
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#start" do
|
79
|
+
it "should raise if already started" do
|
80
|
+
@r.start(:mytime)
|
81
|
+
lambda do
|
82
|
+
@r.start(:mytime)
|
83
|
+
end.should raise_error RuntimeError
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should report name in exception message" do
|
87
|
+
@r.start(:mytime)
|
88
|
+
message = @r.start(:mytime) rescue $!.message
|
89
|
+
message.should be_a String
|
90
|
+
message.should match /\s*:mytime\s*/
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return a Time object" do
|
94
|
+
@r.start(:mytime).should be_a Time
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#stop" do
|
99
|
+
it "should return a Time object" do
|
100
|
+
@r.start(:mytime)
|
101
|
+
@r.stop(:mytime).should be_a Time
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should validate presence" do
|
105
|
+
lambda do
|
106
|
+
@r.stop(:mytime)
|
107
|
+
end.should raise_error RuntimeError
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should report name in exception message" do
|
111
|
+
message = @r.stop(:mytime) rescue $!.message
|
112
|
+
message.should be_a String
|
113
|
+
message.should match /\s*:mytime\s*/
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end # describe "named mode"
|
117
|
+
|
118
|
+
describe "stacked mode" do
|
119
|
+
it "should generally work" do
|
120
|
+
@r.start
|
121
|
+
sleep 0.01
|
122
|
+
("%.2f" % @r.took).should == "0.01"
|
123
|
+
|
124
|
+
@r.start
|
125
|
+
sleep 0.01
|
126
|
+
@r.start
|
127
|
+
sleep 0.02
|
128
|
+
("%.2f" % @r.took).should == "0.02"
|
129
|
+
("%.2f" % @r.took).should == "0.03"
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#start" do
|
133
|
+
it "should return a Time object" do
|
134
|
+
@r.start.should be_a Time
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#stop" do
|
139
|
+
it "should return a Time object" do
|
140
|
+
@r.start
|
141
|
+
@r.stop.should be_a Time
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should raise if stack underflow" do
|
145
|
+
lambda do
|
146
|
+
@r.stop
|
147
|
+
end.should raise_error RuntimeError
|
148
|
+
|
149
|
+
lambda do
|
150
|
+
2.times {@r.start}
|
151
|
+
3.times {@r.stop}
|
152
|
+
end.should raise_error RuntimeError
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "#took" do
|
157
|
+
it "should raise if stack underflow" do
|
158
|
+
lambda do
|
159
|
+
@r.took
|
160
|
+
end.should raise_error RuntimeError
|
161
|
+
|
162
|
+
lambda do
|
163
|
+
2.times {@r.start}
|
164
|
+
3.times {@r.took}
|
165
|
+
end.should raise_error RuntimeError
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end # describe "stacked mode"
|
169
|
+
end # shared_examples_for Elapse::Instance
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# NOTE: I usually support `STANDALONE` mode in specs for Rails projects' components
|
2
|
+
# to be able to test them without loading the environment. This project does not
|
3
|
+
# depend on Rails *BUT* I still want a consistent RSpec file structure.
|
4
|
+
# If this is confusing, feel free to propose something better. :)
|
5
|
+
|
6
|
+
# No Rails, we're always standalone... and free! :)
|
7
|
+
STANDALONE = 1
|
8
|
+
|
9
|
+
if STANDALONE
|
10
|
+
# Provide root path object.
|
11
|
+
module Standalone
|
12
|
+
eval <<-EOT
|
13
|
+
def self.root
|
14
|
+
# This is an absolute path, it's perfectly safe to do a `+` and then `require`.
|
15
|
+
Pathname("#{File.expand_path('../..', __FILE__)}")
|
16
|
+
end
|
17
|
+
EOT
|
18
|
+
end
|
19
|
+
|
20
|
+
# Load stuff.
|
21
|
+
[
|
22
|
+
"lib/**/*.rb",
|
23
|
+
].each do |fmask|
|
24
|
+
Dir[Standalone.root + fmask].each do |fn|
|
25
|
+
require fn
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require File.expand_path("../shared_examples", __FILE__)
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: elapse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex Fortuna
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-12 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &81559990 !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: *81559990
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
requirement: &81559720 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *81559720
|
36
|
+
description: Elapsed time measurement tool
|
37
|
+
email:
|
38
|
+
- alex.r@askit.org
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .rspec
|
45
|
+
- Gemfile
|
46
|
+
- Gemfile.lock
|
47
|
+
- MIT-LICENSE
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- elapse.gemspec
|
51
|
+
- lib/elapse.rb
|
52
|
+
- lib/elapse/instance.rb
|
53
|
+
- lib/elapse/stopwatch.rb
|
54
|
+
- lib/elapse/version.rb
|
55
|
+
- spec/elapse/instance_spec.rb
|
56
|
+
- spec/elapse/spec_helper.rb
|
57
|
+
- spec/elapse/stopwatch_spec.rb
|
58
|
+
- spec/elapse_spec.rb
|
59
|
+
- spec/shared_examples.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
homepage: http://github.com/dadooda/elapse
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.10
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Elapsed time measurement tool
|
85
|
+
test_files: []
|
86
|
+
has_rdoc:
|