yawl 0.0.3 → 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/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format progress
3
+ --order random
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Yawl
2
2
 
3
- TODO: Write a gem description
3
+ Yawl is **Y**et **a**nother **w**orkflow **l**ibrary.
4
+
5
+ The target audience is for those who have workflows that are mostly sequential and don't need to create complex branching logic.
4
6
 
5
7
  ## Installation
6
8
 
@@ -18,16 +20,45 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- TODO: Write usage instructions here
23
+ The way you go about using it is:
24
+
25
+ 1. You define a set of steps where most of your logic will go
26
+
27
+ ```ruby
28
+ Yawl::Steps.set :morning_routine do
29
+ step :first_thing do
30
+ def run
31
+ puts "brush teeth"
32
+ end
33
+ end
34
+ end
35
+ ```
36
+ 2. You define a process which references set(s) of steps, this will be the name you call when you want to run the process.
37
+
38
+ ```ruby
39
+ Yawl::ProcessDefinitions.add(:wake_up) do |process|
40
+ Yawl::Steps.realize_set_on(:morning_routine)
41
+ end
42
+ ```
43
+ 3. You call the process with the name you defined in step 2, and add any variables that you need to the `Yawl::Process#config` json field.
22
44
 
23
- ## Example
45
+ ```ruby
46
+ p = Yawl::Process.create(:desired_state => "wake_up", :config => {})
47
+ p.start
48
+ ```
49
+
50
+ ## Running the Example
24
51
 
25
52
  ```
26
53
  bundle exec sequel -m migrations/ postgres://localhost/yawl_examples
54
+ bundle exec ruby examples/cook_worker.rb &
27
55
  bundle exec ruby examples/cook.rb
28
- bundle exec ruby examples/cook_worker.rb
29
56
  ```
30
57
 
58
+ ## Credit
59
+
60
+ Originally written by @dpiddy, extracted by @ricardochimal from a larger project into its own gem.
61
+
31
62
  ## Contributing
32
63
 
33
64
  1. Fork it
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
data/examples/cook.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  $:.unshift(File.expand_path(File.join(File.dirname($0), "../lib")))
2
2
 
3
- require "sequel"
4
-
5
- Sequel.connect(ENV["DATABASE_URL"] || "postgres://localhost/yawl_examples")
3
+ ENV["DATABASE_URL"] ||= "postgres://localhost/yawl_examples"
6
4
 
7
5
  require "yawl"
8
6
  require File.dirname(File.expand_path(__FILE__)) + "/steps/scrambled_eggs"
@@ -2,8 +2,7 @@
2
2
 
3
3
  $:.unshift(File.expand_path(File.join(File.dirname($0), "../lib")))
4
4
 
5
- require "sequel"
6
- Sequel.connect(ENV["DATABASE_URL"] || "postgres://localhost/yawl_examples")
5
+ ENV["DATABASE_URL"] ||= "postgres://localhost/yawl_examples"
7
6
 
8
7
  require "yawl"
9
8
  require "yawl/worker"
data/lib/yawl.rb CHANGED
@@ -7,6 +7,8 @@ end
7
7
  require "yawl/config"
8
8
  require "yawl/log"
9
9
 
10
+ require "yawl/db"
11
+
10
12
  require "yawl/process"
11
13
  require "yawl/process_definitions"
12
14
  require "yawl/step"
data/lib/yawl/config.rb CHANGED
@@ -2,13 +2,9 @@ module Yawl
2
2
  module Config
3
3
  extend self
4
4
 
5
- attr_writer :app
5
+ attr_accessor :app
6
6
  attr_accessor :deploy
7
7
 
8
- def app
9
- @app || "yawl"
10
- end
11
-
12
8
  def log_quiet?
13
9
  env("LOG_QUIET") == "1"
14
10
  end
data/lib/yawl/db.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'sequel'
2
+ require 'yawl/config'
3
+
4
+ module Yawl
5
+ DB = Sequel.connect(ENV["DATABASE_URL"].gsub('postgresql://', 'postgres://'))
6
+ DB.extension :pg_json
7
+ DB.execute("SET bytea_output TO 'escape'")
8
+
9
+ if Config.log_sequel?
10
+ require 'logger'
11
+ DB.loggers << Logger.new($stdout)
12
+ end
13
+ end
data/lib/yawl/log.rb CHANGED
@@ -10,7 +10,12 @@ module Yawl
10
10
  end
11
11
 
12
12
  def log_measure(data)
