futo-spec 0.2.1 → 0.4.2
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/bin/futo +37 -7
- data/lib/exec_block_context.rb +6 -0
- data/lib/futo-spec/futo_logger.rb +13 -0
- data/lib/{spec/_glue/initialize → futo-spec/self-test/futo/_glue/mocks}/basics.setup.rb +0 -0
- data/lib/futo-spec.rb +300 -100
- data/lib/markdown_generator.rb +62 -0
- metadata +9 -67
- data/lib/spec/_glue/chizu/self.chizu +0 -39
- data/lib/spec/basics.futo +0 -16
- data/lib/spec/edge_cases.futo +0 -17
- data/lib/spec/rspec.futo +0 -4
- data/lib/spec/todos.futo +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48d8df4da9a931c852aae9634f50935faf9ca0cb0b7a2710cd84e1aa2d4324a4
|
4
|
+
data.tar.gz: b6b77baf4d97717ca952d68b4990a1dbfe6f386788aaad15e3d96676be2d538e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0cf9e38aef828267575780c27d53629ae3f719ba90882f44582594edee317721ef4b6dc516363f2b3a6e1bc0a6b3cc343ff3b87b6f3aa687cfb25e2c267d82f
|
7
|
+
data.tar.gz: 65ed1cd537b0550fcfd4087e40ff78d3eeed8a276a764ff9275131a4be38e39258015379b7adbf15e8366bdd6ff29fe4070d9af266c1568a87794cf2dfa7b0c6
|
data/bin/futo
CHANGED
@@ -1,10 +1,40 @@
|
|
1
|
-
#!/usr/bin/env
|
2
|
-
|
1
|
+
#!/usr/bin/env ruby_executeable_hooks
|
2
|
+
require 'fileutils'
|
3
3
|
require 'futo-spec'
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
output_version_only = false
|
6
|
+
opts = {}
|
7
|
+
|
8
|
+
def futo_init_directories
|
9
|
+
FileUtils.mkdir_p("#{Dir.pwd}/futo/chizus")
|
10
|
+
FileUtils.mkdir("#{Dir.pwd}/futo/_glue")
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
ARGV.each do |arg|
|
14
|
+
if arg == '-d' || arg == '--dry-run'
|
15
|
+
opts.store(:dry, true)
|
16
|
+
elsif arg == '-md' || arg == '--markdown'
|
17
|
+
opts.store(:markdown, true)
|
18
|
+
elsif arg == '-v' || arg == '--version'
|
19
|
+
output_version_only = true
|
20
|
+
puts Gem.loaded_specs['futo-spec'].version
|
21
|
+
elsif arg == '--init'
|
22
|
+
futo_init_directories
|
23
|
+
elsif arg == '-h' || arg == '--headless'
|
24
|
+
opts.store(:headless, true)
|
25
|
+
elsif arg == '-v' || arg == '--version'
|
26
|
+
output_version_only = true
|
27
|
+
elsif arg.end_with? '.futo'
|
28
|
+
opts.store(:specified_file, arg)
|
29
|
+
elsif arg.include? ':'
|
30
|
+
opts.store(:specified_line, arg)
|
31
|
+
elsif not arg.start_with? '-'
|
32
|
+
# support passing a file name without having to type .futo
|
33
|
+
opts.store(:specified_file, "#{arg}.futo")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
unless output_version_only
|
38
|
+
fs = FutoSpec.new(opts)
|
39
|
+
fs.run
|
40
|
+
end
|
File without changes
|
data/lib/futo-spec.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'byebug'; alias :breakpoint :byebug
|
2
|
+
require 'find'
|
1
3
|
require 'paint/pa'
|
2
4
|
require 'rspec/expectations'
|
3
|
-
require 'find'
|
4
5
|
require 'rspec'
|
6
|
+
require_relative './markdown_generator'
|
5
7
|
|
6
8
|
|
7
9
|
BULLET_POINTS_REGEX = /[\->]*/
|
@@ -12,6 +14,20 @@ RSpec.configure do |config|
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
17
|
+
def logd(msg, *colors)
|
18
|
+
if $debug
|
19
|
+
unless colors
|
20
|
+
puts msg
|
21
|
+
else
|
22
|
+
if colors.first == :bb
|
23
|
+
pa msg, :yellow, :bright
|
24
|
+
else
|
25
|
+
pa msg, *colors
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
alias :dpa :logd
|
15
31
|
|
16
32
|
class FutoBullet
|
17
33
|
attr_accessor :label, :associated_commands
|
@@ -23,6 +39,11 @@ class FutoBullet
|
|
23
39
|
end
|
24
40
|
|
25
41
|
class FutoCase
|
42
|
+
##
|
43
|
+
# A test case, with a description and associated bullet points.
|
44
|
+
# The description won't actually execute code.
|
45
|
+
# The associated bullet points will be mapped to ruby commands via "Chizus".
|
46
|
+
# Bullets will in sequence until a newline is encountered.
|
26
47
|
attr_accessor :description, :bullet_points
|
27
48
|
def initialize(h, b_arr)
|
28
49
|
@description = h
|
@@ -32,6 +53,10 @@ class FutoCase
|
|
32
53
|
end
|
33
54
|
|
34
55
|
class ChizuEntry
|
56
|
+
##
|
57
|
+
# "Chizu" is Japanese for "map".
|
58
|
+
# Chizus map bullet point text to specific ruby commands which will be executed.
|
59
|
+
# Analagous to Cucumber's "step definition" layer.
|
35
60
|
attr_accessor :kkey, :associated_commands
|
36
61
|
def initialize(h, c_arr)
|
37
62
|
@kkey = h
|
@@ -41,71 +66,151 @@ class ChizuEntry
|
|
41
66
|
end
|
42
67
|
|
43
68
|
class FutoSpec
|
69
|
+
##
|
70
|
+
# A collection of test cases, "FutoCase", and execution mappings, "Chizus".
|
71
|
+
# Collect test definitions, then match them to chizus and run the associated commands.
|
44
72
|
include RSpec::Matchers
|
45
|
-
attr_accessor :cases, :chizu, :unmatched
|
73
|
+
attr_accessor :cases, :chizu, :unmatched, :included_ins
|
74
|
+
|
75
|
+
def check_and_set_debug
|
76
|
+
if ENV.has_key? 'DEBUG'
|
77
|
+
if ENV.fetch('DEBUG') == 'true'
|
78
|
+
$debug = true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
46
82
|
|
47
|
-
def initialize(
|
83
|
+
def initialize(opts={})
|
48
84
|
@cases = Array.new
|
49
|
-
@
|
85
|
+
@chizu_array = Array.new
|
50
86
|
@unmatched = Array.new
|
87
|
+
@included_ins = Array.new
|
51
88
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
89
|
+
check_and_set_debug
|
90
|
+
|
91
|
+
if opts.include? :dry
|
92
|
+
$dry_run = true if opts[:dry]
|
93
|
+
pa 'dry run', :gray
|
57
94
|
end
|
58
95
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
96
|
+
if opts.include? :markdown
|
97
|
+
$markdown = true if opts[:markdown]
|
98
|
+
pa 'markdown mode', :gray, :bright
|
99
|
+
end
|
100
|
+
|
101
|
+
if opts.include? :headless
|
102
|
+
$headless = true if opts[:headless]
|
103
|
+
end
|
104
|
+
|
105
|
+
if opts.include? :specified_line
|
106
|
+
puts "line specified: #{opts.fetch(:specified_line)}"
|
107
|
+
specified_line = opts.fetch(:specified_line)
|
108
|
+
elsif opts.include? :specified_file
|
109
|
+
puts "specific file requested: #{opts.fetch(:specified_file)}"
|
110
|
+
specified_file = opts.fetch(:specified_file)
|
111
|
+
end
|
112
|
+
|
113
|
+
if $markdown
|
114
|
+
unless specified_file
|
115
|
+
raise ArgumentError, "please specify a file when using --markdown option."
|
116
|
+
else
|
117
|
+
test_case_lines = process_specific_file(specified_file)
|
118
|
+
generate_markdown_and_print(test_case_lines)
|
119
|
+
pa 'finished markdown.', :gray, :bright
|
120
|
+
end
|
121
|
+
else
|
122
|
+
look_for_envrb_and_parse
|
123
|
+
find_and_load_chizu_files
|
124
|
+
|
125
|
+
if specified_line
|
126
|
+
test_case_lines = process_specific_line(specified_line)
|
127
|
+
dpa "line specified: #{specified_line} test case lines: #{test_case_lines}", :red
|
128
|
+
elsif specified_file
|
129
|
+
test_case_lines = process_specific_file(specified_file)
|
130
|
+
else
|
131
|
+
test_case_lines = discover_and_process_spec_files
|
132
|
+
end
|
133
|
+
|
134
|
+
create_test_cases(test_case_lines)
|
135
|
+
dpa "test cases loaded: #{@cases.length}", :bb
|
136
|
+
|
137
|
+
match_chizus_to_test_cases
|
138
|
+
end
|
63
139
|
end
|
64
140
|
|
65
141
|
def look_for_envrb_and_parse
|
66
|
-
if Dir.children(
|
67
|
-
if Dir.children("#{Dir.pwd}/futo
|
68
|
-
|
69
|
-
|
142
|
+
if Dir.children(Dir.pwd).include? 'futo'
|
143
|
+
if Dir.children("#{Dir.pwd}/futo").include? '_glue'
|
144
|
+
if Dir.children("#{Dir.pwd}/futo/_glue").include? 'env.rb'
|
145
|
+
dpa 'found futo/_glue/env.rb', :gray
|
146
|
+
load 'futo/_glue/env.rb'
|
147
|
+
end
|
70
148
|
end
|
71
149
|
end
|
72
150
|
end
|
73
151
|
|
74
|
-
def
|
152
|
+
def discover_and_process_spec_files
|
153
|
+
dpa "no file specified, discovering all .futo or .spec files ...", :yellow, :bright
|
75
154
|
futo_files = []
|
76
155
|
test_case_lines = []
|
77
156
|
|
78
|
-
Find.find(
|
157
|
+
Find.find("#{Dir.pwd}/futo") do |ff|
|
79
158
|
if ff.end_with? '.futo' or ff.end_with? 'spec'
|
80
|
-
|
159
|
+
fn = ff.split('/').last
|
160
|
+
futo_files << fn
|
81
161
|
end
|
82
162
|
end
|
83
163
|
|
84
|
-
futo_files.each { |
|
164
|
+
futo_files.each { |fn| test_case_lines += process_specific_file(fn) }
|
85
165
|
return test_case_lines
|
86
166
|
end
|
87
167
|
|
88
|
-
def
|
168
|
+
def process_specific_file(fn)
|
169
|
+
dpa "process_specific_file: #{fn}", :yellow
|
170
|
+
path = "futo/#{fn}"
|
171
|
+
File.open(path) do |file|
|
172
|
+
file_lines = file.readlines(chomp:true)
|
173
|
+
return file_lines
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def process_specific_line(desc)
|
89
178
|
spl = desc.split(':')
|
90
179
|
desc_file = spl.first
|
91
|
-
|
180
|
+
# allow for specifying line w/o .futo, eg `futo current:19 for current.futo:19`
|
181
|
+
desc_file = "#{desc_file}.futo" if not desc_file.include? '.'
|
182
|
+
line_specified = spl.last
|
183
|
+
idx = line_specified.to_i - 1 # line numbers are 1-indexed
|
184
|
+
|
185
|
+
puts "found specific file request: #{desc_file} at line #{line_specified} (index #{idx})"
|
92
186
|
|
93
|
-
File.open(desc_file) do |file|
|
187
|
+
File.open("./futo/#{desc_file}") do |file|
|
94
188
|
all_lines = file.readlines(chomp:true)
|
95
189
|
specified_line = all_lines[idx]
|
96
|
-
|
190
|
+
if is_description? specified_line
|
191
|
+
return add_additional_lines_context_to_specified_line(all_lines, idx)
|
192
|
+
else
|
193
|
+
specified_line_as_arr = [ specified_line ]
|
194
|
+
return specified_line_as_arr
|
195
|
+
end
|
97
196
|
end
|
98
197
|
end
|
99
198
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
199
|
+
def add_additional_lines_context_to_specified_line(all_lines, idx)
|
200
|
+
starting_slice = all_lines.slice(idx, all_lines.length)
|
201
|
+
final_idx = nil
|
202
|
+
starting_slice.each_with_index do |ll, ii|
|
203
|
+
if is_newline? ll
|
204
|
+
final_idx = ii
|
205
|
+
break
|
206
|
+
end
|
207
|
+
if final_idx == nil
|
208
|
+
# no newline found through the rest of the futo
|
209
|
+
final_idx = starting_slice.length
|
107
210
|
end
|
108
211
|
end
|
212
|
+
final_slice = starting_slice.slice(0, final_idx)
|
213
|
+
return final_slice
|
109
214
|
end
|
110
215
|
|
111
216
|
def add_case_to_spec
|
@@ -127,13 +232,37 @@ class FutoSpec
|
|
127
232
|
@new_case_label = line
|
128
233
|
end
|
129
234
|
|
235
|
+
def is_description?(line)
|
236
|
+
return false if is_bullet? line
|
237
|
+
return false if is_newline? line
|
238
|
+
return false if is_mock_data? line
|
239
|
+
return false if is_asterisk? line
|
240
|
+
return true
|
241
|
+
end
|
242
|
+
|
243
|
+
def is_asterisk?(line)
|
244
|
+
return line.start_with?('*')
|
245
|
+
end
|
246
|
+
|
247
|
+
def is_bullet?(line)
|
248
|
+
return line.start_with?('-') || line.start_with?('>')
|
249
|
+
end
|
250
|
+
|
130
251
|
def is_newline?(line)
|
131
252
|
return line == ''
|
132
253
|
end
|
133
254
|
|
134
|
-
def
|
135
|
-
return line.start_with?('**
|
136
|
-
|
255
|
+
def is_mock_data?(line)
|
256
|
+
return line.start_with?('** mock data:')
|
257
|
+
end
|
258
|
+
|
259
|
+
def load_mock_data(ll)
|
260
|
+
# ll is the full line including '** mock data:'
|
261
|
+
fn = ll.split(' ').last.gsub("'",'').gsub('"','')
|
262
|
+
# now we have the filename minus futo/
|
263
|
+
path = "futo/#{fn}"
|
264
|
+
md = File.readlines(path, chomp:true)
|
265
|
+
@mock_data = md
|
137
266
|
end
|
138
267
|
|
139
268
|
def init_test(line)
|
@@ -147,26 +276,32 @@ class FutoSpec
|
|
147
276
|
puts
|
148
277
|
end
|
149
278
|
|
150
|
-
def
|
151
|
-
return line.start_with?('-') || line.start_with?('>')
|
152
|
-
end
|
153
|
-
|
154
|
-
def create_test_cases_and_load_bullet_points(test_case_lines)
|
279
|
+
def create_test_cases(test_case_lines)
|
155
280
|
begin_new_case
|
156
281
|
|
157
282
|
test_case_lines.each do |line|
|
158
283
|
l0 = line.gsub('(DONE)','').gsub('(done)','')
|
159
284
|
ll = l0.lstrip.rstrip
|
160
285
|
if is_newline? ll
|
286
|
+
dpa "found newline: #{ll}", :yellow
|
161
287
|
add_case_to_spec
|
162
288
|
begin_new_case
|
163
289
|
else
|
164
|
-
if
|
165
|
-
|
290
|
+
if is_mock_data? ll
|
291
|
+
dpa "found mock data: #{ll}", :yellow
|
292
|
+
load_mock_data(ll)
|
166
293
|
elsif is_bullet? ll
|
294
|
+
dpa "found bullet: #{ll}", :yellow
|
167
295
|
new_bullet(ll)
|
168
|
-
|
296
|
+
elsif is_asterisk? ll
|
297
|
+
dpa "found asterisk, treating as description: #{ll}", :yellow
|
298
|
+
label = ll.gsub('*', '').lstrip
|
299
|
+
new_label(label)
|
300
|
+
elsif is_description? ll
|
301
|
+
dpa "found new description: #{ll}", :yellow
|
169
302
|
new_label(ll)
|
303
|
+
else
|
304
|
+
raise RuntimeError, "could not find entry type for string #{ll}"
|
170
305
|
end
|
171
306
|
end
|
172
307
|
end
|
@@ -191,72 +326,116 @@ class FutoSpec
|
|
191
326
|
|
192
327
|
def find_and_load_chizu_files
|
193
328
|
chizu_files = []
|
329
|
+
search_dir = "#{Dir.pwd}/futo/chizus"
|
330
|
+
Find.find(search_dir) do |ff|
|
331
|
+
chizu_files << ff if ff.end_with? '.chizu'
|
332
|
+
chizu_files << ff if ff.end_with? '.rb'
|
333
|
+
end
|
194
334
|
|
195
|
-
|
196
|
-
|
197
|
-
|
335
|
+
dpa "loading chizu ...", :yellow, :bright
|
336
|
+
chizu_files.each {|ff| load_chizu_commands ff}
|
337
|
+
dpa "chizu load complete, files below:", :yellow
|
338
|
+
@chizu_array.each do |cc|
|
339
|
+
dpa "- #{cc} -", :yellow
|
340
|
+
dpa "commands: #{cc.associated_commands}", :yellow
|
198
341
|
end
|
342
|
+
end
|
199
343
|
|
200
|
-
|
344
|
+
def add_new_chizu(kkey, commands)
|
345
|
+
@chizu_array << ChizuEntry.new(kkey, commands)
|
201
346
|
end
|
202
347
|
|
203
|
-
def
|
348
|
+
def load_chizu_commands(ff)
|
204
349
|
File.open(ff) do |file|
|
205
350
|
lines = file.readlines(chomp:true)
|
206
351
|
kkey = ''
|
207
|
-
|
352
|
+
associated_commands = Array.new
|
353
|
+
|
354
|
+
processing_stanza = false
|
355
|
+
inside_begin_end_block = false
|
356
|
+
begin_end_block_string = ''
|
357
|
+
|
208
358
|
lines.each do |ll|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
359
|
+
if processing_stanza
|
360
|
+
if inside_begin_end_block
|
361
|
+
puts "processing begin-end command: #{ll}"
|
362
|
+
if ll.lstrip.start_with? 'end'
|
363
|
+
begin_end_block_string += " #{ll.lstrip};"
|
364
|
+
associated_commands << begin_end_block_string
|
365
|
+
begin_end_block_string = ''
|
366
|
+
inside_begin_end_block = false
|
367
|
+
else
|
368
|
+
begin_end_block_string += " #{ll.lstrip};"
|
369
|
+
end
|
213
370
|
else
|
214
|
-
|
371
|
+
if ll.strip.start_with? 'begin'
|
372
|
+
inside_begin_end_block= true
|
373
|
+
begin_end_block_string += "#{ll.lstrip};"
|
374
|
+
elsif ll.start_with? 'end'
|
375
|
+
processing_stanza = false
|
376
|
+
add_new_chizu(kkey, associated_commands)
|
377
|
+
kkey = ''
|
378
|
+
associated_commands = Array.new
|
379
|
+
else
|
380
|
+
associated_commands << ll.lstrip
|
381
|
+
end
|
215
382
|
end
|
216
|
-
elsif ll.start_with? 'end'
|
217
|
-
@chizu << ChizuEntry.new(kkey, commands)
|
218
|
-
kkey = ''
|
219
|
-
commands = Array.new
|
220
|
-
elsif ll == "\n" || ll == ''
|
221
|
-
next
|
222
383
|
else
|
223
|
-
|
384
|
+
#puts "processing description line: #{ll}"
|
385
|
+
if ll.start_with? 'On'
|
386
|
+
processing_stanza = true
|
387
|
+
using_single_quotes = single_quoted_line?(ll)
|
388
|
+
if using_single_quotes
|
389
|
+
kkey = ll.split("'")[1]
|
390
|
+
else
|
391
|
+
kkey = ll.split('"')[1]
|
392
|
+
end
|
393
|
+
elsif ll == "\n" || ll == ''
|
394
|
+
next
|
395
|
+
else
|
396
|
+
breakpoint
|
397
|
+
puts
|
398
|
+
end
|
224
399
|
end
|
225
400
|
end
|
226
401
|
end
|
227
402
|
end
|
228
403
|
|
229
404
|
def is_todo?(chizu)
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
405
|
+
return chizu.associated_commands.include?('TODO')
|
406
|
+
end
|
407
|
+
|
408
|
+
def is_included_in?(chizu)
|
409
|
+
return chizu.associated_commands.first.include? 'included_in'
|
410
|
+
end
|
411
|
+
|
412
|
+
def set_all_unmatched
|
413
|
+
@cases.each do |cc|
|
414
|
+
cc.bullet_points.each {|bullet| @unmatched << bullet.label }
|
236
415
|
end
|
237
416
|
end
|
238
417
|
|
239
|
-
def load_commands_into_test_cases_from_chizu
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
bullet.associated_commands = chizu.associated_commands
|
254
|
-
end
|
418
|
+
#def load_commands_into_test_cases_from_chizu
|
419
|
+
def match_chizus_to_test_cases
|
420
|
+
if @chizu_array.length == 0
|
421
|
+
set_all_unmatched
|
422
|
+
else
|
423
|
+
@cases.each_with_index do |test_case, tc_index|
|
424
|
+
test_case.bullet_points.each do |bullet|
|
425
|
+
dpa "matching bullet: #{bullet}", :bb
|
426
|
+
matched = false
|
427
|
+
@chizu_array.each do |chizu|
|
428
|
+
if process_bullet_chizu_match(bullet, chizu)
|
429
|
+
bullet.associated_commands = chizu.associated_commands
|
430
|
+
matched = true
|
431
|
+
break
|
255
432
|
end
|
256
433
|
end
|
434
|
+
dpa "matched? #{bullet.label} : #{matched}", :bb
|
257
435
|
if ! matched
|
258
|
-
unless @unmatched.include? bullet
|
259
|
-
|
436
|
+
unless @unmatched.include? bullet.label
|
437
|
+
dpa "couldn't find a match for #{bullet.label}", :red
|
438
|
+
@unmatched << bullet.label
|
260
439
|
end
|
261
440
|
end
|
262
441
|
end
|
@@ -264,37 +443,58 @@ class FutoSpec
|
|
264
443
|
end
|
265
444
|
end
|
266
445
|
|
446
|
+
def process_bullet_chizu_match(bullet, chizu)
|
447
|
+
matched = false
|
448
|
+
dpa "chizu: #{chizu.kkey}", :yellow
|
449
|
+
if is_todo? chizu
|
450
|
+
#logd "found todo: #{chizu}", :yellow
|
451
|
+
# todos aren't considered completed so they are unmatched
|
452
|
+
elsif is_included_in? chizu
|
453
|
+
#logd "found included_in: #{chizu}", :yellow
|
454
|
+
@included_ins << chizu
|
455
|
+
else
|
456
|
+
if bullet.label == chizu.kkey
|
457
|
+
logd "matched: #{bullet.label} #{chizu.kkey}", :blue
|
458
|
+
matched = true
|
459
|
+
end
|
460
|
+
end
|
461
|
+
return matched
|
462
|
+
end
|
463
|
+
|
267
464
|
def output_unmatched_commands
|
268
465
|
puts
|
269
466
|
pa "Missing chizu entries:", :yellow
|
270
467
|
puts
|
271
|
-
@unmatched.each do |
|
272
|
-
pa "On '#{
|
468
|
+
@unmatched.each do |label|
|
469
|
+
pa "On '#{label}' do", :yellow
|
273
470
|
pa ' # TODO', :yellow
|
274
471
|
pa 'end', :yellow
|
275
472
|
puts
|
276
473
|
end
|
277
474
|
end
|
278
475
|
|
279
|
-
def run
|
280
|
-
exec_cases unless dry_run
|
281
|
-
output_unmatched_commands
|
476
|
+
def run
|
477
|
+
exec_cases unless $dry_run
|
478
|
+
output_unmatched_commands if @unmatched.length > 0
|
479
|
+
end
|
480
|
+
|
481
|
+
def run_commands_in_block_context(bullet)
|
482
|
+
bullet.associated_commands.each do |cmd|
|
483
|
+
pa cmd, :cyan if cmd != 'breakpoint'
|
484
|
+
begin
|
485
|
+
binding = eval(cmd, binding)
|
486
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
487
|
+
pa e, :red
|
488
|
+
end
|
489
|
+
end
|
282
490
|
end
|
283
491
|
|
284
492
|
def exec_cases
|
285
493
|
puts
|
286
494
|
@cases.each do |test_case|
|
495
|
+
pa "case: #{test_case.description}", :gray
|
287
496
|
test_case.bullet_points.each do |bullet|
|
288
|
-
|
289
|
-
pa "case: #{bullet.label}", :gray
|
290
|
-
bullet.associated_commands.each do |cmd|
|
291
|
-
pa cmd, :cyan if cmd != 'breakpoint'
|
292
|
-
begin
|
293
|
-
eval cmd
|
294
|
-
rescue RSpec::Expectations::ExpectationNotMetError => e
|
295
|
-
pa e, :red
|
296
|
-
end
|
297
|
-
end
|
497
|
+
run_commands_in_block_context(bullet)
|
298
498
|
end
|
299
499
|
end
|
300
500
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class MarkdownTestCase
|
2
|
+
def initialize(markdown)
|
3
|
+
@markdown = markdown
|
4
|
+
end
|
5
|
+
def to_s
|
6
|
+
@markdown
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def table_headings
|
11
|
+
'|| test case || steps || expected result'
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_step?(ll)
|
15
|
+
ll.start_with?('-') && not(ll.include?('>'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def is_expected_result?(ll)
|
19
|
+
ll.start_with?('-') && ll.include?('>')
|
20
|
+
end
|
21
|
+
|
22
|
+
def is_blank_line?(ll)
|
23
|
+
ll == ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_markdown_and_print(test_case_lines)
|
27
|
+
puts
|
28
|
+
pa 'generating markdown ...', :gray, :bright
|
29
|
+
desc = ''
|
30
|
+
steps = ''
|
31
|
+
expected_result = ''
|
32
|
+
tcs = [ table_headings ]
|
33
|
+
|
34
|
+
test_case_lines.each do |ll|
|
35
|
+
if is_step? ll
|
36
|
+
txt = ll.gsub('-', '').lstrip
|
37
|
+
steps += "#{txt}\n"
|
38
|
+
elsif is_expected_result? ll
|
39
|
+
txt = ll.gsub('-', '').gsub('>','').lstrip
|
40
|
+
expected_result += "* #{txt}\n"
|
41
|
+
elsif is_blank_line? ll
|
42
|
+
unless desc == ''
|
43
|
+
row = "| #{desc} | #{steps.chomp} | #{expected_result.chomp}"
|
44
|
+
tcs << MarkdownTestCase.new(row)
|
45
|
+
desc = ''
|
46
|
+
steps = ''
|
47
|
+
expected_result = ''
|
48
|
+
end
|
49
|
+
else
|
50
|
+
desc += ll.lstrip
|
51
|
+
end
|
52
|
+
end
|
53
|
+
unless desc == ''
|
54
|
+
row = "| #{desc} | #{steps.chomp} | #{expected_result.chomp}"
|
55
|
+
tcs << MarkdownTestCase.new(row)
|
56
|
+
end
|
57
|
+
puts
|
58
|
+
tcs.each do |tc|
|
59
|
+
puts tc
|
60
|
+
end
|
61
|
+
puts
|
62
|
+
end
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: futo-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Felipe Wolfe
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2020-09-21 00:00:00.000000000 Z
|
@@ -24,62 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.2'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: apparition
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.6'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.6'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: selenium-webdriver
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '3.1'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '3.1'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: webdrivers
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '4.4'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '4.4'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: capybara
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '3.3'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '3.3'
|
83
27
|
- !ruby/object:Gem::Dependency
|
84
28
|
name: rspec
|
85
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,18 +75,16 @@ extensions: []
|
|
131
75
|
extra_rdoc_files: []
|
132
76
|
files:
|
133
77
|
- bin/futo
|
78
|
+
- lib/exec_block_context.rb
|
134
79
|
- lib/futo-spec.rb
|
135
|
-
- lib/spec/
|
136
|
-
- lib/spec/_glue/
|
137
|
-
- lib/
|
138
|
-
- lib/spec/edge_cases.futo
|
139
|
-
- lib/spec/rspec.futo
|
140
|
-
- lib/spec/todos.futo
|
80
|
+
- lib/futo-spec/futo_logger.rb
|
81
|
+
- lib/futo-spec/self-test/futo/_glue/mocks/basics.setup.rb
|
82
|
+
- lib/markdown_generator.rb
|
141
83
|
homepage: https://rubygems.org/gems/futo-spec
|
142
84
|
licenses:
|
143
85
|
- MIT
|
144
86
|
metadata: {}
|
145
|
-
post_install_message:
|
87
|
+
post_install_message:
|
146
88
|
rdoc_options: []
|
147
89
|
require_paths:
|
148
90
|
- lib
|
@@ -157,8 +99,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
99
|
- !ruby/object:Gem::Version
|
158
100
|
version: '0'
|
159
101
|
requirements: []
|
160
|
-
rubygems_version: 3.
|
161
|
-
signing_key:
|
102
|
+
rubygems_version: 3.1.4
|
103
|
+
signing_key:
|
162
104
|
specification_version: 4
|
163
105
|
summary: Test engine using bullet points. Like you're writing on an envelope.
|
164
106
|
test_files: []
|
@@ -1,39 +0,0 @@
|
|
1
|
-
On 'lines with bullets should map as a normal test case' do
|
2
|
-
puts "lines with bullets test case"
|
3
|
-
end
|
4
|
-
|
5
|
-
On 'lines without bullets should map as a test description' do
|
6
|
-
# TODO
|
7
|
-
end
|
8
|
-
|
9
|
-
On 'newlines \n should start a new case' do
|
10
|
-
# TODO
|
11
|
-
end
|
12
|
-
|
13
|
-
On 'when specific line requested with colon :, only specific line should run' do
|
14
|
-
# TODO
|
15
|
-
end
|
16
|
-
|
17
|
-
On 'if specific line is description not bullet point, all bullets in that case should run' do
|
18
|
-
# TODO
|
19
|
-
end
|
20
|
-
|
21
|
-
On 'what to do with long bullets or descriptions that have a <Cr for readability ?' do
|
22
|
-
# TODO
|
23
|
-
end
|
24
|
-
|
25
|
-
On 'unmatched description steps, should generate a sample chizu to copypaste' do
|
26
|
-
# TODO
|
27
|
-
end
|
28
|
-
|
29
|
-
On 'single quotes' do
|
30
|
-
# TODO
|
31
|
-
end
|
32
|
-
|
33
|
-
On 'double quotes' do
|
34
|
-
# TODO
|
35
|
-
end
|
36
|
-
|
37
|
-
On 'should be parsed as a test description *and* bullet' do
|
38
|
-
# TODO
|
39
|
-
end
|
data/lib/spec/basics.futo
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
basic mapping
|
2
|
-
** initialize with: basics **
|
3
|
-
- lines with bullets should map as a normal test case
|
4
|
-
- lines without bullets should map as a test description
|
5
|
-
- newlines \n should start a new case
|
6
|
-
|
7
|
-
specific line
|
8
|
-
- when specific line requested with colon :, only specific line should run
|
9
|
-
- if specific line is description not bullet point, all bullets in that case should run
|
10
|
-
|
11
|
-
wrapped / long lines
|
12
|
-
- what to do with long bullets or descriptions that have a <Cr> for readability ?
|
13
|
-
|
14
|
-
state
|
15
|
-
- lines starting with "** using setup:" load state for the whole file
|
16
|
-
- will need levels of scope for this
|
data/lib/spec/edge_cases.futo
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
missing / unmatched steps
|
2
|
-
- unmatched description steps, should generate a sample chizu to copy-paste
|
3
|
-
|
4
|
-
single vs double quotes
|
5
|
-
- single quotes
|
6
|
-
- double quotes
|
7
|
-
|
8
|
-
test point with only one line, without a bullet -
|
9
|
-
|
10
|
-
desc file which starts with a blank line
|
11
|
-
|
12
|
-
single lines which start with a dash -
|
13
|
-
- should be parsed as a test description *and* bullet
|
14
|
-
|
15
|
-
unmatched should work properly
|
16
|
-
- matched should not appear in unmatched output
|
17
|
-
- see commit :2087519 for the fix; an indentation problem caused a bug
|
data/lib/spec/rspec.futo
DELETED
data/lib/spec/todos.futo
DELETED