kametori 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Kametori
2
2
 
3
- TODO: Write a gem description
3
+ Kametori helps you to write a benchmark test suite
4
4
 
5
5
  ## Installation
6
6
 
@@ -18,7 +18,26 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ The best way to use this gem is adding a profile to your
22
+ cucumber.yml file (usually located in config in Rails projects).
23
+ Like:
24
+ benchmark: --format progress -r features/support/benchmark.rb
25
+
26
+ And in features/support/benchmark.rb you write:
27
+
28
+ Kametori.scenario_limits = [{ tag: "fast_scenario", limit:1 },
29
+ {tag:"slow_scenario", limit:10}]
30
+
31
+ Kametori.raise_errors = true
32
+
33
+ Around do |scenario, block|
34
+ Kametori.scenario_benchmark(scenario) do
35
+ block.call
36
+ end
37
+ end
38
+
39
+
40
+
22
41
 
23
42
  ## Contributing
24
43
 
data/kametori.gemspec CHANGED
@@ -17,4 +17,6 @@ Gem::Specification.new do |gem|
17
17
  gem.version = Kametori::VERSION
18
18
 
19
19
  gem.add_development_dependency("rspec", [">= 2.2.0"])
20
+ gem.add_development_dependency("timecop")
21
+ gem.add_development_dependency("debugger")
20
22
  end
@@ -1,3 +1,3 @@
1
1
  module Kametori
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/kametori.rb CHANGED
@@ -2,36 +2,89 @@ require "kametori/version"
2
2
 
3
3
  module Kametori
4
4
  # exception classes
5
- class Error < RuntimeError
6
- end
7
- class Timeout < RuntimeError
8
-
5
+ class Timeout < StandardError
9
6
  end
10
7
 
11
8
  class << self
12
- def limits=(limits)
13
- raise Error if !limits.is_a? Array
9
+ attr_accessor :raise_errors
10
+ def reset!
11
+ @raise_errors = false
12
+ @limits = []
13
+ @repeat_count = 1
14
+ end
15
+ def scenario_limits=(limits)
16
+ check_limits (limits)
14
17
  @limits = limits
15
18
  end
16
19
 
17
- def limits
18
- @limits
20
+ def scenario_limits
21
+ @limits || []
22
+ end
23
+
24
+ def average_over=(count)
25
+ raise( ArgumentError, "Wrong average over count") unless count.is_a? Integer
26
+ raise( ArgumentError, "Wrong average over count") if count < 1
27
+ @repeat_count = count
28
+ end
29
+
30
+ def current_scenario
31
+ @current_scenario || {}
19
32
  end
20
33
 
21
- def benchmark_scenario(scenario, options={})
22
- under_test = @limits.find{ |limit| limit[:tag] == scenario.tag}
34
+ def average_over
35
+ current_scenario[:average_over] || @repeat_count || 1
36
+ end
37
+
38
+ def scenario_benchmark(scenario, options={}, &block)
39
+ under_test = find_scenario_under_test(scenario)
23
40
  return nil if under_test.nil?
24
- before = Time.now
25
- yield if block_given?
26
- after = Time.now
27
- elapsed = after - before
28
- if options[:raise]
29
- if ( elapsed > under_test[:limit])
30
- raise Timeout
31
- end
32
- end
41
+ return nil unless block_given?
42
+
43
+ elapsed = execute_with_timing(average_over) { block.call }
44
+ limit = under_test[:limit]
45
+ check_finish_on_time(elapsed,limit)
33
46
  elapsed
34
47
  end
35
48
 
49
+ private
50
+
51
+ def check_limits(limits)
52
+ correct = limits.is_a?(Array) &&
53
+ limits.all? { |l| l.include?(:tag) && l.include?(:limit) && l[:limit].is_a?(Numeric)}
54
+ raise( ArgumentError, "wrong scenario limits") unless correct
55
+ end
56
+
57
+ def find_scenario_under_test(scenario)
58
+ @current_scenario = @limits.find{ |limit| scenario.source_tag_names.include? limit[:tag] }
59
+ end
60
+
61
+ def execute_with_timing(average_over)
62
+ elapsed = []
63
+ average_over.times do
64
+ before = Time.now
65
+ yield
66
+ after = Time.now
67
+ elapsed.push (after - before)
68
+ end
69
+ mean(elapsed)
70
+ end
71
+
72
+ def check_finish_on_time( elapsed, limit )
73
+ if raise_errors
74
+ if ( elapsed > limit)
75
+ raise Timeout, "Scenario timed out with #{format_float(elapsed)} > #{limit}"
76
+ end
77
+ end
78
+ end
79
+
80
+ def format_float(float)
81
+ "%.3f" % float
82
+ end
83
+
84
+ def mean(array)
85
+ sum = array.inject(0){ |accum, i| accum + i }
86
+ sum / array.length.to_f
87
+ end
88
+
36
89
  end
