stella 0.8.2.003 → 0.8.3.001

Sign up to get free protection for your applications and to get access to all the features.
data/lib/stella/engine.rb CHANGED
@@ -34,8 +34,6 @@ module Stella::Engine
34
34
  @logdir = nil
35
35
  end
36
36
 
37
- @@client_limit = 1000
38
-
39
37
  def update(*args)
40
38
  what, *args = args
41
39
  if respond_to?("update_#{what}")
@@ -49,69 +47,7 @@ module Stella::Engine
49
47
  def runid(plan)
50
48
  args = [Stella.sysinfo.hostname, Stella.sysinfo.user]
51
49
  args.push Stella::START_TIME, plan
52
- args.digest
53
- end
54
-
55
- def log_dir(plan, file=nil)
56
- stamp = Stella::START_TIME.strftime("%Y%m%d-%H-%M-%S")
57
- stamp <<"-#{plan.digest.shorter}"
58
- #stamp << "STAMP"
59
- l = File.join Stella::Config.project_dir, 'log', stamp
60
- FileUtils.mkdir_p l unless File.exists? l
61
- l
62
- end
63
-
64
- def log_path(plan, file)
65
- File.join log_dir(plan), file
66
- end
67
-
68
- def process_options!(plan, opts={})
69
- # Plan must be frozen before running (see freeze methods)
70
- plan.frozen? || plan.freeze
71
-
72
- opts = {
73
- :hosts => [],
74
- :clients => 1,
75
- :duration => 0,
76
- :nowait => false,
77
- :arrival => nil,
78
- :repetitions => 1
79
- }.merge! opts
80
-
81
- Stella.ld " Options: #{opts.inspect}"
82
-
83
- unless Array === opts[:hosts]
84
- opts[:hosts] = [opts[:hosts]]
85
- end
86
-
87
- opts[:hosts].collect! do |host|
88
- if URI::Generic === host
89
- host
90
- else
91
- URI.parse host
92
- end
93
- end
94
-
95
- opts[:clients] &&= opts[:clients].to_i
96
- opts[:duration] &&= opts[:duration].to_i
97
- opts[:arrival] &&= opts[:arrival].to_f
98
- opts[:repetitions] &&= opts[:repetitions].to_i
99
- opts[:clients] = plan.usecases.size if opts[:clients] < plan.usecases.size
100
-
101
- if opts[:clients] > @@client_limit
102
- Stella.stdout.info2 "Client limit is #{@@client_limit}"
103
- opts[:clients] = @@client_limit
104
- end
105
-
106
- # Parses 60m -> 3600. See mixins.
107
- if opts[:duration].in_seconds.nil?
108
- raise Stella::WackyDuration, opts[:duration]
109
- end
110
-
111
- opts[:duration] = opts[:duration].in_seconds
112
-
113
- Stella.stdout.info3 " Hosts: " << opts[:hosts].join(', ')
114
- opts
50
+ args.id
115
51
  end
116
52
 
117
53
 
@@ -147,43 +83,214 @@ module Stella::Engine
147
83
  end
148
84
 
149
85
  class Stella::Testrun < Storable
150
- extend Attic
151
- attic :remote_digest
152
- field :samples => Array
153
- field :plan
154
- field :stats
155
- field :hosts
156
- field :events
157
- field :mode # (f)unctional or (l)oad
86
+ CLIENT_LIMIT = 1000
87
+ include Gibbler::Complex
88
+ field :id => String, &gibbler_id_processor
89
+ field :status => String
90
+ field :userid => String
91
+ field :start_time => Integer
158
92
  field :clients => Integer
159
93
  field :duration => Integer
160
94
  field :arrival => Float
161
95
  field :repetitions => Integer
