baf 0.13.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4b953e86f4f36c48b3401c8415ebad766276a775
4
- data.tar.gz: b25cb6a092dc3d54fae9696a8104fde2ff25b7c7
2
+ SHA256:
3
+ metadata.gz: c3dd2c36e21fb8a41d21f0d3ea90c5126274b9f68f19f4b2cb0f09c33aa38605
4
+ data.tar.gz: 9cf8f0b59d4b8cbb70f174912f2569f204fd27a82236a8e992c6729b366cc574
5
5
  SHA512:
6
- metadata.gz: 357dde19820d28cbffabe4f9edc9ba71992af6c341214c74c815db8978e989415f56f6ef8ddc6fee6a8a33c1ba4a5a09e409e82fb9800ce9203e03f26790919e
7
- data.tar.gz: 0a1bc15eab8fb67eab0b0baa1a3bdd9e4c13a93ff364fcc9e16dedc2ca36ef2d698b2678d44e5208f85fd929dc8388f088ffd2c6fda3ebdc1512c1d423fd6720
6
+ metadata.gz: bcc9f8fb5658bb47c75067a09912585878ee73ab227c09628eb4d2742e3f360a8c2f55b3effa1e2acc1329f130046f8ec76caefa66d6c468fbdce46596ba6370
7
+ data.tar.gz: 8aa8f06dee9cb55a12e560177c80a44f724c4fab30b5a5e9de9764f7fdd4eb12d0e9e76ebdedbad4fdd5fbb7cb58ea101fb3402d68d56fd191a0297b0dd198bb
data/lib/baf/cli.rb CHANGED
@@ -10,7 +10,7 @@ module Baf
10
10
  class CLI
11
11
  ArgumentError = Class.new ::Baf::ArgumentError
12
12
 
13
- EX_USAGE = 64
13
+ EX_USAGE = 64
14
14
  EX_SOFTWARE = 70
15
15
 
16
16
  class << self
@@ -43,15 +43,17 @@ module Baf
43
43
  parent = Object.const_get parent_name
44
44
  parent.const_defined?(:Env) ? parent.const_get(:Env) : Env
45
45
  end
46
+
47
+ def ruby2_keywords *; end unless Module.respond_to? :ruby2_keywords, true
46
48
  end
47
49
 
48
50
  attr_reader :arguments, :env, :parser
49
51
 
50
52
  def initialize env, arguments, **opts
51
- @env = env
52
- @arguments = arguments
53
- @parser = opts[:parser] || OptionParser.new
54
- @registrant = opts[:registrant] || OptionsRegistrant.new
53
+ @env = env
54
+ @arguments = arguments
55
+ @parser = opts.fetch(:parser) { OptionParser.new }
56
+ @registrant = opts.fetch(:registrant) { OptionsRegistrant.new }
55
57
 
56
58
  registrant.register(env, parser) { setup }
57
59
  end
@@ -63,6 +65,7 @@ module Baf
63
65
  registrant.banner = arg
64
66
  end
65
67
 
68
+ ruby2_keywords \
66
69
  def flag *args
67
70
  registrant.flag *args
68
71
  end
@@ -80,15 +83,15 @@ module Baf
80
83
  tail: true
81
84
  end
82
85
 
83
- def option *args
84
- args = [*args, Proc.new] if block_given?
86
+ def option *args, &block
87
+ args = [*args, block] if block_given?
85
88
  registrant.option *args
86
89
  end
87
90
 
88
91
  def parse_arguments!
89
92
  parser.parse! arguments
90
93
  rescue OptionParser::InvalidOption
91
- raise ArgumentError, parser
94
+ fail ArgumentError, parser
92
95
  end
93
96
 
94
97
  def usage!
data/lib/baf/env.rb CHANGED
@@ -7,10 +7,18 @@ module Baf
7
7
  def_delegators :@output, :print, :puts
8
8
  def_delegator :@output_error, :puts, :puts_error
9
9
 
10
- def initialize input: $input, output: $stdout, output_error: $stderr
11
- @input = input
12
- @output = output
10
+ def initialize input: $stdin, output: $stdout, output_error: $stderr
11
+ @input = input
12
+ @output = output
13
13
  @output_error = output_error
14
14
  end
15
+
16
+ def sync_output
17
+ output.sync = true
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :output
15
23
  end
16
24
  end
data/lib/baf/option.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  module Baf
2
2
  class Option
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
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
 
@@ -41,20 +41,20 @@ module Baf
41
41
 
42
42
  def build_attrs short, long, arg_or_desc = nil, desc_or_block = nil, block = nil
43
43
  {
44
- short: short,
45
- long: long,
46
- desc: arg_or_desc
44
+ short: short,
45
+ long: long,
46
+ desc: arg_or_desc
47
47
  }.merge case desc_or_block
48
48
  when Proc