37
90
  end
@@ -0,0 +1,152 @@
1
+ require 'spec_helper'
2
+
3
+ # our mock for a cucumber scenario
4
+ class Scenario
5
+ attr_accessor :source_tag_names
6
+ attr_accessor :execution_time
7
+ attr_reader :times_called
8
+ def initialize (names)
9
+ @source_tag_names = [*names]
10
+ @execution_time = 0.1
11
+ @times_called = 0
12
+ end
13
+ def execute
14
+ Timecop.travel Time.now + @execution_time
15
+ @times_called += 1
16
+ end
17
+ end
18
+
19
+ describe Kametori do
20
+
21
+ =begin
22
+ describe '.standard=' do
23
+ it 'raises Kametori::Error if is an unknown standard' do
24
+ expect {Kametori.standard='asdfasdf'}.to raise_error(Kamitori::Error)
25
+ end
26
+ end
27
+
28
+ describe '.speed_test' do
29
+ end
30
+ =end
31
+ describe '.scenario_limits=' do
32
+ it 'should raise an error if the param is not an array' do
33
+ expect { Kametori.scenario_limits= 2 }.to raise_error(ArgumentError, "wrong scenario limits")
34
+ end
35
+ it 'should raise an error if there is no limit for tag' do
36
+ expect { Kametori.scenario_limits=[{tag:"aa"}] }.to raise_error(ArgumentError, "wrong scenario limits")
37
+ end
38
+ it 'should raise and error if there is no tag for limit' do
39
+ expect { Kametori.scenario_limits=[{limit:2}] }.to raise_error(ArgumentError, "wrong scenario limits")
40
+ end
41
+ it 'should raise and error if limit is not numeric' do
42
+ limits = [{ tag: "A", limit: "a"} ]
43
+ expect { Kametori.scenario_limits= limits }.to raise_error(ArgumentError, "wrong scenario limits")
44
+ end
45
+ it 'should set the limits for the tags' do
46
+ limits = [{ tag: "A", limit: 1} ]
47
+ Kametori.scenario_limits = limits
48
+ Kametori.scenario_limits.should == limits
49
+ end
50
+ end
51
+
52
+ describe '.reset!' do
53
+ it 'should reset to the defaults' do
54
+ Kametori.reset!
55
+ Kametori.average_over.should == 1
56
+ Kametori.scenario_limits.should be_empty
57
+ Kametori.raise_errors.should be_false
58
+ end
59
+ end
60
+ describe '.average_over' do
61
+ it 'should raise an error if the parameter is not integer' do
62
+ expect { Kametori.average_over=1.2 }.to raise_error(ArgumentError, "Wrong average over count")
63
+ end
64
+ it 'should raise an error if the parameter is less than 1' do
65
+ expect { Kametori.average_over=0 }.to raise_error(ArgumentError, "Wrong average over count")
66
+ end
67
+ it 'defaults to 1 executions' do
68
+ Kametori.average_over.should == 1
69
+ Kametori.average_over= 10
70
+ Kametori.average_over.should == 10
71
+ end
72
+ end
73
+
74
+ describe '.scenario_benchmark' do
75
+ before do
76
+ @time_limit = 0.2
77
+ Timecop.freeze Time.now
78
+ limits = [{ tag: "MyTag", limit: @time_limit}, {tag: "MyTag2", limit:@time_limit} ]
79
+ Kametori.scenario_limits = limits
80
+ Kametori.average_over= 1
81
+ end
82
+ it 'should return nil if we do not have a limit for this scenario' do
83
+ scenario = Scenario.new("OtherTag")
84
+ Kametori.scenario_benchmark( scenario ) do
85
+ scenario.execute
86
+ end.should == nil
87
+ end
88
+ it 'should return nil if no block given' do
89
+ scenario = Scenario.new("MyTag")
90
+ Kametori.scenario_benchmark( scenario ).should == nil
91
+ end
92
+ it 'should return the time it took to finish the scenario' do
93
+ scenario = Scenario.new("MyTag")
94
+ Kametori.scenario_benchmark( scenario ) do
95
+ scenario.execute
96
+ end.should >= 0.1
97
+ end
98
+
99
+ it 'should work with scenarios with several tags' do
100
+ scenario = Scenario.new(["MyTag", "otherTag", "one_more"])
101
+ Kametori.scenario_benchmark( scenario ) do
102
+ scenario.execute
103
+ end.should >= 0.1
104
+ end
105
+
106
+ describe '.average_over' do
107
+ it 'should call average_over times the block passed' do
108
+ scenario = Scenario.new("MyTag")
109
+ Kametori.average_over = 5
110
+ Kametori.scenario_benchmark( scenario ) do
111
+ scenario.execute
112
+ end
113
+ scenario.times_called.should == 5
114
+ Kametori.average_over = 1
115
+ end
116
+ it '.average_over can be overriden by the value in the hash' do
117
+ old_limits = Kametori.scenario_limits
118
+ limits = [{ tag: "MyTag", limit: @time_limit, average_over: 2}, {tag: "MyTag2", limit:@time_limit} ]
119
+ Kametori.scenario_limits = limits
120
+ Kametori.average_over = 5
121
+ scenario = Scenario.new("MyTag")
122
+ Kametori.scenario_benchmark( scenario ) do
123
+ scenario.execute
124
+ end
125
+ scenario.times_called.should == 2
126
+ Kametori.scenario_limits = old_limits
127
+ end
128
+ end
129
+
130
+ describe '.raise_errors' do
131
+ it 'should return the time it took to finish the scenario and not raise if it finished before the limit' do
132
+ scenario = Scenario.new("MyTag")
133
+ Kametori.raise_errors = true
134
+ Kametori.scenario_benchmark( scenario ) do
135
+ scenario.execute
136
+ end.should < 0.2
137
+ end
138
+
139
+ it 'should raise Kametori::Timeout if the scenario is slower than its limit and we set to raise' do
140
+ scenario = Scenario.new("MyTag")
141
+ scenario.execution_time = 0.21
142
+ Kametori.raise_errors = true
143
+ expect do
144
+ Kametori.scenario_benchmark( scenario ) do
145
+ scenario.execute
146
+ end
147
+ end.to raise_error( Kametori::Timeout, /Scenario timed out with [0-9]*\.?[0-9]{3} > #{@time_limit}/ )
148
+ end
149
+ end
150
+
151
+ end
152
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/kametori'
2
+ require 'timecop'
3
+
4
+ RSpec.configure do |config|
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ config.run_all_when_everything_filtered = true
7
+ config.filter_run :focus
8
+
9
+ # Run specs in random order to surface order dependencies. If you find an
10
+ # order dependency and want to debug it, you can fix the order by providing
11
+ # the seed, which is printed after each run.
12
+ # --seed 1234
13
+ config.order = 'random'
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kametori
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,6 +27,38 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: timecop
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
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
+ - !ruby/object:Gem::Dependency
47
+ name: debugger
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
30
62
  description: A gem to create benchmark suites for your app. It allows you to keep
31
63
  track of your performance
32
64
  email:
@@ -36,6 +68,7 @@ extensions: []
36
68
  extra_rdoc_files: []
37
69
  files:
38
70
  - .gitignore
71
+ - .rspec
39
72
  - Gemfile
40
73
  - LICENSE
41
74
  - README.md
@@ -43,6 +76,8 @@ files:
43
76
  - kametori.gemspec
44
77
  - lib/kametori.rb
45
78
  - lib/kametori/version.rb
79
+ - spec/kametori_spec.rb
80
+ - spec/spec_helper.rb
46
81
  homepage: http://www.github.com/JordiPolo/kametori
47
82
  licenses: []
48
83
  post_install_message:
@@ -67,5 +102,7 @@ rubygems_version: 1.8.24
67
102
  signing_key:
68
103
  specification_version: 3
69
104
  summary: A gem to create benchmark suites for your app.
70
- test_files: []
105
+ test_files:
106
+ - spec/kametori_spec.rb
107
+ - spec/spec_helper.rb
71
108
  has_rdoc: