baf 0.14.0 → 0.15.1

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: 30b9c85a7af0b78d5fde855f4df47b907ee0f3f4
4
- data.tar.gz: 5fc0895f480eb22b9589c2d7ae5cb292838db483
2
+ SHA256:
3
+ metadata.gz: 9ae72395dc2c034e6b12f33f383794c31ed4ab8d0e93ebd4ae939c9ea3f218a5
4
+ data.tar.gz: 28268255bb47195a8647bdc66c2f89e21dbfd5dafbc6d6dcf7a473a8fee5d239
5
5
  SHA512:
6
- metadata.gz: 1048997ad551c80a4927c97966aa647eab6e3480a26f2131f2593bd0af29dfa0791ac74a401acce57972c9af5a8aa30b2c32121d1fc714c27c83a010c96a4e7b
7
- data.tar.gz: 946e877506f84efecd2f6ab63a9a8dece8665c1d6f592301424b3b58af3ac586ecc51ae08e34fe65f0d5bf966207d713bee23853951eea52be0ec74683bd309e
6
+ metadata.gz: 2ba74a745aa0b8e85a1045727a69c9fb5e4b931966391fbf81486f2fd2ed8ba0937323e93afdf30f20979d175762ec78b20ce4c677cad2d8caf6f7d53f4ee8d2
7
+ data.tar.gz: 845a48d062d19a4b81f909d534a7314a9d109a430a5222d03e7d1a35c30896473d146ef675d1f91290432e1579b3abf5810c24ac3df9292c3669ecbf7fbd6a6b
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,9 +7,9 @@ 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
15
 
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,44 +1,119 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.1
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-07-06 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
+ - - ">="
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: rake
28
+ name: cucumber
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '10'
47
+ version: '3.11'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '10'
41
- description: Basic Application Framework
54
+ version: '3.11'
55
+ description: |
56
+ == Baf
57
+
58
+ baf helps writing an user acceptance test suite with a dedicated library
59
+ and cucumber steps. It can run and wait for programs in a modified
60
+ environment, verify the exit status, the output streams and other side
61
+ effects. It also supports interactive programs and writing to their
62
+ standard input.
63
+
64
+ Then, it provides a DSL to write the CLI:
65
+
66
+ require 'baf/cli'
67
+
68
+ module MyProgram
69
+ class CLI < Baf::CLI
70
+ def setup
71
+ flag_version '0.1.2'.freeze
72
+
73
+ option :c, :config, 'config', 'specify config file' do |path|
74
+ @config_path = path
75
+ end
76
+ end
77
+
78
+ def run
79
+ usage! unless arguments.any?
80
+
81
+ puts 'arguments: %s' % arguments
82
+ puts 'config: %s' % @config_path if @config_path
83
+ end
84
+ end
85
+ end
86
+
87
+ MyProgram::CLI.run ARGV
88
+
89
+ Which behaves this way:
90
+
91
+ % ./my_program
92
+ Usage: my_program [options]
93
+
94
+ options:
95
+ -c, --config config specify config file
96
+
97
+ -h, --help print this message
98
+ -V, --version print version
99
+ zsh: exit 64 ./my_program
100
+
101
+ % ./my_program --wrong-arg
102
+ Usage: my_program [options]
103
+
104
+ options:
105
+ -c, --config config specify config file
106
+
107
+ -h, --help print this message
108
+ -V, --version print version
109
+ zsh: exit 64 ./my_program --wrong-arg
110
+
111
+ % ./my_program foo
112
+ arguments ["foo"]
113
+
114
+ % ./my_program -c some_file foo
115
+ arguments ["foo"]
116
+ config path some_file
42
117
  email: tj@a13.fr
43
118
  executables: []
44
119
  extensions: []
@@ -50,17 +125,19 @@ files:
50
125
  - lib/baf/flag.rb
51
126
  - lib/baf/option.rb
52
127
  - lib/baf/options_registrant.rb
128
+ - lib/baf/testing.rb
53
129
  - lib/baf/testing/cucumber.rb
54
130
  - lib/baf/testing/cucumber/steps/execution.rb
131
+ - lib/baf/testing/cucumber/steps/filesystem.rb
55
132
  - lib/baf/testing/cucumber/steps/input.rb
56
133
  - lib/baf/testing/cucumber/steps/output.rb
57
134
  - lib/baf/testing/cucumber/steps/output_wait.rb
58
- - lib/baf/version.rb
135
+ - lib/baf/testing/process.rb
59
136
  homepage: https://rubygems.org/gems/baf
60
137
  licenses:
61
138
  - BSD-3-Clause
62
139
  metadata: {}
63
- post_install_message:
140
+ post_install_message:
64
141
  rdoc_options: []
65
142
  require_paths:
66
143
  - lib
@@ -75,9 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
152
  - !ruby/object:Gem::Version
76
153
  version: '0'
77
154
  requirements: []
78
- rubyforge_project:
79
- rubygems_version: 2.6.14
80
- signing_key:
155
+ rubygems_version: 3.3.17
156
+ signing_key:
81
157
  specification_version: 4
82
- summary: Basic Application Framework
158
+ summary: Toolkit for testing and writing CLI programs
83
159
  test_files: []
data/lib/baf/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module Baf
2
- VERSION = '0.14.0'.freeze
3
- end