13
- measure_base = "#{Config.app}.#{data[:ns]}.#{data[:fn]}"
13
+ if Config.app
14
+ measure_base = "#{Config.app}.#{data[:ns]}.#{data[:fn]}"
15
+ else
16
+ measure_base = "#{data[:ns]}.#{data[:fn]}"
17
+ end
18
+
14
19
  begin
15
20
  t0 = Time.now
16
21
  log(data.merge(at: "start"))
@@ -28,7 +33,8 @@ module Yawl
28
33
  if Config.log_quiet?
29
34
  block.call if block
30
35
  else
31
- params = { app: Config.app }
36
+ params = { }
37
+ params[:app] = Config.app if Config.app
32
38
  params[:source] = Config.deploy if Config.deploy
33
39
  Scrolls.log(params.merge(data), &block)
34
40
  end
data/lib/yawl/process.rb CHANGED
@@ -15,7 +15,7 @@ module Yawl
15
15
  class RequestIdAttributeMismatch < RuntimeError; end
16
16
 
17
17
  def self.log(data, &block)
18
- Log.log({ ns: "process" }.merge(data), &block)
18
+ Log.log({ ns: "yawl-process" }.merge(data), &block)
19
19
  end
20
20
 
21
21
  def log(data, &block)
data/lib/yawl/setup.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'sequel'
2
2
 
3
+ require 'yawl/db'
4
+
3
5
  Sequel.extension :migration
4
6
 
5
7
  module Yawl
@@ -41,17 +43,27 @@ module Yawl
41
43
  end
42
44
  end
43
45
 
44
-
45
46
  def create!
46
- MIGRATION.apply(db, :up)
47
+ MIGRATION.apply(DB, :up)
47
48
  end
48
49
 
49
50
  def destroy!
50
- MIGRATION.apply(db, :down)
51
+ MIGRATION.apply(DB, :down)
51
52
  end
52
53
 
53
- def db
54
- Sequel.connect(ENV["DATABASE_URL"])
54
+ def create_for_test!
55
+ if DB.tables.include?(:processes)
56
+ destroy!
57
+ end
58
+ create!
59
+
60
+ require "queue_classic"
61
+ QC::Setup.drop
62
+ QC::Setup.create
63
+
64
+ require "queue_classic/later"
65
+ QC::Later::Setup.drop
66
+ QC::Later::Setup.create
55
67
  end
56
68
  end
57
69
  end
data/lib/yawl/step.rb CHANGED
@@ -22,7 +22,7 @@ module Yawl
22
22
  end
23
23
 
24
24
  def self.log(data, &block)
25
- Log.log({ ns: "step" }.merge(data), &block)
25
+ Log.log({ ns: "yawl-step" }.merge(data), &block)
26
26
  end
27
27
 
28
28
  def log(data, &block)
@@ -115,7 +115,7 @@ module Yawl
115
115
  end
116
116
 
117
117
  def log(data, &block)
118
- Log.log({ ns: "step_#{name}" }.merge(data), &block)
118
+ Log.log({ ns: "yawl-step_#{name}" }.merge(data), &block)
119
119
  end
120
120
  end
121
121
 