162
- field :nowait => Integer
163
- def initialize(plan, events, opts={})
164
- @plan, @events = plan, events
165
- @samples, @stats = nil, nil
166
- opts.each_pair do |n,v|
167
- self.send("#{n}=", v) if has_field? n
96
+ field :wait => Float
97
+ field :nowait => TrueClass
98
+ field :withparam => TrueClass
99
+ field :withheader => TrueClass
100
+ field :notemplates => TrueClass
101
+ field :nostats => TrueClass
102
+ field :stats => Hash
103
+ field :samples => Array
104
+ field :mode # verify or generate
105
+ field :plan
106
+ field :hosts
107
+ field :events
108
+ field :log
109
+ gibbler :plan, :hosts, :mode, :clients, :duration, :repetitions, :wait, :start_time, :userid
110
+ def initialize(plan=nil, opts={})
111
+ @plan = plan
112
+ process_options! opts if !plan.nil? && !opts.empty?
113
+ reset_stats
114
+ end
115
+ def id
116
+ @id || self.digest
117
+ end
118
+ def has_log?() !@log.nil? && !@log.empty? end
119
+ def self.from_hash(hash={})
120
+ me = super(hash)
121
+ me.plan = Stella::Testplan.from_hash(me.plan)
122
+ me.process_options! unless me.plan.nil?
123
+
124
+ me.samples.collect! do |sample|
125
+ Stella::Testrun::Sample.from_hash(sample)
126
+ end
127
+
128
+ me.plan.usecases.uniq.each_with_index do |uc,i|
129
+ uc.requests.each do |req|
130
+ me.events.each_with_index do |event,idx| # do_request, etc...
131
+ event &&= event.to_s
132
+ me.stats[uc.id][req.id][event] =
133
+ Benelux::Stats::Calculator.from_hash(me.stats[uc.id][req.id][event])
134
+ me.stats[uc.id]['summary'][event] =
135
+ Benelux::Stats::Calculator.from_hash(me.stats[uc.id]['summary'][event])
136
+ me.stats['summary'][event] =
137
+ Benelux::Stats::Calculator.from_hash(me.stats['summary'][event])
138
+ end
139
+ end
140
+ end
141
+
142
+ me
143
+ end
144
+
145
+ def client_options
146
+ opts = {
147
+ :nowait => self.nowait || false,
148
+ :notemplates => self.notemplates || false,
149
+ :withparam => self.withparam || false,
150
+ :withheader => self.withheader || false,
151
+ :wait => self.wait || 0
152
+ }
153
+ end
154
+
155
+ def process_options!(opts={})
156
+
157
+ unless opts.empty?
158
+ opts = {
159
+ :hosts => [],
160
+ :clients => 1,
161
+ :duration => 0,
162
+ :wait => 0,
163
+ :nowait => false,
164
+ :arrival => nil,
165
+ :repetitions => 1,
166
+ :mode => :verify
167
+ }.merge! opts
168
+
169
+ opts.each_pair do |n,v|
170
+ self.send("#{n}=", v) if has_field? n
171
+ end
172
+
173
+ Stella.ld " Options: #{opts.inspect}"
168
174
  end
169
- reset
175
+
176
+ @id &&= Gibbler::Digest.new(@id)
177
+
178
+ @samples ||= []
179
+ @stats ||= { :summary => {} }
180
+
181
+ @status ||= "new"
182
+ @events ||= [:response_time, :failed]
183
+
184
+ @start_time ||= Time.now.to_i
185
+
186
+ @events.collect! { |event| event.to_sym }
187
+
188
+ @duration ||= 0
189
+ @repetitions ||= 0
190
+
191
+ @clients &&= @clients.to_i
192
+ @duration &&= @duration.to_i
193
+ @arrival &&= @arrival.to_f
194
+ @repetitions &&= @repetitions.to_i
195
+ @wait &&= @wait.to_f
196
+
197
+ @mode &&= @mode.to_sym
198
+
199
+ @hosts = [@hosts] unless Array === @hosts
200
+
201
+ @hosts.collect! do |host|
202
+ host.to_s
203
+ end
204
+
205
+ if @clients > CLIENT_LIMIT
206
+ Stella.stdout.info2 "Client limit is #{CLIENT_LIMIT}"
207
+ @clients = CLIENT_LIMIT
208
+ end
209
+
210
+ # Parses 60m -> 3600. See mixins.
211
+ @duration = @duration.in_seconds
212
+
213
+ raise Stella::WackyDuration, @duration if @duration.nil?
214
+
215
+ @mode &&= @mode.to_sym
216
+
217
+ unless [:verify, :generate].member?(@mode)
218
+ raise Stella::Error, "Unsupported mode: #{@mode}"
219
+ end
220
+
221
+ if Hash === self.plan # When reconstituting from JSON
222
+ self.plan = Stella::Testplan.from_hash(self.plan)
223
+ end
224
+
225
+ if Stella::Testplan === self.plan
226
+ # Plan must be frozen before running (see freeze methods)
227
+ self.plan.frozen? || self.plan.freeze
228
+ @clients = plan.usecases.size if @clients < plan.usecases.size
229
+ end
230
+
231
+ @id ||= self.gibbler # populate id
232
+
233
+ end
234
+
235
+ def freeze
236
+ return if frozen?
237
+ Stella.ld "FREEZE TESTRUN: #{self.id}"
238
+ plan.freeze
239
+ super
240
+ self
170
241
  end
