baf 0.14.1 → 0.15.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.
- checksums.yaml +4 -4
- data/lib/baf/option.rb +6 -6
- data/lib/baf/options_registrant.rb +2 -2
- data/lib/baf/testing/cucumber/steps/execution.rb +21 -36
- data/lib/baf/testing/cucumber/steps/filesystem.rb +3 -0
- data/lib/baf/testing/cucumber/steps/input.rb +1 -1
- data/lib/baf/testing/cucumber/steps/output.rb +14 -23
- data/lib/baf/testing/cucumber/steps/output_wait.rb +5 -46
- data/lib/baf/testing/cucumber.rb +9 -3
- data/lib/baf/testing/process.rb +107 -0
- data/lib/baf/testing.rb +138 -0
- metadata +89 -14
- data/lib/baf/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3dd2c36e21fb8a41d21f0d3ea90c5126274b9f68f19f4b2cb0f09c33aa38605
|
4
|
+
data.tar.gz: 9cf8f0b59d4b8cbb70f174912f2569f204fd27a82236a8e992c6729b366cc574
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcc9f8fb5658bb47c75067a09912585878ee73ab227c09628eb4d2742e3f360a8c2f55b3effa1e2acc1329f130046f8ec76caefa66d6c468fbdce46596ba6370
|
7
|
+
data.tar.gz: 8aa8f06dee9cb55a12e560177c80a44f724c4fab30b5a5e9de9764f7fdd4eb12d0e9e76ebdedbad4fdd5fbb7cb58ea101fb3402d68d56fd191a0297b0dd198bb
|
data/lib/baf/option.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Baf
|
2
2
|
class Option
|
3
|
-
LONG_PREFIX
|
4
|
-
LONG_NORMALIZE_SEARCH
|
5
|
-
LONG_NORMALIZE_REPLACE
|
6
|
-
LONG_WITH_ARG_GLUE
|
7
|
-
PARSER_MESSAGE
|
8
|
-
PARSER_MESSAGE_TAIL
|
3
|
+
LONG_PREFIX = '--'.freeze
|
4
|
+
LONG_NORMALIZE_SEARCH = ?_.freeze
|
5
|
+
LONG_NORMALIZE_REPLACE = ?-.freeze
|
6
|
+
LONG_WITH_ARG_GLUE = ' '.freeze
|
7
|
+
PARSER_MESSAGE = :on
|
8
|
+
PARSER_MESSAGE_TAIL = :on_tail
|
9
9
|
|
10
10
|
attr_accessor :short, :long, :arg, :desc, :block, :tail
|
11
11
|
|
@@ -1,50 +1,35 @@
|
|
1
|
-
def
|
2
|
-
cmd
|
3
|
-
cmd
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
else
|
8
|
-
run cmd.join ' '
|
9
|
-
end
|
10
|
-
program_run_check if check
|
11
|
-
end
|
12
|
-
|
13
|
-
def program_run_check status: 0
|
14
|
-
expect(last_command_started).to have_exit_status status
|
15
|
-
rescue RSpec::Expectations::ExpectationNotMetError => e
|
16
|
-
if ENV.key? 'BAF_TEST_DEBUG'
|
17
|
-
fail RSpec::Expectations::ExpectationNotMetError, <<-eoh
|
18
|
-
#{e.message} Output was:
|
19
|
-
```\n#{last_command_started.output.lines.map { |l| " #{l}" }.join} ```
|
20
|
-
eoh
|
21
|
-
else
|
22
|
-
raise
|
23
|
-
end
|
1
|
+
def run state, cmd: nil, wait: true, args: []
|
2
|
+
cmd ||= state[:program]
|
3
|
+
Baf::Testing.run cmd + args,
|
4
|
+
wait: wait,
|
5
|
+
env_allow: state.fetch(:env_allow) { [] },
|
6
|
+
timeout: state[:exec_timeout]
|
24
7
|
end
|
25
8
|
|
26
9
|
|
27
10
|
When /^I( successfully)? (run|\w+) the program$/ do |check, run|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
When /^I( successfully)? (run|\w+) the program with arguments? (.+)$/ do |check, run, args|
|
32
|
-
program_run check: !!check, args: args, wait: run == 'run'
|
11
|
+
$_baf[:process] = run $_baf, wait: run == 'run'
|
12
|
+
Baf::Testing.expect_ex $_baf[:process], 0 if check
|
33
13
|
end
|
34
14
|
|
35
|
-
When
|
36
|
-
|
15
|
+
When(
|
16
|
+
/^I( successfully)? (run|\w+) the program with (?:argument|command|option)s? (.+)$/
|
17
|
+
) do |check, run, args|
|
18
|
+
$_baf[:process] = run $_baf, wait: run == 'run', args: args.split(' ')
|
19
|
+
Baf::Testing.expect_ex $_baf[:process], 0 if check
|
37
20
|
end
|
38
21
|
|
39
|
-
When /^I( successfully)? (run|\w+)
|
40
|
-
|
22
|
+
When /^I( successfully)? (run|\w+) `([^`]+)`$/ do |check, run, command|
|
23
|
+
$_baf[:process] = run $_baf, cmd: command.split(' '), wait: run == 'run'
|
24
|
+
Baf::Testing.expect_ex $_baf[:process], 0 if check
|
41
25
|
end
|
42
26
|
|
43
27
|
|
44
|
-
Then /^the
|
45
|
-
|
28
|
+
Then /^the program must terminate successfully$/ do
|
29
|
+
Baf::Testing.wait $_baf[:process]
|
30
|
+
Baf::Testing.expect_ex $_baf[:process], 0
|
46
31
|
end
|
47
32
|
|
48
|
-
Then /^the
|
49
|
-
|
33
|
+
Then /^the exit status must be (\d+)$/ do |exit_status|
|
34
|
+
Baf::Testing.expect_ex $_baf[:process], Integer(exit_status)
|
50
35
|
end
|
@@ -1,44 +1,35 @@
|
|
1
|
-
def build_regexp pattern, options
|
2
|
-
Regexp.new(pattern, options.each_char.inject(0) do |m, e|
|
3
|
-
m | case e
|
4
|
-
when ?i then Regexp::IGNORECASE
|
5
|
-
when ?m then Regexp::MULTILINE
|
6
|
-
when ?x then Regexp::EXTENDED
|
7
|
-
end
|
8
|
-
end)
|
9
|
-
end
|
10
|
-
|
11
|
-
def expect_output content, stream: :output
|
12
|
-
stream = :stderr if stream == :error
|
13
|
-
expect(last_command_started.send stream).to eq unescape_text content
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
1
|
Then /^the output must be empty$/ do
|
18
|
-
expect(
|
2
|
+
expect($_baf[:process].output).to be_empty
|
19
3
|
end
|
20
4
|
|
21
5
|
Then /^the output must contain:$/ do |content|
|
22
|
-
expect(
|
6
|
+
expect($_baf[:process].output).to include content
|
23
7
|
end
|
24
8
|
|
25
9
|
Then /^the output must contain "([^"]+)"$/ do |content|
|
26
|
-
expect(
|
10
|
+
expect($_baf[:process].output).to include content
|
27
11
|
end
|
28
12
|
|
29
13
|
Then /^the output must not contain "([^"]+)"$/ do |content|
|
30
|
-
expect(
|
14
|
+
expect($_baf[:process].output).not_to include content
|
31
15
|
end
|
32
16
|
|
33
17
|
Then /^the output must contain exactly:$/ do |content|
|
34
|
-
|
18
|
+
expect($_baf[:process].output).to eq content + $/
|
35
19
|
end
|
36
20
|
|
37
21
|
Then /^the( error)? output must contain exactly "([^"]+)"$/ do |stream, content|
|
38
22
|
stream = stream ? :error : :output
|
39
|
-
|
23
|
+
expect($_baf[:process].output stream)
|
24
|
+
.to eq Baf::Testing::unescape_step_arg content
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^the output must match:/ do |pattern|
|
28
|
+
expect($_baf[:process].output)
|
29
|
+
.to match Baf::Testing.build_regexp(pattern, 'mx')
|
40
30
|
end
|
41
31
|
|
42
32
|
Then /^the output must match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
|
43
|
-
expect(
|
33
|
+
expect($_baf[:process].output)
|
34
|
+
.to match Baf::Testing.build_regexp(pattern, options)
|
44
35
|
end
|
@@ -1,57 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Baf
|
4
|
-
module Testing
|
5
|
-
class WaitError < ::StandardError
|
6
|
-
attr_reader :timeout
|
7
|
-
|
8
|
-
def initialize message, timeout
|
9
|
-
super message
|
10
|
-
@timeout = timeout
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def wait_output! pattern, times: 1, results: nil
|
17
|
-
output = -> { last_command_started.output }
|
18
|
-
wait_until do
|
19
|
-
case pattern
|
20
|
-
when Regexp then (results = output.call.scan(pattern)).size >= times
|
21
|
-
when String then output.call.include? pattern
|
22
|
-
end
|
23
|
-
end
|
24
|
-
results
|
25
|
-
rescue Baf::Testing::WaitError => e
|
26
|
-
fail <<-eoh
|
27
|
-
expected `#{pattern}' not seen after #{e.timeout} seconds in:
|
28
|
-
```\n#{output.call.lines.map { |l| " #{l}" }.join} ```
|
29
|
-
eoh
|
30
|
-
end
|
31
|
-
|
32
|
-
def wait_until message: 'condition not met after %d seconds'
|
33
|
-
timeout = ENV.key?('BAF_TEST_TIMEOUT') ?
|
34
|
-
ENV['BAF_TEST_TIMEOUT'].to_i :
|
35
|
-
2
|
36
|
-
Timeout.timeout timeout do
|
37
|
-
loop do
|
38
|
-
break if yield
|
39
|
-
sleep 0.05
|
40
|
-
end
|
41
|
-
end
|
42
|
-
rescue Timeout::Error
|
43
|
-
fail Baf::Testing::WaitError.new(message % timeout, timeout)
|
1
|
+
def wait_output pattern, output: -> { $_baf[:process].output }, times: 1
|
2
|
+
Baf::Testing.wait_output pattern, stream: output, times: times
|
44
3
|
end
|
45
4
|
|
46
5
|
|
47
6
|
Then /^the output will match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
|
48
|
-
wait_output
|
7
|
+
wait_output Baf::Testing.build_regexp pattern, options
|
49
8
|
end
|
50
9
|
|
51
10
|
Then /^the output will contain:$/ do |content|
|
52
|
-
wait_output
|
11
|
+
wait_output content + $/
|
53
12
|
end
|
54
13
|
|
55
14
|
Then /^the output will contain "([^"]+)"$/ do |content|
|
56
|
-
wait_output
|
15
|
+
wait_output content
|
57
16
|
end
|
data/lib/baf/testing/cucumber.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
require '
|
2
|
-
require 'aruba/cucumber/hooks'
|
3
|
-
|
1
|
+
require 'baf/testing'
|
4
2
|
require 'baf/testing/cucumber/steps/execution'
|
3
|
+
require 'baf/testing/cucumber/steps/filesystem'
|
5
4
|
require 'baf/testing/cucumber/steps/output'
|
5
|
+
|
6
|
+
$_baf = {}
|
7
|
+
|
8
|
+
Around do |_, block|
|
9
|
+
Baf::Testing.exercise_scenario &block
|
10
|
+
$_baf.delete :process
|
11
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'baf'
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
module Baf
|
6
|
+
module Testing
|
7
|
+
class Process
|
8
|
+
ExecutionFailure = Class.new Error
|
9
|
+
|
10
|
+
TIMEOUT = 4
|
11
|
+
TMP_FILE_PREFIX = 'baf_test_'.freeze
|
12
|
+
WAIT_POLL_DELAY = 0.01
|
13
|
+
|
14
|
+
attr_reader :pid, :exit_status, :timeout
|
15
|
+
|
16
|
+
def initialize command, env_allow: [], timeout: TIMEOUT
|
17
|
+
@command = command
|
18
|
+
@env_allow = env_allow
|
19
|
+
@timeout = timeout
|
20
|
+
@stdout = Tempfile.new TMP_FILE_PREFIX
|
21
|
+
@stderr = Tempfile.new TMP_FILE_PREFIX
|
22
|
+
end
|
23
|
+
|
24
|
+
def start
|
25
|
+
reader, writer = IO.pipe
|
26
|
+
|
27
|
+
@pid = spawn env,
|
28
|
+
*@command,
|
29
|
+
unsetenv_others: true,
|
30
|
+
in: reader,
|
31
|
+
out: @stdout,
|
32
|
+
err: @stderr
|
33
|
+
reader.close
|
34
|
+
@stdin = writer
|
35
|
+
rescue Errno::ENOENT => e
|
36
|
+
fail ExecutionFailure, e.message
|
37
|
+
end
|
38
|
+
|
39
|
+
def wait timeout: @timeout
|
40
|
+
deadline = Time.now + timeout
|
41
|
+
wait_poll
|
42
|
+
until stopped? || Time.now >= deadline
|
43
|
+
sleep WAIT_POLL_DELAY
|
44
|
+
wait_poll
|
45
|
+
end
|
46
|
+
yield unless stopped? if block_given?
|
47
|
+
end
|
48
|
+
|
49
|
+
def stop wait_timeout: 1
|
50
|
+
::Process.kill :TERM, @pid
|
51
|
+
wait timeout: wait_timeout
|
52
|
+
return if stopped?
|
53
|
+
::Process.kill :KILL, @pid
|
54
|
+
::Process.wait2 @pid
|
55
|
+
rescue Errno::ECHILD, Errno::ESRCH
|
56
|
+
end
|
57
|
+
|
58
|
+
def running?
|
59
|
+
started? && !stopped?
|
60
|
+
end
|
61
|
+
|
62
|
+
def input str
|
63
|
+
@stdin.write str
|
64
|
+
end
|
65
|
+
|
66
|
+
def output stream = nil
|
67
|
+
case stream
|
68
|
+
when :output then [@stdout]
|
69
|
+
when :error then [@stderr]
|
70
|
+
else [@stdout, @stderr]
|
71
|
+
end.inject '' do |memo, stream|
|
72
|
+
memo + IO.read(stream.path)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def env
|
79
|
+
ENV.inject({}) do |acc, (k, v)|
|
80
|
+
if env_allow? k then acc.merge k => v else acc end
|
81
|
+
end.merge 'HOME' => File.realpath(?.)
|
82
|
+
end
|
83
|
+
|
84
|
+
def env_allow? var
|
85
|
+
@env_allow.any? do |e|
|
86
|
+
case e
|
87
|
+
when String then var == e
|
88
|
+
when Regexp then var =~ e
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def started?
|
94
|
+
!!@pid
|
95
|
+
end
|
96
|
+
|
97
|
+
def stopped?
|
98
|
+
!!@exit_status
|
99
|
+
end
|
100
|
+
|
101
|
+
def wait_poll
|
102
|
+
pid, status = ::Process.wait2 @pid, ::Process::WNOHANG
|
103
|
+
@exit_status = status.exitstatus if pid
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/baf/testing.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'baf'
|
4
|
+
require 'baf/testing/process'
|
5
|
+
|
6
|
+
module Baf
|
7
|
+
module Testing
|
8
|
+
ExecutionTimeout = Class.new Error
|
9
|
+
ExitStatusMismatch = Class.new Error
|
10
|
+
|
11
|
+
class WaitError < Error
|
12
|
+
attr_reader :timeout
|
13
|
+
|
14
|
+
def initialize message, timeout
|
15
|
+
super message
|
16
|
+
@timeout = timeout
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ENV_WHITELIST = [
|
21
|
+
/\ACHRUBY_/,
|
22
|
+
/\AGEM_/,
|
23
|
+
'PATH',
|
24
|
+
/\ARB_/,
|
25
|
+
'RUBYOPT'
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
EXEC_TIMEOUT_ERROR_FMT = 'process did not exit after %.03f seconds'.freeze
|
29
|
+
|
30
|
+
EXIT_STATUS_MISMATCH_FMT = <<~eoh.freeze
|
31
|
+
expected %<expected>d exit status got %<actual>d; output was:
|
32
|
+
%{separator}
|
33
|
+
%{output}
|
34
|
+
%{separator}
|
35
|
+
eoh
|
36
|
+
|
37
|
+
OUTPUT_SEPARATOR = (?- * 70).freeze
|
38
|
+
|
39
|
+
WAIT_MESSAGE_FMT = 'condition not met after %.03f seconds'.freeze
|
40
|
+
WAIT_OUTPUT_MESSAGE_FMT = <<~eoh.freeze
|
41
|
+
expected `%{pattern}' not seen after %<timeout>.03f seconds in:
|
42
|
+
%{separator}
|
43
|
+
%{output}
|
44
|
+
%{separator}
|
45
|
+
eoh
|
46
|
+
WAIT_TIMEOUT = ENV.key?('BAF_TEST_TIMEOUT') ?
|
47
|
+
ENV['BAF_TEST_TIMEOUT'].to_i :
|
48
|
+
2
|
49
|
+
|
50
|
+
WORKING_DIR = 'tmp/uat'.freeze
|
51
|
+
|
52
|
+
class << self
|
53
|
+
def build_regexp pattern, options = ''
|
54
|
+
Regexp.new(pattern, options.each_char.inject(0) do |m, e|
|
55
|
+
m | case e
|
56
|
+
when ?i then Regexp::IGNORECASE
|
57
|
+
when ?m then Regexp::MULTILINE
|
58
|
+
when ?x then Regexp::EXTENDED
|
59
|
+
end
|
60
|
+
end)
|
61
|
+
end
|
62
|
+
|
63
|
+
def exercise_scenario dir: WORKING_DIR
|
64
|
+
FileUtils.remove_entry_secure dir, true
|
65
|
+
FileUtils.mkdir_p dir
|
66
|
+
Dir.chdir dir do
|
67
|
+
yield
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def expect_ex process, exit_status
|
72
|
+
return if process.exit_status == exit_status
|
73
|
+
|
74
|
+
fail ExitStatusMismatch, EXIT_STATUS_MISMATCH_FMT % {
|
75
|
+
expected: exit_status,
|
76
|
+
actual: process.exit_status,
|
77
|
+
separator: OUTPUT_SEPARATOR,
|
78
|
+
output: process.output.chomp
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def run command, wait: true, env_allow: [], timeout: nil
|
83
|
+
Process.new(
|
84
|
+
command,
|
85
|
+
env_allow: ENV_WHITELIST + env_allow,
|
86
|
+
timeout: timeout || Process::TIMEOUT
|
87
|
+
).tap do |process|
|
88
|
+
process.start
|
89
|
+
wait process if wait
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def wait process
|
94
|
+
process.wait do
|
95
|
+
process.stop
|
96
|
+
fail ExecutionTimeout, EXEC_TIMEOUT_ERROR_FMT % process.timeout
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def unescape_step_arg str
|
101
|
+
str.gsub '\n', "\n"
|
102
|
+
end
|
103
|
+
|
104
|
+
def wait_until message: WAIT_MESSAGE_FMT, timeout: WAIT_TIMEOUT
|
105
|
+
return if yield
|
106
|
+
deadline = Time.now + timeout
|
107
|
+
until Time.now >= deadline
|
108
|
+
return if yield
|
109
|
+
sleep 0.05
|
110
|
+
end
|
111
|
+
fail WaitError.new message % timeout, timeout
|
112
|
+
end
|
113
|
+
|
114
|
+
def wait_output pattern, stream:, times: 1, timeout: WAIT_TIMEOUT
|
115
|
+
results = nil
|
116
|
+
wait_until timeout: timeout do
|
117
|
+
case pattern
|
118
|
+
when Regexp then (results = stream.call.scan(pattern)).size >= times
|
119
|
+
when String then stream.call.include? pattern
|
120
|
+
end
|
121
|
+
end
|
122
|
+
results
|
123
|
+
rescue Baf::Testing::WaitError => e
|
124
|
+
fail Baf::Testing::WaitError.new(WAIT_OUTPUT_MESSAGE_FMT % {
|
125
|
+
pattern: pattern,
|
126
|
+
timeout: timeout,
|
127
|
+
separator: OUTPUT_SEPARATOR,
|
128
|
+
output: stream.call.chomp
|
129
|
+
}, timeout)
|
130
|
+
end
|
131
|
+
|
132
|
+
def write_file path, content
|
133
|
+
FileUtils.mkdir_p File.dirname path
|
134
|
+
IO.write path, content
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
metadata
CHANGED
@@ -1,44 +1,117 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: baf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibault Jouan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: cucumber
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
41
|
-
|
40
|
+
version: '3.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.11'
|
55
|
+
description: |
|
56
|
+
baf helps writing an user acceptance test suite with a dedicated library
|
57
|
+
and cucumber steps. It can run and wait for programs in a modified
|
58
|
+
environment, verify the exit status, the output streams and other side
|
59
|
+
effects. It also supports interactive programs and writing to their
|
60
|
+
standard input.
|
61
|
+
|
62
|
+
Then, it provides a DSL to write the CLI:
|
63
|
+
|
64
|
+
require 'baf/cli'
|
65
|
+
|
66
|
+
module MyProgram
|
67
|
+
class CLI < Baf::CLI
|
68
|
+
def setup
|
69
|
+
flag_version '0.1.2'.freeze
|
70
|
+
|
71
|
+
option :c, :config, 'config', 'specify config file' do |path|
|
72
|
+
@config_path = path
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def run
|
77
|
+
usage! unless arguments.any?
|
78
|
+
|
79
|
+
puts 'arguments: %s' % arguments
|
80
|
+
puts 'config: %s' % @config_path if @config_path
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
MyProgram::CLI.run ARGV
|
86
|
+
|
87
|
+
Which behaves this way:
|
88
|
+
|
89
|
+
% ./my_program
|
90
|
+
Usage: my_program [options]
|
91
|
+
|
92
|
+
options:
|
93
|
+
-c, --config config specify config file
|
94
|
+
|
95
|
+
-h, --help print this message
|
96
|
+
-V, --version print version
|
97
|
+
zsh: exit 64 ./my_program
|
98
|
+
|
99
|
+
% ./my_program --wrong-arg
|
100
|
+
Usage: my_program [options]
|
101
|
+
|
102
|
+
options:
|
103
|
+
-c, --config config specify config file
|
104
|
+
|
105
|
+
-h, --help print this message
|
106
|
+
-V, --version print version
|
107
|
+
zsh: exit 64 ./my_program --wrong-arg
|
108
|
+
|
109
|
+
% ./my_program foo
|
110
|
+
arguments ["foo"]
|
111
|
+
|
112
|
+
% ./my_program -c some_file foo
|
113
|
+
arguments ["foo"]
|
114
|
+
config path some_file
|
42
115
|
email: tj@a13.fr
|
43
116
|
executables: []
|
44
117
|
extensions: []
|
@@ -50,12 +123,14 @@ files:
|
|
50
123
|
- lib/baf/flag.rb
|
51
124
|
- lib/baf/option.rb
|
52
125
|
- lib/baf/options_registrant.rb
|
126
|
+
- lib/baf/testing.rb
|
53
127
|
- lib/baf/testing/cucumber.rb
|
54
128
|
- lib/baf/testing/cucumber/steps/execution.rb
|
129
|
+
- lib/baf/testing/cucumber/steps/filesystem.rb
|
55
130
|
- lib/baf/testing/cucumber/steps/input.rb
|
56
131
|
- lib/baf/testing/cucumber/steps/output.rb
|
57
132
|
- lib/baf/testing/cucumber/steps/output_wait.rb
|
58
|
-
- lib/baf/
|
133
|
+
- lib/baf/testing/process.rb
|
59
134
|
homepage: https://rubygems.org/gems/baf
|
60
135
|
licenses:
|
61
136
|
- BSD-3-Clause
|
@@ -75,8 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
150
|
- !ruby/object:Gem::Version
|
76
151
|
version: '0'
|
77
152
|
requirements: []
|
78
|
-
rubygems_version: 3.
|
153
|
+
rubygems_version: 3.3.14
|
79
154
|
signing_key:
|
80
155
|
specification_version: 4
|
81
|
-
summary:
|
156
|
+
summary: Toolkit for testing and writing CLI programs
|
82
157
|
test_files: []
|
data/lib/baf/version.rb
DELETED