waitfor 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -6,8 +6,11 @@ lib/waitfor.rb
6
6
  lib/waitfor/fixnum.rb
7
7
  lib/waitfor/timer.rb
8
8
  lib/waitfor/version.rb
9
- spec/waitfor_spec.rb
10
- spec/timer_spec.rb
9
+ lib/waitfor/waitfor_timeout_error.rb
11
10
  spec/fixnum_spec.rb
12
11
  spec/spec.opts
13
- spec/spec_helper.rb
12
+ spec/spec_helper.rb
13
+ spec/spec_helper_spec.rb
14
+ spec/waitfor_spec.rb
15
+ spec/timer_spec.rb
16
+ spec/waitfor_timeout_error_spec.rb
data/README.rdoc CHANGED
@@ -4,44 +4,72 @@
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- Continuously executes a Block until the Block returns true or the time limit is reached, at which point an error is raised.
7
+ Blocks execution until a specified statement becomes true, or a specified time interval is reached, at which point an error is raised.
8
+
8
9
  Useful for strengthening tests involving asynchronous or non-blocking operations.
9
10
 
10
11
  == FEATURES/PROBLEMS:
11
12
 
12
- * Accepts arguments of second / seconds or minute / minutes
13
- * Allows for custom RuntimeError messages
14
-
15
- * No custom Error support yet
16
- * Resolution of delay between Block executions is currently 1 second, not yet configurable
13
+ * Accepts time intervals in two formats
14
+ * Simple time DSL of seconds or minutes
15
+ * 30.seconds
16
+ * 5.minutes
17
+ * Hash with symbols :seconds or :minutes
18
+ * :seconds => 30
19
+ * :minutes => 5
20
+ * Singular forms ( 1.second or :minute => 1 ) accepted as well
21
+ * Allows for custom exceptions, custom error messages or both
22
+ * For custom exceptions, add ':exception => YourException' to the options
23
+ * Use either :exception or :error for custom exceptions ( both are identical in functionality )
24
+ * For custom messages, add ':message => "Your Custom Message"' to the options
25
+
26
+ * Resolution of delay between Ruby block executions is currently 1 second, not yet configurable
27
+ * Must use hash if specifying custom exceptions or messages, can't mix and match simple time DSL with hash ( yet )
17
28
 
18
29
  == SYNOPSIS:
19
30
 
20
- This gem is used with asynchronous or non-blocking operations where the action of doing something is separate from whether that action succeeded.
31
+ This gem is used in cases where the execution of an operation occurs asynchronously but a method to determine the operation's status exists. In these cases
32
+ you want to 'wait for' that operation to either complete by continuously checking the status or fail at a specified timeout.
21
33
 
22
- The example below executes an asynchronous operation, then waits for up to 30 seconds for the status of the object to change by continuously checking whether it was successful.
23
- The Block will continue to be executed until it either returns true or 30 seconds elapses. If the time limit is reached, then a RuntimeError is raised.
34
+ The example below runs a non-blocking operation which can not return whether it succeeded or failed. WaitFor blocks execution, in this case, for up to 30 seconds
35
+ while it continuously runs a Ruby block supplied by the user. The Ruby block in this example determines whether the previous non-blocking operation has run to completion.
36
+ As the Ruby block returns false, the timer continues to count down. If it returns true, then it breaks out of the loop and continues on its way. However, if the time elapsed
37
+ becomes greater than the time permitted, 30 seconds in this example, then an exception is raised.
24
38
 
25
- object.some_async_operation
39
+ object.some_nonblocking_operation
26
40
 
27
41
  WaitFor.upto 30.seconds do
28
- object.succeeded?
42
+ object.completed?
29
43
  end
30
44
 
31
- A custom error message is specified in the example below. ( Custom errors are not yet supported. )
45
+ Custom exception and message are specified in the examples below.
32
46
 
