danielsdeleo-em-spec 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,84 @@
1
+ Simple BDD API for testing asynchronous Ruby/EventMachine code
2
+ (c) 2008 Aman Gupta (tmm1)
3
+
4
+ em-spec can be used with either bacon or rspec.
5
+
6
+ =Rspec
7
+ There are two ways to use the Rspec extension. To use it as a helper, include EM::SpecHelper in your describe block. You then use the em method to wrap your evented test code. Inside the em block, you must call #done after your expectations. Everything works normally otherwise.
8
+
9
+ require "em-spec/rspec"
10
+ describe EventMachine do
11
+ include EM::SpecHelper
12
+
13
+ it "works normally when not using #em" do
14
+ 1.should == 1
15
+ end
16
+
17
+ it "makes testing evented code easy with #em" do
18
+ em do
19
+ start = Time.now
20
+
21
+ EM.add_timer(0.5){
22
+ (Time.now-start).should be_close( 0.5, 0.1 )
23
+ done
24
+ }
25
+ end
26
+ end
27
+ end
28
+ The other option is to include EM::Spec in your describe block. This will patch Rspec so that all of your examples run inside an em block automatically:
29
+ require "em-spec/rspec"
30
+ describe EventMachine do
31
+ include EM::Spec
32
+
33
+ it "requires a call to #done every time" do
34
+ 1.should == 1
35
+ done
36
+ end
37
+
38
+ it "runs test code in an em block automatically" do
39
+ start = Time.now
40
+
41
+ EM.add_timer(0.5){
42
+ (Time.now-start).should be_close( 0.5, 0.1 )
43
+ done
44
+ }
45
+ end
46
+ end
47
+
48
+ =Bacon
49
+ The API is identical to Bacon, except that you must explicitly call 'done' after all the current behavior's assertions have been made:
50
+
51
+ require 'em-spec/bacon'
52
+
53
+ EM.describe EventMachine do
54
+
55
+ should 'have timers' do
56
+ start = Time.now
57
+
58
+ EM.add_timer(0.5){
59
+ (Time.now-start).should.be.close 0.5, 0.1
60
+ done
61
+ }
62
+ end
63
+
64
+ should 'have periodic timers' do
65
+ num = 0
66
+ start = Time.now
67
+
68
+ timer = EM.add_periodic_timer(0.5){
69
+ if (num += 1) == 2
70
+ (Time.now-start).should.be.close 1.0, 0.1
71
+ EM.__send__ :cancel_timer, timer
72
+ done
73
+ end
74
+ }
75
+ end
76
+
77
+ end
78
+
79
+
80
+ Resources:
81
+
82
+ * Git repository: http://github.com/tmm1/em-spec
83
+ * Bacon: http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/30b07b651b0662fd
84
+ * Initial announcement: http://groups.google.com/group/eventmachine/browse_thread/thread/8b4e7ead72f9d013
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ task :gem => :gemspec do
2
+ sh 'gem build em-spec.gemspec'
3
+ end
4
+
5
+ task :gemspec do
6
+
7
+ end
8
+
9
+ task :install => :gem do
10
+ sh 'sudo gem install em-spec-*.gem'
11
+ end
12
+
13
+ task :default => :gem
14
+
15
+ task :spec do
16
+ sh 'bacon test/bacon_spec.rb'
17
+ sh 'spec -f specdoc test/rspec_spec.rb test/rspec_fail_examples.rb'
18
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/../ext/fiber18'
2
+ require 'rubygems'
3
+ require 'eventmachine'
4
+
5
+ module EventMachine
6
+
7
+ def self.spec_backend=( backend )
8
+ @spec_backend = backend
9
+ end
10
+
11
+ def self.spec_backend
12
+ @spec_backend
13
+ end
14
+
15
+ def self.spec *args, &blk
16
+ raise ArgumentError, 'block required' unless block_given?
17
+ raise 'EventMachine reactor already running' if EM.reactor_running?
18
+
19
+ spec_backend.spec( args, blk )
20
+ end
21
+ class << self; alias :describe :spec; end
22
+
23
+ def self.bacon( *args, &block )
24
+ require File.dirname(__FILE__) + '/spec/bacon'
25
+ self.spec_backend = EventMachine::Spec::Bacon
26
+ self.spec( args, &block )
27
+ end
28
+
29
+ end
30
+
31
+ module EventMachine
32
+ module Spec
33
+ module Bacon
34
+
35
+ def self.spec( args, blk )
36
+ EM.run do
37
+ ::Bacon.summary_on_exit
38
+ ($em_spec_fiber = Fiber.new{
39
+ ::Bacon::FiberedContext.new(args.join(' '), &blk).run
40
+ EM.stop_event_loop
41
+ }).resume
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+
49
+ class Bacon::FiberedContext < Bacon::Context
50
+ def it *args
51
+ super{
52
+ if block_given?
53
+ yield
54
+ Fiber.yield
55
+ end
56
+ }
57
+ end
58
+
59
+ def done
60
+ EM.next_tick{
61
+ :done.should == :done
62
+ $em_spec_fiber.resume if $em_spec_fiber
63
+ }
64
+ end
65
+ end
@@ -0,0 +1,55 @@
1
+ require 'eventmachine'
2
+ require File.dirname(__FILE__) + '/../ext/fiber18'
3
+
4
+ module EventMachine
5
+ module SpecHelper
6
+
7
+ def em(&block)
8
+
9
+ EM.run do
10
+ em_spec_exception = nil
11
+ @_em_spec_fiber = Fiber.new do
12
+ begin
13
+ block.call
14
+ rescue Exception => em_spec_exception
15
+ done
16
+ end
17
+ Fiber.yield
18
+ end
19
+
20
+ @_em_spec_fiber.resume
21
+
22
+ raise em_spec_exception if em_spec_exception
23
+ end
24
+ end
25
+
26
+ def done
27
+ EM.next_tick{
28
+ finish_em_spec_fiber
29
+ }
30
+ end
31
+
32
+ private
33
+
34
+ def finish_em_spec_fiber
35
+ EM.stop_event_loop if EM.reactor_running?
36
+ @_em_spec_fiber.resume if @_em_spec_fiber.alive?
37
+ end
38
+
39
+ end
40
+
41
+ module Spec
42
+
43
+ include SpecHelper
44
+
45
+ def instance_eval(&block)
46
+ em do
47
+ super(&block)
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+
@@ -0,0 +1,81 @@
1
+ # Poor Man's Fiber (API compatible Thread based Fiber implementation for Ruby 1.8)
2
+ # (c) 2008 Aman Gupta (tmm1)
3
+
4
+ unless defined? Fiber
5
+ require 'thread'
6
+
7
+ class FiberError < StandardError; end
8
+
9
+ class Fiber
10
+ def initialize
11
+ raise ArgumentError, 'new Fiber requires a block' unless block_given?
12
+
13
+ @yield = Queue.new
14
+ @resume = Queue.new
15
+
16
+ @thread = Thread.new{ @yield.push [ *yield(*@resume.pop) ] }
17
+ @thread.abort_on_exception = true
18
+ @thread[:fiber] = self
19
+ end
20
+ attr_reader :thread
21
+
22
+ def alive?
23
+ @thread.alive?
24
+ end
25
+
26
+ def resume *args
27
+ raise FiberError, 'dead fiber called' unless @thread.alive?
28
+ raise FiberError, 'double resume' if @thread == Thread.current
29
+ @resume.push(args)
30
+ result = @yield.pop
31
+ result.size > 1 ? result : result.first
32
+ end
33
+
34
+ def resume!
35
+ @resume.push []
36
+ end
37
+
38
+ def yield *args
39
+ @yield.push(args)
40
+ result = @resume.pop
41
+ result.size > 1 ? result : result.first
42
+ end
43
+
44
+ def self.yield *args
45
+ raise FiberError, "can't yield from root fiber" unless fiber = Thread.current[:fiber]
46
+ fiber.yield(*args)
47
+ end
48
+
49
+ def self.current
50
+ Thread.current[:fiber] or raise FiberError, 'not inside a fiber'
51
+ end
52
+
53
+ def inspect
54
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
55
+ end
56
+ end
57
+ else
58
+ require 'fiber'
59
+ end
60
+
61
+ if __FILE__ == $0
62
+ f = Fiber.new{ puts 'hi'; p Fiber.yield(1); puts 'bye'; :done }
63
+ p f.resume
64
+ p f.resume(2)
65
+ end
66
+
67
+ __END__
68
+
69
+ $ ruby fbr.rb
70
+ hi
71
+ 1
72
+ 2
73
+ bye
74
+ :done
75
+
76
+ $ ruby1.9 fbr.rb
77
+ hi
78
+ 1
79
+ 2
80
+ bye
81
+ :done
@@ -0,0 +1,51 @@
1
+ require 'bacon'
2
+ require File.dirname(__FILE__) + '/../lib/em-spec/bacon'
3
+
4
+ EM.spec_backend = EventMachine::Spec::Bacon
5
+
6
+ describe 'Bacon' do
7
+ should 'work as normal outside EM.describe' do
8
+ 1.should == 1
9
+ end
10
+ end
11
+
12
+ EM.describe EventMachine do
13
+ should 'work' do
14
+ done
15
+ end
16
+
17
+ should 'have timers' do
18
+ start = Time.now
19
+
20
+ EM.add_timer(0.5){
21
+ (Time.now-start).should.be.close 0.5, 0.1
22
+ done
23
+ }
24
+ end
25
+
26
+ should 'have periodic timers' do
27
+ num = 0
28
+ start = Time.now
29
+
30
+ timer = EM.add_periodic_timer(0.5){
31
+ if (num += 1) == 2
32
+ (Time.now-start).should.be.close 1.0, 0.1
33
+ EM.__send__ :cancel_timer, timer
34
+ done
35
+ end
36
+ }
37
+ end
38
+
39
+ should 'have deferrables' do
40
+ defr = EM::DefaultDeferrable.new
41
+ defr.timeout(1)
42
+ defr.errback{
43
+ done
44
+ }
45
+ end
46
+
47
+ # it "should not block on failure" do
48
+ # 1.should == 2
49
+ # end
50
+
51
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../lib/em-spec/rspec'
2
+
3
+ describe EventMachine, "when running failing examples" do
4
+ include EM::Spec
5
+
6
+ it "should not bubble failures beyond rspec" do
7
+ EM.add_timer(0.1) do
8
+ :should_not_bubble.should == :failures
9
+ done
10
+ end
11
+ end
12
+
13
+ it "should not block on failure" do
14
+ 1.should == 2
15
+ end
16
+
17
+
18
+ end
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + '/../lib/em-spec/rspec'
2
+
3
+ describe 'Rspec' do
4
+ it 'should work as normal outside EM.describe' do
5
+ 1.should == 1
6
+ end
7
+ end
8
+
9
+ describe EventMachine, "when testing with EM::SpecHelper" do
10
+ include EM::SpecHelper
11
+
12
+ it "should not require a call to done when #em is not used" do
13
+ 1.should == 1
14
+ end
15
+
16
+ it "should have timers" do
17
+ em do
18
+ start = Time.now
19
+
20
+ EM.add_timer(0.5){
21
+ (Time.now-start).should be_close( 0.5, 0.1 )
22
+ done
23
+ }
24
+ end
25
+ end
26
+ end
27
+
28
+ describe EventMachine, "when testing with EM::Spec" do
29
+ include EM::Spec
30
+
31
+ it 'should work' do
32
+ done
33
+ end
34
+
35
+ it 'should have timers' do
36
+ start = Time.now
37
+
38
+ EM.add_timer(0.5){
39
+ (Time.now-start).should be_close( 0.5, 0.1 )
40
+ done
41
+ }
42
+ end
43
+
44
+ it 'should have periodic timers' do
45
+ num = 0
46
+ start = Time.now
47
+
48
+ timer = EM.add_periodic_timer(0.5){
49
+ if (num += 1) == 2
50
+ (Time.now-start).should be_close( 1.0, 0.1 )
51
+ EM.__send__ :cancel_timer, timer
52
+ done
53
+ end
54
+ }
55
+ end
56
+
57
+ it 'should have deferrables' do
58
+ defr = EM::DefaultDeferrable.new
59
+ defr.timeout(1)
60
+ defr.errback{
61
+ done
62
+ }
63
+ end
64
+
65
+ end
66
+
67
+ describe "Rspec", "when running an example group after another group that uses EMSpec " do
68
+ it "should work normally" do
69
+ :does_not_hang.should_not be_false
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: danielsdeleo-em-spec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Aman Gupta
8
+ - "Lourens Naud\xC3\xA9"
9
+ - Daniel DeLeo
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2009-04-20 00:00:00 -07:00
15
+ default_executable:
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: eventmachine
19
+ type: :runtime
20
+ version_requirement:
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 0.12.6
26
+ version:
27
+ - !ruby/object:Gem::Dependency
28
+ name: bacon
29
+ type: :runtime
30
+ version_requirement:
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 1.1.0
36
+ version:
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ type: :runtime
40
+ version_requirement:
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 1.1.12
46
+ version:
47
+ description: Rspec and Bacon based BDD API for Ruby/EventMachine
48
+ email: em-spec@tmm1.net
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - README.rdoc
57
+ - Rakefile
58
+ - lib/em-spec/bacon.rb
59
+ - lib/em-spec/rspec.rb
60
+ - lib/ext/fiber18.rb
61
+ - test/bacon_spec.rb
62
+ - test/rspec_spec.rb
63
+ - test/rspec_fail_examples.rb
64
+ has_rdoc: false
65
+ homepage: http://github.com/tmm1/em-spec
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.2.0
87
+ signing_key:
88
+ specification_version: 2
89
+ summary: Bacon based BDD API for Ruby/EventMachine
90
+ test_files: []
91
+