49
49
  {
50
- desc: arg_or_desc,
51
- block: desc_or_block
50
+ desc: arg_or_desc,
51
+ block: desc_or_block
52
52
  }
53
53
  when String
54
54
  {
55
- arg: arg_or_desc,
56
- desc: desc_or_block,
57
- block: block
55
+ arg: arg_or_desc,
56
+ desc: desc_or_block,
57
+ block: block
58
58
  }
59
59
  else
60
60
  {}
@@ -3,8 +3,8 @@ require 'baf/option'
3
3
 
4
4
  module Baf
5
5
  class OptionsRegistrant
6
- SUMMARY_HEADER = "\noptions:".freeze
7
- HELP_PARSER_ARGS = %w[
6
+ SUMMARY_HEADER = "\noptions:".freeze
7
+ HELP_PARSER_ARGS = %w[
8
8
  -h
9
9
  --help
10
10
  print\ this\ message
@@ -1,50 +1,35 @@
1
- def program_run check: false, opts: nil, args: nil, wait: true
2
- cmd = [*@_baf_program ||= %w[ruby baf]]
3
- cmd << opts if opts
4
- cmd << args.split(' ') if args
5
- if wait
6
- run_simple cmd.join(' '), fail_on_error: false
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
- program_run check: !!check, wait: run == 'run'
29
- end
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 /^I( successfully)? (run|\w+) the program with command (.+)$/ do |check, run, cmd|
36
- program_run check: !!check, args: cmd, wait: run == 'run'
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+) the program with options? (-.+)$/ do |check, run, opts|
40
- program_run check: !!check, opts: opts, wait: run == 'run'
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 exit status must be (\d+)$/ do |exit_status|
45
- program_run_check status: exit_status.to_i
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 program must terminate successfully$/ do
49
- program_run_check status: 0
33
+ Then /^the exit status must be (\d+)$/ do |exit_status|
34
+ Baf::Testing.expect_ex $_baf[:process], Integer(exit_status)
50
35
  end
@@ -0,0 +1,3 @@
1
+ Given /^a file named ([^ ]+) with:$/ do |path, content|
2
+ Baf::Testing.write_file path, content + $/
3
+ end
@@ -1,3 +1,3 @@
1
1
  When /^I input "([^"]+)"$/ do |content|
2
- last_command_started.write unescape_text content
2
+ $_baf[:process].input Baf::Testing.unescape_step_arg content
3
3
  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(last_command_started.output).to be_empty
2
+ expect($_baf[:process].output).to be_empty
19
3
  end
20
4
 
21
5
  Then /^the output must contain:$/ do |content|
22
- expect(last_command_started.output).to include unescape_text content
6
+ expect($_baf[:process].output).to include content
23
7
  end
24
8
 
25
9
  Then /^the output must contain "([^"]+)"$/ do |content|
26
- expect(last_command_started.output).to include unescape_text content
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(last_command_started.output).not_to include unescape_text content
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
- expect_output content + $/
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
- expect_output content, stream: stream
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(last_command_started.output).to match build_regexp(pattern, options)
33
+ expect($_baf[:process].output)
34
+ .to match Baf::Testing.build_regexp(pattern, options)
44
35
  end
@@ -1,57 +1,16 @@
1
- require 'timeout'
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
- raise 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! build_regexp pattern, options
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! content + $/
11
+ wait_output content + $/
53
12
  end
54
13
 
55
14
  Then /^the output will contain "([^"]+)"$/ do |content|
56
- wait_output! content
15
+ wait_output content
57
16
  end
@@ -1,5 +1,11 @@
1
- require 'aruba/api'
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
@@ -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
data/lib/baf.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Baf
2
- Error = Class.new ::StandardError
2
+ Error = Class.new ::StandardError
3
3
  ArgumentError = Class.new Error
4
4
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibault Jouan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-22 00:00:00.000000000 Z
11
+ date: 2022-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: baf-testing
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,20 +25,93 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: cucumber
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
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: '0'
41
- description: Basic Application Framework
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,17 +123,19 @@ 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/version.rb
133
+ - lib/baf/testing/process.rb
59
134
  homepage: https://rubygems.org/gems/baf
60
135
  licenses:
61
136
  - BSD-3-Clause
62
137
  metadata: {}
63
- post_install_message:
138
+ post_install_message:
64
139
  rdoc_options: []
65
140
  require_paths:
66
141
  - lib
@@ -75,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
150
  - !ruby/object:Gem::Version
76
151
  version: '0'
77
152
  requirements: []
78
- rubyforge_project:
79
- rubygems_version: 2.6.14
80
- signing_key:
153
+ rubygems_version: 3.3.14
154
+ signing_key:
81
155
  specification_version: 4
82
- summary: Basic Application Framework
156
+ summary: Toolkit for testing and writing CLI programs
83
157
  test_files: []
data/lib/baf/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module Baf
2
- VERSION = '0.13.0'.freeze
3
- end