33
- WaitFor.upto( 2.minutes, "Timeout after 2 minutes!" ) do
47
+ WaitFor.upto( :minute => 1, :exception => EventFailedToOccurError ) do
34
48
  event.happened?
35
49
  end
36
50
 
37
- Finally, a real world example taken from a FunFX test script I wrote. Here a button is clicked and we want to wait for the new screen to appear before moving on.
51
+ WaitFor.upto( :minute => 1, :message => "Event took longer than 1 minute to complete" ) do
52
+ event.happened?
53
+ end
54
+
55
+ WaitFor.upto( :minute => 1, :exception => EventFailedToOccurError, :message => "Event took longer than 1 minute to complete" ) do
56
+ event.happened?
57
+ end
58
+
59
+ Finally, a few more "real world" examples.
38
60
 
39
61
  button.click
40
62
 
41
- WaitFor.upto 1.minute do
63
+ WaitFor.upto( :minute => 1, :message => "New screen did not appear within 1 minute after clicking button" ) do
42
64
  Check.whether( new_screen ).is :visible
43
65
  end
44
66
 
67
+ website_cluster.propagate_new_entry "Good news everyone!"
68
+
69
+ WaitFor.upto( :seconds => 30, :exception => WebsiteFailedToUpdateError ) do
70
+ website_cluster.each_node_reports "Good news everyone!"
71
+ end
72
+
45
73
  == REQUIREMENTS:
46
74
 
47
75
  * Ruby >= 1.8.6
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ $hoe = Hoe.spec 'waitfor' do
12
12
  self.developer 'James Bobowski', 'james.bobowski@gmail.com'
13
13
  self.rubyforge_name = self.name
14
14
  self.version = WaitFor::VERSION::STRING
15
- self.description = "Continuously executes a Block until the Block returns true or the time limit is reached, at which point an error is raised"
15
+ self.description = "Blocks execution until a specified statement becomes true, or a specified time interval is reached, at which point an error is raised."
16
16
  end
17
17
 
18
18
  require 'newgem/tasks'
data/lib/waitfor/timer.rb CHANGED
@@ -1,13 +1,35 @@
1
1
  class Timer #:nodoc:
2
- def initialize( seconds, exception_message = "Timeout Error Waiting for Event" )
3
- @seconds = seconds
4
- @exception_message = exception_message
5
- @start_time = Time.now
2
+ def initialize( options )
3
+ @seconds = Timer.to_seconds options
4
+
5
+ if options.instance_of? Hash
6
+ @exception = options[ :exception ]
7
+ @exception = options[ :error ] || @exception
8
+ @message = options[ :message ]
9
+ end
10
+
11
+ @exception ||= WaitFor::TimeoutError
12
+ @start_time = Time.now
13
+ end
14
+
15
+ def self.to_seconds( options )
16
+ # Not a hash, already converted to seconds, return as is
17
+ return options if options.instance_of? Fixnum
18
+
19
+ seconds = options[ :second ] || 0
20
+ seconds = options[ :seconds ] || seconds
21
+
22
+ minutes = options[ :minute ] || 0
23
+ minutes = options[ :minutes ] || minutes
24
+
25
+ return seconds + minutes * 60
6
26
  end
7
27
 
8
28
  def out_of_time?
9
- out_of_time = ( Time.now - @start_time ) > @seconds
10
- raise @exception_message if out_of_time
11
- out_of_time
29
+ if ( Time.now - @start_time ) > @seconds
30
+ raise @exception, @message
31
+ end
32
+
33
+ false
12
34
  end
13
35
  end
@@ -1,8 +1,8 @@
1
1
  module WaitFor #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 0
5
- TINY = 1
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -0,0 +1,5 @@
1
+ module WaitFor #:nodoc:
2
+ class TimeoutError < RuntimeError #:nodoc:
3
+
4
+ end
5
+ end
data/lib/waitfor.rb CHANGED
@@ -6,8 +6,8 @@ require 'waitfor/timer'
6
6
 