data/lib/yawl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yawl
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,368 @@
1
+ require "spec_helper"
2
+
3
+ describe Yawl::Step do
4
+ let(:process) {
5
+ p = Yawl::Process.create(:desired_state => "tested")
6
+ p.start
7
+ p
8
+ }
9
+ let(:step) { process.unfinished_steps.first }
10
+
11
+ before do
12
+ Yawl::ProcessDefinitions.add :tested do |process|
13
+ process.add_step(:name => "testing")
14
+ end
15
+ end
16
+
17
+ def define_successful_step
18
+ Yawl::Steps.step :testing do
19
+ def run
20
+ puts "I worked"
21
+ end
22
+ end
23
+ end
24
+
25
+ def define_failing_step
26
+ Yawl::Steps.step :testing do
27
+ def run
28
+ puts "I started"
29
+ raise "I failed"
30
+ end
31
+ end
32
+ end
33
+
34
+ def define_sigterm_step
35
+ Yawl::Steps.step :testing do
36
+ def run
37
+ puts "I started"
38
+ raise SignalException.new("SIGTERM")
39
+ end
40
+ end
41
+ end
42
+
43
+ def define_one_shot_failing_step
44
+ Yawl::Steps.step :testing do
45
+ def run
46
+ puts "I started"
47
+ raise "I failed"
48
+ end
49
+
50
+ def attempts
51
+ 1
52
+ end
53
+ end
54
+ end
55
+
56
+ def define_fatal_step
57
+ Yawl::Steps.step :testing do
58
+ def run
59
+ puts "I started"
60
+ raise Yawl::Step::Fatal
61
+ end
62
+ end
63
+ end
64
+
65
+ def define_sleepy_step
66
+ Yawl::Steps.step :testing do
67
+ def run
68
+ puts "I started"
69
+ sleep
70
+ end
71
+ end
72
+ end
73
+
74
+ def define_one_shot_sleepy_step
75
+ Yawl::Steps.step :testing do
76
+ def run
77
+ puts "I started"
78
+ sleep
79
+ end
80
+
81
+ def attempts
82
+ 1
83
+ end
84
+ end
85
+ end
86
+
87
+ describe ".execute" do
88
+ before do
89
+ define_successful_step
90
+ end
91
+
92
+ it "executes a single step by id" do
93
+ Yawl::Step.execute(step.id)
94
+
95
+ step.reload.state.should == "completed"
96
+ end
97
+ end
98
+
99
+ describe ".restart_interrupted" do
100
+ before do
101
+ define_successful_step
102
+ end
103
+
104
+ it "starts steps in the interrupted state" do
105
+ step.update(:state => "interrupted")
106
+
107
+ Yawl::Step.restart_interrupted
108
+
109
+ step.should be_queued_for_now
110
+ end
111
+ end
112
+
113
+ describe "#start" do
114
+ before do
115
+ define_successful_step
116
+ end
117
+
118
+ it "enqueues the step for immediate execution" do
119
+ step.start
120
+
121
+ step.should be_queued_for_now
122
+ end
123
+
124
+ it "resets state to pending" do
125
+ step.update(:state => "failed")
126
+
127
+ step.start
128
+
129
+ step.state.should == "pending"
130
+ end
131
+ end
132
+
133
+ context "running a successful step" do
134
+ before do
135
+ define_successful_step
136
+ end
137
+
138
+ it "sets state to completed" do
139
+ step.execute
140
+
141
+ step.state.should == "completed"
142
+ end
143
+
144
+ it "notifies the process of completion" do
145
+ step.process.should_receive(:step_finished)
146
+
147
+ step.execute
148
+ end
149
+
150
+ it "captures output" do
151
+ step.execute
152
+
153
+ step.attempts.first.output.should == "I worked\n"
154
+ end
155
+ end
156
+
157
+ context "running a failing step" do
158
+ context "that has attempts remaining" do
159
+ before do
160
+ define_failing_step
161
+ end
162
+
163
+ it "sets state to pending" do
164
+ step.execute
165
+
166
+ step.state.should == "pending"
167
+ end
168
+
169
+ it "does not notify the process of failure" do
170
+ step.process.should_not_receive(:step_failed)
171
+
172
+ step.execute
173
+ end
174
+
175
+ it "is queued for retry" do
176
+ step.execute
177
+
178
+ step.should be_queued_for_later
179
+ end
180
+
181
+ it "captures output" do
182
+ step.execute
183
+
184
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: I failed\n.*:in `.*'/ # backtrace
185
+ end
186
+ end
187
+
188
+ context "running a fatal step" do
189
+ context "that has attempts remaining" do
190
+ before do
191
+ define_fatal_step
192
+ end
193
+
194
+ it "sets state to pending" do
195
+ expect {
196
+ step.execute
197
+ }.to raise_error(Yawl::Step::Fatal)
198
+
199
+ step.state.should == "failed"
200
+ end
201
+
202
+ it "does not notify the process of failure" do
203
+ step.process.should_receive(:step_failed)
204
+
205
+ expect {
206
+ step.execute
207
+ }.to raise_error(Yawl::Step::Fatal)
208
+ end
209
+
210
+ it "is not queued for retry" do
211
+ expect {
212
+ step.execute
213
+ }.to raise_error(Yawl::Step::Fatal)
214
+
215
+ step.should_not be_queued_for_later
216
+ end
217
+
218
+ it "captures output" do
219
+ expect {
220
+ step.execute
221
+ }.to raise_error(Yawl::Step::Fatal)
222
+
223
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: Fatal error in step\n.*:in `.*'/ # backtrace
224
+ end
225
+ end
226
+ end
227
+
228
+ context "that has no attempts remaining" do
229
+ before do
230
+ define_one_shot_failing_step
231
+ end
232
+
233
+ it "passes the error through" do
234
+ expect {
235
+ step.execute
236
+ }.to raise_error("I failed")
237
+ end
238
+
239
+ it "sets state to failed" do
240
+ expect { step.execute }.to raise_error
241
+
242
+ step.state.should == "failed"
243
+ end
244
+
245
+ it "notifies the process of failure" do
246
+ step.process.should_receive(:step_failed)
247
+
248
+ expect { step.execute }.to raise_error
249
+ end
250
+
251
+ it "is not queued for retry" do
252
+ expect { step.execute }.to raise_error
253
+
254
+ step.should_not be_queued_for_later
255
+ end
256
+
257
+ it "captures output" do
258
+ expect { step.execute }.to raise_error
259
+
260
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: I failed\n.*:in `.*'/
261
+ end
262
+ end
263
+
264
+ context "that fails due to SIGTERM" do
265
+ before do
266
+ define_sigterm_step
267
+ end
268
+
269
+ it "passes the error through" do
270
+ expect {
271
+ step.execute
272
+ }.to raise_error("SIGTERM")
273
+ end
274
+
275
+ it "sets state to interrupted" do
276
+ expect { step.execute }.to raise_error
277
+
278
+ step.state.should == "interrupted"
279
+ end
280
+
281
+ it "does not notify the process of failure" do
282
+ step.process.should_not_receive(:step_failed)
283
+
284
+ expect { step.execute }.to raise_error
285
+ end
286
+
287
+ it "is not queued for retry" do
288
+ expect { step.execute }.to raise_error
289
+
290
+ step.should_not be_queued_for_later
291
+ end
292
+
293
+ it "captures output" do
294
+ expect { step.execute }.to raise_error
295
+
296
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: SIGTERM\n.*:in `.*'/ # backtrace
297
+ end
298
+ end
299
+ end
300
+
301
+ context "running a sleepy process" do
302
+ context "that has attempts remaining" do
303
+ before do
304
+ define_sleepy_step
305
+ end
306
+
307
+ it "sets state to pending" do
308
+ step.execute
309
+
310
+ step.state.should == "pending"
311
+ end
312
+
313
+ it "does not notify the process of failure" do
314
+ step.process.should_not_receive(:step_failed)
315
+
316
+ step.execute
317
+ end
318
+
319
+ it "is queued for retry" do
320
+ step.execute
321
+
322
+ step.should be_queued_for_later
323
+ end
324
+
325
+ it "captures output" do
326
+ step.execute
327
+
328
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: Step slept\n.*:in `.*'/ # backtrace
329
+ end
330
+ end
331
+
332
+ context "that has no attempts remaining" do
333
+ before do
334
+ define_one_shot_sleepy_step
335
+ end
336
+
337
+ it "passes the error through" do
338
+ expect {
339
+ step.execute
340
+ }.to raise_error(Yawl::Step::Tired)
341
+ end
342
+
343
+ it "sets state to failed" do
344
+ expect { step.execute }.to raise_error
345
+
346
+ step.state.should == "failed"
347
+ end
348
+
349
+ it "notifies the process of failure" do
350
+ step.process.should_receive(:step_failed)
351
+
352
+ expect { step.execute }.to raise_error
353
+ end
354
+
355
+ it "is not queued for retry" do
356
+ expect { step.execute }.to raise_error
357
+
358
+ step.should_not be_queued_for_later
359
+ end
360
+
361
+ it "captures output" do
362
+ expect { step.execute }.to raise_error
363
+
364
+ step.attempts.first.output.should =~ /\AI started\n\n\n---\nCAUGHT ERROR: Step slept\n.*:in `.*'/ # backtrace
365
+ end
366
+ end
367
+ end
368
+ end
@@ -0,0 +1,70 @@
1
+ if ENV["CI"]
2
+ raise "ENV[DATABASE_URL] not set" unless ENV["DATABASE_URL"]
3
+ else
4
+ ENV["DATABASE_URL"] = "postgres://localhost/yawl-test"
5
+ end
6
+ ENV["LOG_QUIET"] ||= "1"
7
+
8
+ require "rspec"
9
+ require "yawl"
10
+
11
+ require "yawl/setup"
12
+
13
+ Yawl::Setup.create_for_test!
14
+
15
+ def QC.jobs
16
+ s = "SELECT * FROM queue_classic_jobs"
17
+ [QC::Conn.execute(s)].compact.flatten.
18
+ map {|j| j.reject {|k, v| !%w[q_name method args].include?(k) } }.
19
+ map {|j| j.merge("args" => JSON.parse(j["args"])) }.
20
+ map {|j| j.reject {|k, v| k == "args" && v.empty? } }
21
+ end
22
+
23
+ def QC.later_jobs
24
+ s = "SELECT * FROM queue_classic_later_jobs"
25
+ [QC::Conn.execute(s)].compact.flatten.
26
+ map {|j| j.reject {|k, v| !%w[q_name method args].include?(k) } }.
27
+ map {|j| j.merge("args" => JSON.parse(j["args"])) }.
28
+ map {|j| j.reject {|k, v| k == "args" && v.empty? } }
29
+ end
30
+
31
+ RSpec.configure do |c|
32
+ c.around(:each) do |example|
33
+ Yawl::DB.transaction(:rollback => :always) do
34
+ begin
35
+ QC::Conn.execute("BEGIN")
36
+ example.run
37
+ ensure
38
+ QC::Conn.execute("ROLLBACK")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ RSpec::Matchers.define :be_queued_for_later do
45
+ match do |step|
46
+ QC.later_jobs.include?("q_name" => "default", "method" => "Yawl::Step.execute", "args" => [step.id])
47
+ end
48
+
49
+ failure_message_for_should do |step|
50
+ "expected #{step.inspect} to be queued for later in later jobs #{QC.later_jobs}"
51
+ end
52
+
53
+ failure_message_for_should_not do |step|
54
+ "expected #{step.inspect} to not be queued for later in later jobs #{QC.later_jobs}"
55
+ end
56
+ end
57
+
58
+ RSpec::Matchers.define :be_queued_for_now do
59
+ match do |step|
60
+ QC.jobs.include?("q_name" => "default", "method" => "Yawl::Step.execute", "args" => [step.id])
61
+ end
62
+
63
+ failure_message_for_should do |step|
64
+ "expected #{step.inspect} to be queued for now in jobs #{QC.jobs}"
65
+ end
66
+
67
+ failure_message_for_should_not do |step|
68
+ "expected #{step.inspect} to not be queued for now in jobs #{QC.jobs}"
69
+ end
70
+ end
data/yawl.gemspec CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "sequel"
22
22
  spec.add_dependency "scrolls"