171
242
 
172
- def save(path)
173
- Stella::Utils.write_to_file(path, self.to_json, 'w', 0644)
243
+ def log_dir
244
+ # Don't use @start_time here b/c that won't be set
245
+ # until just before the actual testing starts.
246
+ stamp = Stella::START_TIME.strftime("%Y%m%d-%H-%M-%S")
247
+ stamp << "-#{self.plan.id.shorter}" unless self.plan.nil?
248
+ l = File.join Stella::Config.project_dir, 'log', stamp
249
+ FileUtils.mkdir_p l unless File.exists?(l) || Stella::Logger.disabled?
250
+ l
174
251
  end
175
252
 
176
- def reset
253
+ def log_path(file)
254
+ File.join log_dir, file
255
+ end
256
+
257
+
258
+ def run(opts={})
259
+ engine = case self.mode
260
+ when :verify
261
+ Stella::Engine::Functional.new(opts)
262
+ when :generate
263
+ Stella::Engine::Load.new(opts)
264
+ else
265
+ raise Stella::Error, "Unsupported mode: #{self.mode}"
266
+ end
267
+ engine.run self
268
+ @status = "done"
269
+ self.freeze
270
+ self
271
+ end
272
+
273
+ def save
274
+ unless Stella::Logger.disabled?
275
+ path = log_path('stats')
276
+ Stella::Utils.write_to_file(path, self.to_json, 'w', 0644)
277
+ end
278
+ end
279
+
280
+ def reset_stats
177
281
  @samples = []
178
- @stats = { :summary => {} }
179
- @plan.usecases.each do |uc|
180
- @events.each do |event|
181
- @stats[:summary][event] = Benelux::Stats::Calculator.new
182
- @stats[uc.digest] ||= { :summary => {} }
183
- @stats[uc.digest][:summary][event] = Benelux::Stats::Calculator.new
184
- uc.requests.each do |req|
185
- @stats[uc.digest][req.digest] ||= {}
186
- @stats[uc.digest][req.digest][event] = Benelux::Stats::Calculator.new
282
+ @stats = { 'summary' => {} }
283
+ unless @plan.nil?
284
+ @plan.usecases.each do |uc|
285
+ @events.each do |event|
286
+ event &&= event.to_s
287
+ @stats['summary'][event] = Benelux::Stats::Calculator.new
288
+ @stats[uc.id] ||= { 'summary' => {} }
289
+ @stats[uc.id]['summary'][event] = Benelux::Stats::Calculator.new
290
+ uc.requests.each do |req|
291
+ @stats[uc.id][req.id] ||= {}
292
+ @stats[uc.id][req.id][event] = Benelux::Stats::Calculator.new
293
+ end
187
294
  end
188
295
  end
189
296
  end
@@ -201,32 +308,24 @@ class Stella::Testrun < Storable
201
308
  sam = Stella::Testrun::Sample.new opts
202
309
 
203
310
  @plan.usecases.uniq.each_with_index do |uc,i|
204
- sam.stats[uc.digest] ||= { }
311
+ sam.stats[uc.id] ||= { }
205
312
  uc.requests.each do |req|
206
- sam.stats[uc.digest][req.digest] ||= {}
207
- filter = [uc.digest, req.digest]
313
+ sam.stats[uc.id][req.id] ||= {}
314
+ filter = [uc.id, req.id]
208
315
  @events.each_with_index do |event,idx| # do_request, etc...
209
- stats = tl.stats.group(event)[filter].merge
210
- sam.stats[uc.digest][req.digest][event] = stats
316
+ event &&= event.to_s
317
+ stats = tl.stats.group(event.to_sym)[filter].merge
318
+ sam.stats[uc.id][req.id][event] = stats
211
319
  # Tally request, usecase and total summaries at the same time.