7
7
  module WaitFor
8
8
  class << self
9
- def upto( length_of_time )
10
- timer = Timer.new length_of_time
9
+ def upto( options )
10
+ timer = Timer.new options
11
11
  until yield or timer.out_of_time?
12
12
  sleep 1
13
13
  end
data/spec/spec_helper.rb CHANGED
@@ -10,9 +10,30 @@ $:.unshift( File.dirname( __FILE__ ) + '/../lib' )
10
10
  require File.dirname( __FILE__ ) + '/../lib/waitfor.rb'
11
11
  require File.dirname( __FILE__ ) + '/../lib/waitfor/fixnum.rb'
12
12
  require File.dirname( __FILE__ ) + '/../lib/waitfor/timer.rb'
13
+ require File.dirname( __FILE__ ) + '/../lib/waitfor/waitfor_timeout_error.rb'
13
14
 
14
15
  def timer
15
16
  start_time = Time.now
16
17
  yield
17
18
  Time.now - start_time
18
19
  end
20
+
21
+ class CustomTestError < RuntimeError
22
+
23
+ end
24
+
25
+ class ToggleBetweenFalseAndTrue
26
+ def initialize
27
+ @status = false
28
+ end
29
+
30
+ def status
31
+ if @status
32
+ @status = false
33
+ true
34
+ else
35
+ @status = true
36
+ false
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "timer method" do
4
+ it "should report an elapsed time of at least 1 second but not more than 2 seconds for the code 'sleep 1'" do
5
+ elapsed_time = timer {
6
+ sleep 1
7
+ }
8
+
9
+ elapsed_time.should be > 1
10
+ elapsed_time.should be < 2
11
+ end
12
+ end
13
+
14
+ describe CustomTestError do
15
+ it "should be of a kind of RuntimeError" do
16
+ exception = CustomTestError.new
17
+ exception.should be_a_kind_of( RuntimeError )
18
+ end
19
+ end
20
+
21
+ describe ToggleBetweenFalseAndTrue do
22
+ it "should have a status method that returns false then true then false then true" do
23
+ event = ToggleBetweenFalseAndTrue.new
24
+
25
+ event.status.should be( false )
26
+ event.status.should be( true )
27
+ event.status.should be( false )
28
+ event.status.should be( true )
29
+ end
30
+ end
data/spec/timer_spec.rb CHANGED
@@ -1,25 +1,83 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
- describe Timer do
4
- it "should not raise an error when set for two seconds and checked after one second" do
5
- timer = Timer.new 2.seconds
6
- sleep 1
3
+ describe Timer, "when checking out_of_time?" do
4
+ it "should return false when set for 5 seconds and queried immediately" do
5
+ timer = Timer.new 5
7
6
  timer.out_of_time?.should be( false )
8
7
  end
9
8
 