23
23
  spec.add_dependency "queue_classic"
24
- spec.add_dependency "queue_classic-later"
24
+ spec.add_dependency "queue_classic-later", ">= 0.3.0"
25
25
 
26
26
  spec.add_development_dependency "bundler", "~> 1.3"
27
27
  spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rspec"
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yawl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-29 00:00:00.000000000 Z
12
+ date: 2014-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sequel
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ! '>='
68
68
  - !ruby/object:Gem::Version
69
- version: '0'
69
+ version: 0.3.0
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
- version: '0'
77
+ version: 0.3.0
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: bundler
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +107,22 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
110
126
  description: Yet Another Workflow Library for Ruby
111
127
  email:
112
128
  - kiwi@null.cx
@@ -115,6 +131,7 @@ extensions: []
115
131
  extra_rdoc_files: []
116
132
  files:
117
133
  - .gitignore
134
+ - .rspec
118
135
  - Gemfile
119
136
  - LICENSE.txt
120
137
  - README.md
@@ -124,6 +141,7 @@ files:
124
141
  - examples/steps/scrambled_eggs.rb
125
142
  - lib/yawl.rb
126
143
  - lib/yawl/config.rb
144
+ - lib/yawl/db.rb
127
145
  - lib/yawl/log.rb
128
146
  - lib/yawl/process.rb