212
- @stats[uc.digest][req.digest][event] += stats
213
- @stats[uc.digest][:summary][event] += stats
214
- @stats[:summary][event] += stats
320
+ @stats[uc.id][req.id][event] += stats
321
+ @stats[uc.id]['summary'][event] += stats
322
+ @stats['summary'][event] += stats
215
323
  end
216
324
  end
217
325
  end
218
326
 
219
327
  @samples << sam
220
328
 
221
- begin
222
- if Stella::Engine.service
223
- Stella::Engine.service.testrun_stats @stats, @samples
224
- end
225
- rescue => ex
226
- Stella.stdout.info "Error syncing to #{Stella::Engine.service.source}"
227
- Stella.stdout.info ex.message, ex.backtrace if Stella.debug?
228
- end
229
-
230
329
  sam
231
330
  end
232
331
 
@@ -244,5 +343,21 @@ class Stella::Testrun < Storable
244
343
  end
245
344
  @stats = { }
246
345
  end
346
+ def self.from_hash(hash={})
347
+ me = super(hash)
348
+ stats = {}
349
+ me.stats.each_pair { |ucid,uchash|
350
+ stats[ucid] = {}
351
+ uchash.each_pair { |reqid,reqhash|
352
+ stats[ucid][reqid] = {}
353
+ reqhash.each_pair { |event,stat|
354
+ tmp = Benelux::Stats::Calculator.from_hash(stat)
355
+ stats[ucid][reqid][event] = tmp
356
+ }
357
+ }
358
+ }
359
+ me.stats = stats
360
+ me
361
+ end
247
362
  end
248
363
  end
data/lib/stella/logger.rb CHANGED
@@ -8,18 +8,20 @@ module Stella
8
8
  attr_accessor :lev
9
9
  attr_reader :templates
10
10
 
11
+ @@disable = false
12
+ class << self
13
+ def disable!() @@disable = true end
14
+ def enable!() @@disable = true end
15
+ def disabled?() @@disable == true end
16
+ end
17
+
11
18
  def initialize(output=STDOUT)
12
19
  @mutex, @buffer = Mutex.new, StringIO.new
13
20
  @lev, @offset = 1, 0
14
21
  @templates = {}
15
22
  @autoflush = false
16
- @disable = false
17
23
  self.output = output
18
24
  end
19
-
20
- def disable!() @disable = true end
21
- def enable!() @disable = true end
22
- def disabled?() @disable == true end
23
25
 
24
26
  def autoflush!() @autoflush = true end
25
27
  def autoflush?() @autoflush == true end
@@ -37,14 +39,14 @@ module Stella
37
39
  end
38
40
 
39
41
  def print(level, *msg)
40
- return if level > @lev || disabled?
42
+ return if level > @lev || self.class.disabled?
41
43
  @buffer.print *msg
42
44
  flush if autoflush?
43
45
  true
44
46
  end
45
47
 
46
48
  def puts(level, *msg)
47
- return if level > @lev || disabled?
49
+ return if level > @lev || self.class.disabled?
48
50
  @buffer.puts *msg
49
51
  flush if autoflush?
50
52
  true
@@ -73,6 +75,7 @@ module Stella
73
75
  end
74
76
 
75
77
  def output=(o)
78
+ return if self.class.disabled?
76
79
  @mutex.synchronize do
77
80
  if o.kind_of? String
78
81
  o = File.open(o, File::CREAT|File::TRUNC|File::RDWR, 0644)
@@ -83,7 +86,7 @@ module Stella
83
86
 
84
87
  # TODO: There's a big when using print (no newline)
85
88
  def flush
86
- return if disabled?
89
+ return if self.class.disabled?
87
90
  @mutex.synchronize do
88
91
  #return if @offset == @output.tell
89
92
  @buffer.seek @offset
@@ -99,7 +102,7 @@ module Stella
99
102
  end
100
103
 
101
104
  def clear
102
- return if disabled?
105
+ return if self.class.disabled?
103
106
  flush
104
107
  @mutex.synchronize do
105
108
  @buffer.rewind
