danielsdeleo-em-spec 0.1.3
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/README.rdoc +84 -0
- data/Rakefile +18 -0
- data/lib/em-spec/bacon.rb +65 -0
- data/lib/em-spec/rspec.rb +55 -0
- data/lib/ext/fiber18.rb +81 -0
- data/test/bacon_spec.rb +51 -0
- data/test/rspec_fail_examples.rb +18 -0
- data/test/rspec_spec.rb +71 -0
- metadata +91 -0
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
|
+
|
data/lib/ext/fiber18.rb
ADDED
@@ -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
|
data/test/bacon_spec.rb
ADDED
@@ -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
|
data/test/rspec_spec.rb
ADDED
@@ -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
|
+
|