spectre-core 2.1.2 → 2.1.4
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.
- checksums.yaml +4 -4
- data/lib/spectre/version.rb +1 -1
- data/lib/spectre.rb +147 -112
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c4d07c24a6be8fbf1ed1ff1b4ec52860294be4b4c2d8580facf183231a3c4ed
|
|
4
|
+
data.tar.gz: 576889b489206a424462b087bc75590aa17339b918c4bc1076f072ceab2c29af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a8c17b521b0e391942bf99a2ecd41d18349b5c79b63e5e71bdd1365284d347c1c31c0315f9b62976ff0068c29248f1a009a4e6eac8e53198ce4e41a8173f8a7
|
|
7
|
+
data.tar.gz: af4a92361d63d56b269a61b088635801b158dd217c4f9bd3400b5b19a0f0e20bad314589a488be101e5204935a6ed68e7d48c771ab257e450cdb6d166edd1df5
|
data/lib/spectre/version.rb
CHANGED
data/lib/spectre.rb
CHANGED
|
@@ -20,7 +20,7 @@ def get_call_location call_stack
|
|
|
20
20
|
.find { |x| x.label.include? 'Spectre::Engine#load_files' or x.base_label == '<top (required)>' }
|
|
21
21
|
|
|
22
22
|
[
|
|
23
|
-
loc.path.sub(
|
|
23
|
+
loc.path.sub(Dir.pwd, '.'),
|
|
24
24
|
loc.lineno
|
|
25
25
|
]
|
|
26
26
|
end
|
|
@@ -78,13 +78,6 @@ end
|
|
|
78
78
|
# The main module containing all logic for the framework
|
|
79
79
|
#
|
|
80
80
|
module Spectre
|
|
81
|
-
# Cache Dir.pwd to avoid repeated system calls
|
|
82
|
-
@pwd = Dir.pwd
|
|
83
|
-
|
|
84
|
-
def self.pwd
|
|
85
|
-
@pwd
|
|
86
|
-
end
|
|
87
|
-
|
|
88
81
|
##
|
|
89
82
|
# Exception to throw in order to abort a spec run
|
|
90
83
|
#
|
|
@@ -265,13 +258,14 @@ module Spectre
|
|
|
265
258
|
counter = 0
|
|
266
259
|
|
|
267
260
|
specs
|
|
268
|
-
.group_by { |x| x.parent.root }
|
|
261
|
+
.group_by { |x| x.parent.root.name }
|
|
269
262
|
.each_value do |spec_group|
|
|
270
|
-
spec_group
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
263
|
+
spec_group
|
|
264
|
+
.sort
|
|
265
|
+
.each do |spec|
|
|
266
|
+
spec_id = "[#{spec.name}]".send(@colors[counter % @colors.length])
|
|
267
|
+
@out.puts "#{spec_id} #{spec.full_desc} #{spec.tags.map { |x| "##{x}" }.join(' ').cyan}"
|
|
268
|
+
end
|
|
275
269
|
|
|
276
270
|
counter += 1
|
|
277
271
|
end
|
|
@@ -280,15 +274,15 @@ module Spectre
|
|
|
280
274
|
##
|
|
281
275
|
# Outputs all the specs for all contexts
|
|
282
276
|
#
|
|
283
|
-
def describe contexts, level = 0
|
|
284
|
-
contexts.each do |context|
|
|
277
|
+
def describe contexts, level = 0, parent: nil
|
|
278
|
+
contexts.select { |x| x.parent == parent }.each do |context|
|
|
285
279
|
@out.puts("#{' ' * level}#{context.desc.send(level.positive? ? :magenta : :blue)}")
|
|
286
280
|
|
|
287
281
|
context.specs.each do |spec|
|
|
288
282
|
@out.puts("#{' ' * (level + 1)}#{spec.desc}")
|
|
289
283
|
end
|
|
290
284
|
|
|
291
|
-
describe(
|
|
285
|
+
describe(contexts, level + 1, parent: context)
|
|
292
286
|
end
|
|
293
287
|
end
|
|
294
288
|
|
|
@@ -327,7 +321,7 @@ module Spectre
|
|
|
327
321
|
mixins.each_value do |mixin|
|
|
328
322
|
output = "#{mixin.desc.yellow}\n"
|
|
329
323
|
output += " params.....: #{mixin.params.join ', '}\n" if mixin.params.any?
|
|
330
|
-
output += " location...: #{mixin.file.sub(
|
|
324
|
+
output += " location...: #{mixin.file.sub(Dir.pwd, '.')}:#{mixin.line}"
|
|
331
325
|
paragraphs << output
|
|
332
326
|
end
|
|
333
327
|
|
|
@@ -781,6 +775,10 @@ module Spectre
|
|
|
781
775
|
end
|
|
782
776
|
end
|
|
783
777
|
|
|
778
|
+
##
|
|
779
|
+
# The run context is passed to all specs and provides the
|
|
780
|
+
# DSL for assertions, expectations, logging, etc.
|
|
781
|
+
#
|
|
784
782
|
class RunContext
|
|
785
783
|
include Delegate
|
|
786
784
|
|
|
@@ -1164,7 +1162,7 @@ module Spectre
|
|
|
1164
1162
|
# Skip the run for this spec. This can be used to skip spec runs when a certain
|
|
1165
1163
|
# condition occurs.
|
|
1166
1164
|
#
|
|
1167
|
-
# skip 'subject is not yet ready to be
|
|
1165
|
+
# skip 'subject is not yet ready to be tested' unless service_is_ready()
|
|
1168
1166
|
#
|
|
1169
1167
|
def skip message
|
|
1170
1168
|
@skipped = true
|
|
@@ -1174,7 +1172,7 @@ module Spectre
|
|
|
1174
1172
|
end
|
|
1175
1173
|
|
|
1176
1174
|
class Specification
|
|
1177
|
-
attr_reader :id, :name, :desc, :full_desc, :parent, :root, :tags, :data, :file
|
|
1175
|
+
attr_reader :id, :name, :desc, :full_desc, :parent, :root, :tags, :data, :file, :block
|
|
1178
1176
|
|
|
1179
1177
|
def initialize parent, name, desc, tags, data, file, block
|
|
1180
1178
|
@parent = parent
|
|
@@ -1189,10 +1187,25 @@ module Spectre
|
|
|
1189
1187
|
end
|
|
1190
1188
|
|
|
1191
1189
|
##
|
|
1192
|
-
#
|
|
1193
|
-
# +before+ and +after+ blocks
|
|
1190
|
+
# Natural sort comparison for spec names respecting numeric parts.
|
|
1194
1191
|
#
|
|
1195
|
-
def
|
|
1192
|
+
def <=>(other)
|
|
1193
|
+
# Split on dash: text part and numeric part
|
|
1194
|
+
self_parts = @name.split('-')
|
|
1195
|
+
other_parts = other.name.split('-')
|
|
1196
|
+
|
|
1197
|
+
text_compare = self_parts[0] <=> other_parts[0]
|
|
1198
|
+
|
|
1199
|
+
# If the text parts are already different, we can return here
|
|
1200
|
+
return text_compare unless text_compare.zero?
|
|
1201
|
+
|
|
1202
|
+
self_parts[1].to_i <=> other_parts[1].to_i
|
|
1203
|
+
end
|
|
1204
|
+
|
|
1205
|
+
##
|
|
1206
|
+
# Execute this specification with its before/after blocks
|
|
1207
|
+
#
|
|
1208
|
+
def run(engine, befores, afters, bag)
|
|
1196
1209
|
RunContext.new(engine, self, :spec, bag) do |run_context|
|
|
1197
1210
|
engine.formatter.scope(@desc, self) do
|
|
1198
1211
|
befores.each do |block|
|
|
@@ -1220,13 +1233,14 @@ module Spectre
|
|
|
1220
1233
|
class DefinitionContext
|
|
1221
1234
|
include Delegate
|
|
1222
1235
|
|
|
1223
|
-
attr_reader :id, :name, :desc, :parent, :full_desc, :
|
|
1236
|
+
attr_reader :id, :name, :desc, :parent, :full_desc, :specs, :file,
|
|
1237
|
+
:setups, :teardowns, :befores, :afters
|
|
1224
1238
|
|
|
1225
|
-
def initialize desc, file, parent = nil
|
|
1239
|
+
def initialize desc, file, engine, parent = nil
|
|
1240
|
+
@engine = engine
|
|
1226
1241
|
@parent = parent
|
|
1227
1242
|
@desc = desc
|
|
1228
1243
|
@file = file
|
|
1229
|
-
@children = []
|
|
1230
1244
|
@specs = []
|
|
1231
1245
|
|
|
1232
1246
|
@setups = []
|
|
@@ -1239,6 +1253,8 @@ module Spectre
|
|
|
1239
1253
|
@name = @parent.name + '-' + @name unless @parent.nil?
|
|
1240
1254
|
|
|
1241
1255
|
@full_desc = @parent.nil? ? @desc : "#{@parent.full_desc} #{@desc}"
|
|
1256
|
+
|
|
1257
|
+
@engine.contexts << self
|
|
1242
1258
|
end
|
|
1243
1259
|
|
|
1244
1260
|
##
|
|
@@ -1249,10 +1265,90 @@ module Spectre
|
|
|
1249
1265
|
end
|
|
1250
1266
|
|
|
1251
1267
|
##
|
|
1252
|
-
#
|
|
1268
|
+
# Returns all direct child contexts
|
|
1253
1269
|
#
|
|
1254
|
-
def
|
|
1255
|
-
@
|
|
1270
|
+
def children
|
|
1271
|
+
@engine.contexts.select { |x| x.parent == self }
|
|
1272
|
+
end
|
|
1273
|
+
|
|
1274
|
+
##
|
|
1275
|
+
# Execute this context with its specs, setups, and teardowns.
|
|
1276
|
+
# Recursively executes child contexts using the tree structure.
|
|
1277
|
+
#
|
|
1278
|
+
def run(specs_set)
|
|
1279
|
+
runs = []
|
|
1280
|
+
|
|
1281
|
+
# Find specs in this context that should be executed
|
|
1282
|
+
selected = @specs.select { |x| specs_set.include? x }
|
|
1283
|
+
|
|
1284
|
+
# Check if any child contexts have specs to execute
|
|
1285
|
+
has_child_specs = children.any? { |child| child.specs_in_tree?(specs_set) }
|
|
1286
|
+
|
|
1287
|
+
# Skip this context if it has no matching specs and no children with specs
|
|
1288
|
+
return runs if selected.empty? && !has_child_specs
|
|
1289
|
+
|
|
1290
|
+
@engine.formatter.scope(@desc, self) do
|
|
1291
|
+
# Execute setup, specs, and teardown for this context
|
|
1292
|
+
if selected.any?
|
|
1293
|
+
setup_bag = nil
|
|
1294
|
+
|
|
1295
|
+
if @setups.any?
|
|
1296
|
+
setup_run = RunContext.new(@engine, self, :setup) do |run_context|
|
|
1297
|
+
@setups.each do |block|
|
|
1298
|
+
@engine.formatter.scope('setup', :setup) do
|
|
1299
|
+
@engine.logger.correlate do
|
|
1300
|
+
@engine.logger.debug("setup \"#{@desc}\"")
|
|
1301
|
+
run_context.execute(nil, &block)
|
|
1302
|
+
end
|
|
1303
|
+
end
|
|
1304
|
+
end
|
|
1305
|
+
end
|
|
1306
|
+
|
|
1307
|
+
setup_bag = setup_run.bag
|
|
1308
|
+
runs << setup_run
|
|
1309
|
+
end
|
|
1310
|
+
|
|
1311
|
+
# Only run specs if setup was successful
|
|
1312
|
+
if runs.all? { |x| x.status == :success }
|
|
1313
|
+
runs += selected.map do |spec|
|
|
1314
|
+
@engine.logger.correlate do
|
|
1315
|
+
spec.run(@engine, @befores, @afters, setup_bag)
|
|
1316
|
+
end
|
|
1317
|
+
end
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
if @teardowns.any?
|
|
1321
|
+
runs << RunContext.new(@engine, self, :teardown, setup_bag) do |run_context|
|
|
1322
|
+
@teardowns.each do |block|
|
|
1323
|
+
@engine.formatter.scope('teardown', :teardown) do
|
|
1324
|
+
@engine.logger.correlate do
|
|
1325
|
+
@engine.logger.debug("teardown \"#{@desc}\"")
|
|
1326
|
+
run_context.execute(nil, &block)
|
|
1327
|
+
end
|
|
1328
|
+
end
|
|
1329
|
+
end
|
|
1330
|
+
end
|
|
1331
|
+
end
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
# Recursively execute child contexts
|
|
1335
|
+
children.each do |child_context|
|
|
1336
|
+
@engine.logger.correlate do
|
|
1337
|
+
runs += child_context.run(specs_set)
|
|
1338
|
+
end
|
|
1339
|
+
end
|
|
1340
|
+
end
|
|
1341
|
+
|
|
1342
|
+
runs
|
|
1343
|
+
end
|
|
1344
|
+
|
|
1345
|
+
##
|
|
1346
|
+
# Check recursively if this context or any of its children have specs in the filter set
|
|
1347
|
+
#
|
|
1348
|
+
def specs_in_tree?(specs_set)
|
|
1349
|
+
return true if @specs.any? { |x| specs_set.include? x }
|
|
1350
|
+
|
|
1351
|
+
children.any? { |child| child.specs_in_tree?(specs_set) }
|
|
1256
1352
|
end
|
|
1257
1353
|
|
|
1258
1354
|
##
|
|
@@ -1262,10 +1358,9 @@ module Spectre
|
|
|
1262
1358
|
file = caller
|
|
1263
1359
|
.first
|
|
1264
1360
|
.gsub(/:in .*/, '')
|
|
1265
|
-
.gsub(
|
|
1361
|
+
.gsub(Dir.pwd, '.')
|
|
1266
1362
|
|
|
1267
|
-
context = DefinitionContext.new(desc, file, self)
|
|
1268
|
-
@children << context
|
|
1363
|
+
context = DefinitionContext.new(desc, file, @engine, self)
|
|
1269
1364
|
context.instance_eval(&)
|
|
1270
1365
|
end
|
|
1271
1366
|
|
|
@@ -1312,12 +1407,18 @@ module Spectre
|
|
|
1312
1407
|
file = caller
|
|
1313
1408
|
.first
|
|
1314
1409
|
.gsub(/:in .*/, '')
|
|
1315
|
-
.gsub(
|
|
1410
|
+
.gsub(Dir.pwd, '.')
|
|
1316
1411
|
|
|
1317
1412
|
with ||= [nil]
|
|
1318
1413
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1414
|
+
initial_index = @engine
|
|
1415
|
+
.contexts
|
|
1416
|
+
.select { |x| x.root.name == root.name }
|
|
1417
|
+
.flat_map(&:specs)
|
|
1418
|
+
.count + 1
|
|
1419
|
+
|
|
1420
|
+
with.each_with_index do |data, index|
|
|
1421
|
+
spec_index = initial_index + index
|
|
1321
1422
|
name = "#{root.name}-#{spec_index}"
|
|
1322
1423
|
|
|
1323
1424
|
spec = Specification.new(self, name, desc, tags, data, file, block)
|
|
@@ -1325,68 +1426,6 @@ module Spectre
|
|
|
1325
1426
|
@specs << spec
|
|
1326
1427
|
end
|
|
1327
1428
|
end
|
|
1328
|
-
|
|
1329
|
-
# :nodoc:
|
|
1330
|
-
def run engine, specs
|
|
1331
|
-
runs = []
|
|
1332
|
-
|
|
1333
|
-
return runs unless all_specs.any? { |x| specs.include? x }
|
|
1334
|
-
|
|
1335
|
-
selected = @specs.select { |x| specs.include? x }
|
|
1336
|
-
|
|
1337
|
-
engine.formatter.scope(@desc, self) do
|
|
1338
|
-
if selected.any?
|
|
1339
|
-
setup_bag = nil
|
|
1340
|
-
|
|
1341
|
-
if @setups.any?
|
|
1342
|
-
setup_run = RunContext.new(engine, self, :setup) do |run_context|
|
|
1343
|
-
@setups.each do |block|
|
|
1344
|
-
engine.formatter.scope('setup', :setup) do
|
|
1345
|
-
engine.logger.correlate do
|
|
1346
|
-
engine.logger.debug("setup \"#{@desc}\"")
|
|
1347
|
-
run_context.execute(nil, &block)
|
|
1348
|
-
end
|
|
1349
|
-
end
|
|
1350
|
-
end
|
|
1351
|
-
end
|
|
1352
|
-
|
|
1353
|
-
setup_bag = setup_run.bag
|
|
1354
|
-
|
|
1355
|
-
runs << setup_run
|
|
1356
|
-
end
|
|
1357
|
-
|
|
1358
|
-
# Only run specs if setup was successful
|
|
1359
|
-
if runs.all? { |x| x.status == :success }
|
|
1360
|
-
runs += selected.map do |spec|
|
|
1361
|
-
engine.logger.correlate do
|
|
1362
|
-
spec.run(engine, @befores, @afters, setup_bag)
|
|
1363
|
-
end
|
|
1364
|
-
end
|
|
1365
|
-
end
|
|
1366
|
-
|
|
1367
|
-
if @teardowns.any?
|
|
1368
|
-
runs << RunContext.new(engine, self, :teardown, setup_bag) do |run_context|
|
|
1369
|
-
@teardowns.each do |block|
|
|
1370
|
-
engine.formatter.scope('teardown', :teardown) do
|
|
1371
|
-
engine.logger.correlate do
|
|
1372
|
-
engine.logger.debug("teardown \"#{@desc}\"")
|
|
1373
|
-
run_context.execute(nil, &block)
|
|
1374
|
-
end
|
|
1375
|
-
end
|
|
1376
|
-
end
|
|
1377
|
-
end
|
|
1378
|
-
end
|
|
1379
|
-
end
|
|
1380
|
-
|
|
1381
|
-
@children.each do |context|
|
|
1382
|
-
engine.logger.correlate do
|
|
1383
|
-
runs += context.run(engine, specs)
|
|
1384
|
-
end
|
|
1385
|
-
end
|
|
1386
|
-
end
|
|
1387
|
-
|
|
1388
|
-
runs
|
|
1389
|
-
end
|
|
1390
1429
|
end
|
|
1391
1430
|
|
|
1392
1431
|
##
|
|
@@ -1581,9 +1620,6 @@ module Spectre
|
|
|
1581
1620
|
require module_name
|
|
1582
1621
|
end
|
|
1583
1622
|
end
|
|
1584
|
-
ensure
|
|
1585
|
-
# return to the previous working directory
|
|
1586
|
-
Dir.chdir(Spectre.pwd)
|
|
1587
1623
|
end
|
|
1588
1624
|
|
|
1589
1625
|
# :nodoc:
|
|
@@ -1609,8 +1645,7 @@ module Spectre
|
|
|
1609
1645
|
tag_filter = config['tags'] || []
|
|
1610
1646
|
|
|
1611
1647
|
@contexts
|
|
1612
|
-
.
|
|
1613
|
-
.flatten
|
|
1648
|
+
.flat_map(&:specs)
|
|
1614
1649
|
.select do |spec|
|
|
1615
1650
|
(spec_filter.empty? and tag_filter.empty?) or
|
|
1616
1651
|
spec_filter.any? { |x| spec.name.match?("^#{x.gsub('*', '.*')}$") } or
|
|
@@ -1630,12 +1665,12 @@ module Spectre
|
|
|
1630
1665
|
end
|
|
1631
1666
|
end
|
|
1632
1667
|
|
|
1633
|
-
list
|
|
1668
|
+
specs = list
|
|
1669
|
+
specs_set = Set.new(list)
|
|
1670
|
+
|
|
1671
|
+
specs
|
|
1634
1672
|
.group_by { |x| x.parent.root }
|
|
1635
|
-
.
|
|
1636
|
-
context.run(self, specs)
|
|
1637
|
-
end
|
|
1638
|
-
.flatten
|
|
1673
|
+
.flat_map { |context, _| context.run(specs_set) }
|
|
1639
1674
|
rescue Interrupt
|
|
1640
1675
|
# Do nothing here
|
|
1641
1676
|
end
|
|
@@ -1669,15 +1704,15 @@ module Spectre
|
|
|
1669
1704
|
##
|
|
1670
1705
|
# Describe a test subject
|
|
1671
1706
|
#
|
|
1672
|
-
def describe(
|
|
1707
|
+
def describe(desc, &)
|
|
1673
1708
|
file = caller
|
|
1674
1709
|
.first
|
|
1675
1710
|
.gsub(/:in .*/, '')
|
|
1676
|
-
.gsub(
|
|
1711
|
+
.gsub(Dir.pwd, '.')
|
|
1677
1712
|
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1713
|
+
DefinitionContext
|
|
1714
|
+
.new(desc, file, self)
|
|
1715
|
+
.instance_eval(&)
|
|
1681
1716
|
end
|
|
1682
1717
|
|
|
1683
1718
|
##
|