129
147
  - lib/yawl/process_definitions.rb
@@ -135,6 +153,8 @@ files:
135
153
  - lib/yawl/worker.rb
136
154
  - migrations/01_setup_tables.rb
137
155
  - migrations/02_setup_queue_classic.rb
156
+ - spec/lib/step_spec.rb
157
+ - spec/spec_helper.rb
138
158
  - yawl.gemspec
139
159
  homepage: https://github.com/ricardochimal/yawl
140
160
  licenses:
@@ -151,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
171
  version: '0'
152
172
  segments:
153
173
  - 0
154
- hash: -1266345301425141028
174
+ hash: -3718802543540648108
155
175
  required_rubygems_version: !ruby/object:Gem::Requirement
156
176
  none: false
157
177
  requirements:
@@ -160,11 +180,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
180
  version: '0'
161
181
  segments:
162
182
  - 0
163
- hash: -1266345301425141028
183
+ hash: -3718802543540648108
164
184
  requirements: []
165
185
  rubyforge_project:
166
186
  rubygems_version: 1.8.23
167
187
  signing_key:
168
188
  specification_version: 3
169
189
  summary: Yet Another Workflow Library for Ruby
170
- test_files: []
190
+ test_files:
191
+ - spec/lib/step_spec.rb
192
+ - spec/spec_helper.rb