10
- it "should raise an error when set for two seconds and checked after one second" do
11
- timer = Timer.new 1.seconds
12
- sleep 2
9
+ it "should raise a WaitFor::TimeoutError when set for 0 seconds and queried immediately" do
10
+ timer = Timer.new 0.seconds
13
11
  lambda {
14
12
  timer.out_of_time?.should be( true )
15
- }.should raise_error( RuntimeError, "Timeout Error Waiting for Event" )
13
+ }.should raise_error( WaitFor::TimeoutError )
14
+ end
15
+ end
16
+
17
+ describe Timer, "when inputting duration in to_seconds" do
18
+ it "should accept a Fixnum value of 5 as 5 seconds" do
19
+ Timer.to_seconds( 1 ).should be( 1 )
20
+ end
21
+
22
+ it "should accept a simple time DSL using a singular value of '1.second' as 1 second" do
23
+ Timer.to_seconds( 1.second ).should be( 1 )
24
+ end
25
+
26
+ it "should accept a simple time DSL using a plural value of '5.seconds' as 5 seconds" do
27
+ Timer.to_seconds( 5.seconds ).should be( 5 )
28
+ end
29
+
30
+ it "should accept a simple time DSL using a singular value of '1.minute' as 60 seconds" do
31
+ Timer.to_seconds( 1.minute ).should be( 60 )
32
+ end
33
+
34
+ it "should accept a simple time DSL using a plural value of '5.minutes' as 300 seconds" do
35
+ Timer.to_seconds( 5.minutes ).should be( 300 )
36
+ end
37
+
38
+ it "should accept a hash using a singular value of ':second => 1' as 1 second" do
39
+ Timer.to_seconds( :second => 1 ).should be( 1 )
40
+ end
41
+
42
+ it "should accept a hash using a plural value of ':seconds => 5' as 5 seconds" do
43
+ Timer.to_seconds( :seconds => 5 ).should be( 5 )
44
+ end
45
+
46
+ it "should accept a hash using a singular value of ':minute => 1' as 60 seconds" do
47
+ Timer.to_seconds( :minute => 1 ).should be( 60 )
16
48
  end
17
49
 
18
- it "should raise a custom error when set for one second and checked after two second" do
19
- timer = Timer.new( 1.seconds, "Custom Error" )
20
- sleep 2
50
+ it "should accept a hash using a plural value of ':minutes => 5' as 300 seconds" do
51
+ Timer.to_seconds( :minutes => 5 ).should be( 300 )
52
+ end
53
+ end
54
+
55
+ describe Timer, "when inputting custom errors" do
56
+ it "should raise a CustomTestError when passed the value of ':exception => CustomTestError" do
57
+ timer = Timer.new :seconds => 0, :exception => CustomTestError
21
58
  lambda {
22
59
  timer.out_of_time?.should be( true )
23
- }.should raise_error( RuntimeError, "Custom Error" )
60
+ }.should raise_error( CustomTestError )
24
61
  end
25
- end
62
+
63
+ it "should raise a CustomTestError when passed the value of ':error => CustomTestError" do
64
+ timer = Timer.new :seconds => 0, :error => CustomTestError
65
+ lambda {
66
+ timer.out_of_time?.should be( true )
67
+ }.should raise_error( CustomTestError )
68
+ end
69
+
70
+ it "should raise an error with the custom message 'Custom Error Message' when passed the value of ':message => 'Custom Error Message'" do
71
+ timer = Timer.new :seconds => 0, :message => "Custom Error Message"
72
+ lambda {
73
+ timer.out_of_time?.should be( true )
74
+ }.should raise_error( "Custom Error Message" )
75
+ end
76
+
77
+ it "should raise a CustomTestError with the custom message 'Custom Error Message' when passed the value of ':exception => CustomTestError' and ':message => 'Custom Error Message'" do
78
+ timer = Timer.new :seconds => 0, :exception => CustomTestError, :message => "Custom Error Message"
79
+ lambda {
80
+ timer.out_of_time?.should be( true )
81
+ }.should raise_error( CustomTestError, "Custom Error Message" )
82
+ end
83
+ end
data/spec/waitfor_spec.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require File.dirname( __FILE__ ) + '/spec_helper.rb'
2
2
 