@@ -108,7 +111,7 @@ module Stella
108
111
  end
109
112
 
110
113
  def close
111
- return if disabled?
114
+ return if self.class.disabled?
112
115
  flush
113
116
  @buffer.close
114
117
  @output.close
@@ -120,7 +123,7 @@ module Stella
120
123
  # Must call flush to send to output.
121
124
  class SyncLogger < Logger
122
125
  def print(level, *msg)
123
- return if level > @lev || disabled?
126
+ return if level > @lev || self.class.disabled?
124
127
  @mutex.synchronize {
125
128
  @buffer.print *msg
126
129
  flush if autoflush?
@@ -130,7 +133,7 @@ module Stella
130
133
 
131
134
  def puts(level, *msg)
132
135
  #Stella.ld [level, @lev, msg]
133
- return if level > @lev || disabled?
136
+ return if level > @lev || self.class.disabled?
134
137
  @mutex.synchronize {
135
138
  @buffer.puts *msg
136
139
  flush if autoflush?
@@ -32,14 +32,14 @@ class Testplan < Storable
32
32
  attic :plan_path
33
33
  attic :description
34
34
 
35
- field :id, &gibbler_id_processor
35
+ field :id => String, &gibbler_id_processor
36
36
 
37
- field :usecases
38
- field :description
37
+ field :usecases => Array
38
+ field :description => String
39
39
  #field :resources
40
40
 
41
41
  # TODO: Add Stellar::TOKEN to the calculation
42
- gibbler :id, :usecases, :description
42
+ gibbler :usecases
43
43
 
44
44
  def initialize(*uris)
45
45
  uris.flatten!
@@ -84,12 +84,23 @@ class Testplan < Storable
84
84
 
85
85
  # make sure all clients share identical test plans
86
86
  def freeze
87
+ return if frozen?
87
88
  Stella.ld "FREEZE TESTPLAN: #{self.description}"
88
89
  @usecases.each { |uc| uc.freeze }
89
90
  super
90
91
  self
91
92
  end
92
93
 
94
+ def id
95
+ Gibbler::Digest.new(@id || self.digest)
96
+ end
97
+
98
+ def self.from_hash(*args)
99
+ me = super(*args)
100
+ me.usecases.collect! { |uc| Stella::Testplan::Usecase.from_hash(uc) }
101
+ me
102
+ end
103
+
93
104
  def usecase(*args, &blk)
94
105
  return @usecases if args.empty? && blk.nil?
95
106
  ratio, name = nil,nil
@@ -189,16 +200,16 @@ class Testplan
189
200
  attic :base_path # we don't want gibbler to see this
190
201
  attic :plan_path
191
202
 
192
- field :id, &gibbler_id_processor
203
+ field :id => String, &gibbler_id_processor
193
204
 
194
205
  attic :description
195
- field :description
206
+ field :description => String
196
207
 
197
- field :ratio
198
- field :http_auth
199
- field :timeout
200
- field :requests
201
- field :resources
208
+ field :ratio => Float
209
+ field :http_auth => Hash
210
+ field :timeout => Float
211
+ field :requests => Array
212
+ field :resources => Hash
202
213
 
203
214
  class UnknownResource < Stella::Error
204
215
  def message; "UnknownResource: #{@obj}"; end
@@ -209,6 +220,17 @@ class Testplan
209
220
  instance_eval &blk unless blk.nil?
210
221
  end
211
222
 
223
+ def id
224
+ Gibbler::Digest.new(@id || self.digest)
225
+ end
226
+
227
+ def self.from_hash(hash={})
228
+ me = super(hash)
229
+ me.requests.collect! { |req| Stella::Data::HTTP::Request.from_hash(req) }
230
+ me
231
+ end
232
+
233
+
212
234
  def desc(*args)
213
235
  self.description = args.first unless args.empty?
214
236
  self.description
@@ -276,7 +298,9 @@ class Testplan
276
298
  end
277
299
 
278
300
  def freeze
301
+ return if frozen?
279
302
  @requests.each { |r| r.freeze }
303
+ self.id ||= self.digest
280
304
  super
281
305
  self
282
306
  end
data/lib/stella.rb CHANGED
@@ -101,8 +101,8 @@ module Stella
101
101
  def abort!() @abort = true end
102
102
 
103
103
  def quiet?() @quiet == true end
104
- def enable_quiet() @quiet = true; @stdout.disable!; end
105
- def disable_quiet() @quiet = false; @stdout.enable!; end
104
+ def enable_quiet() @quiet = true; Stella::Logger.disable!; end
105
+ def disable_quiet() @quiet = false; Stella::Logger.enable!; end
106
106
 
107
107
  def add_global(n,v)
108
108
  Stella.ld "SETGLOBAL: #{n}=#{v}"
data/stella.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{stella}
8
- s.version = "0.8.2.003"
8
+ s.version = "0.8.3.001"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Delano Mandelbaum"]
12
- s.date = %q{2010-03-06}
12
+ s.date = %q{2010-03-15}
13
13
  s.default_executable = %q{stella}
14
14
  s.description = %q{Blame Stella for breaking your web application!}
15
15
  s.email = %q{delano@solutious.com}
@@ -51,7 +51,6 @@ Gem::Specification.new do |s|
51
51
  "lib/stella/engine/load.rb",
52
52
  "lib/stella/guidelines.rb",
53
53
  "lib/stella/logger.rb",
54
- "lib/stella/service.rb",
55
54
  "lib/stella/testplan.rb",
56
55
  "lib/stella/utils.rb",
57
56
  "lib/stella/utils/httputil.rb",
@@ -101,24 +100,24 @@ Gem::Specification.new do |s|
101
100
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
102
101
  s.add_runtime_dependency(%q<gibbler>, [">= 0.7.4"])
103
102
  s.add_runtime_dependency(%q<drydock>, [">= 0.6.9"])
104
- s.add_runtime_dependency(%q<benelux>, [">= 0.5.8"])
103
+ s.add_runtime_dependency(%q<benelux>, [">= 0.5.11"])
105
104
  s.add_runtime_dependency(%q<sysinfo>, [">= 0.7.3"])
106
- s.add_runtime_dependency(%q<storable>, [">= 0.6.3"])
105
+ s.add_runtime_dependency(%q<storable>, [">= 0.6.4"])
107
106
  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
108
107
  else
109
108
  s.add_dependency(%q<gibbler>, [">= 0.7.4"])
110
109
  s.add_dependency(%q<drydock>, [">= 0.6.9"])
111
- s.add_dependency(%q<benelux>, [">= 0.5.8"])
110
+ s.add_dependency(%q<benelux>, [">= 0.5.11"])
112
111
  s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
113
- s.add_dependency(%q<storable>, [">= 0.6.3"])
112
+ s.add_dependency(%q<storable>, [">= 0.6.4"])
114
113
  s.add_dependency(%q<nokogiri>, [">= 0"])
115
114
  end
116
115
  else
117
116
  s.add_dependency(%q<gibbler>, [">= 0.7.4"])
118
117
  s.add_dependency(%q<drydock>, [">= 0.6.9"])
119
- s.add_dependency(%q<benelux>, [">= 0.5.8"])
118
+ s.add_dependency(%q<benelux>, [">= 0.5.11"])
120
119
  s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
121
- s.add_dependency(%q<storable>, [">= 0.6.3"])
120
+ s.add_dependency(%q<storable>, [">= 0.6.4"])
122
121
  s.add_dependency(%q<nokogiri>, [">= 0"])
123
122
  end
124
123
  end
@@ -2,19 +2,20 @@
2
2
 
3
3
  require 'stella'
4
4
 
5
- Benelux.enable_debug
5
+ #Benelux.enable_debug
6
+ #Stella.stdout.lev = 3
6
7
 
7
8
  Stella.enable_quiet
8
- #Stella.stdout.lev = 3
9
+
9
10
  plan = Stella::Testplan.new('http://localhost:3114/search')
10
11
  opts = {
11
12
  :hosts => '',
13
+ :mode => :generate,
12
14
  :clients => 100,
13
15
  #:duration => 10
14
16
  }
15
17
 
16
- #engine = Stella::Engine::Functional.new opts
17
- engine = Stella::Engine::Load.new opts
18
- engine.run plan
18
+ testrun = Stella::Testrun.new plan, opts
19
+ testrun.run
19
20
 
20
- puts engine.testrun.stats[:summary].to_json
21
+ puts testrun.to_yaml