3
- describe WaitFor do
4
- it "should pass in under one second if block returns true immediately" do
3
+ describe WaitFor, "when event is true" do
4
+ it "should halt execution for under 1 second" do
5
5
  elapsed_time = timer {
6
6
  WaitFor.upto 1.second do
7
7
  true
@@ -10,8 +10,10 @@ describe WaitFor do
10
10
 
11
11
  elapsed_time.should be < 1.second
12
12
  end
13
+ end
13
14
 
14
- it "should take at least two seconds before raising an error" do
15
+ describe WaitFor, "when event is false" do
16
+ it "should halt execution for at least 2 seconds, but less than 4 seconds before raising an error" do
15
17
  elapsed_time = timer {
16
18
  lambda {
17
19
  WaitFor.upto 2.seconds do
@@ -20,6 +22,53 @@ describe WaitFor do
20
22
  }.should raise_error
21
23
  }
22
24
 
23
- elapsed_time.should be_close( 2, 0.25 )
25
+ elapsed_time.should be > 2
26
+ elapsed_time.should be < 4
27
+ end
28
+ end
29
+
30
+ describe WaitFor, "when event is false and has custom exception" do
31
+ it "should raise a CustomTestError error" do
32
+ lambda {
33
+ WaitFor.upto( :seconds => 0, :exception => CustomTestError ) do
34
+ false
35
+ end
36
+ }.should raise_error( CustomTestError )
37
+ end
38
+ end
39
+
40
+ describe WaitFor, "when event is false and has custom message" do
41
+ it "should raise an error with a custom message" do
42
+ lambda {
43
+ WaitFor.upto( :seconds => 0, :message => "Custom Error Message" ) do
44
+ false
45
+ end
46
+ }.should raise_error( "Custom Error Message" )
47
+ end
48
+ end
49
+
50
+ describe WaitFor, "when event is false and has custom exception with a custom message" do
51
+ it "should raise a CustomTestError error with a custom message" do
52
+ lambda {
53
+ WaitFor.upto( :seconds => 0, :exception => CustomTestError, :message => "Custom Error Message" ) do
54
+ false
55
+ end
56
+ }.should raise_error( CustomTestError, "Custom Error Message" )
24
57
  end
25
58
  end
59
+
60
+ describe WaitFor, "when event is initially false but becomes true " do
61
+ it "should halt execution for at least 1 second but no more than 3 seconds before continuing on" do
62
+ event = ToggleBetweenFalseAndTrue.new
63
+
64
+ elapsed_time = timer {
65
+ WaitFor.upto 2.seconds do
66
+ event.status
67
+ end
68
+ }
69
+
70
+ elapsed_time.should be > 1
71
+ elapsed_time.should be < 3
72
+ end
73
+ end
74
+
@@ -0,0 +1,6 @@
1
+ describe WaitFor::TimeoutError do
2
+ it "should be of a kind of RuntimeError" do
3
+ exception = WaitFor::TimeoutError.new
4
+ exception.should be_a_kind_of( RuntimeError )
5
+ end
6
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waitfor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Bobowski
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-24 00:00:00 -06:00
12
+ date: 2010-02-03 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,7 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 2.3.3
24
24
  version:
25
- description: Continuously executes a Block until the Block returns true or the time limit is reached, at which point an error is raised
25
+ description: Blocks execution until a specified statement becomes true, or a specified time interval is reached, at which point an error is raised.
26
26
  email:
27
27
  - james.bobowski@gmail.com
28
28
  executables: []
@@ -35,17 +35,20 @@ extra_rdoc_files:
35
35
  files:
36
36
  - History.txt
37
37
  - Manifest.txt
38
- - README.rdoc
39
38
  - Rakefile
39
+ - README.rdoc
40
40
  - lib/waitfor.rb
41
41
  - lib/waitfor/fixnum.rb
42
42
  - lib/waitfor/timer.rb
43
43
  - lib/waitfor/version.rb
44
- - spec/waitfor_spec.rb
45
- - spec/timer_spec.rb
44
+ - lib/waitfor/waitfor_timeout_error.rb
46
45
  - spec/fixnum_spec.rb
47
46
  - spec/spec.opts
48
47
  - spec/spec_helper.rb
48
+ - spec/spec_helper_spec.rb
49
+ - spec/timer_spec.rb
50
+ - spec/waitfor_spec.rb
51
+ - spec/waitfor_timeout_error_spec.rb
49
52
  has_rdoc: true
50
53
  homepage: http://github.com/jamesbobowski/waitfor
51
54
  licenses: []