methadone 1.0.0.rc5 → 1.0.0.rc6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/lib/methadone/cli.rb +2 -0
  2. data/lib/methadone/cli_logging.rb +3 -0
  3. data/lib/methadone/cucumber.rb +1 -1
  4. data/lib/methadone/error.rb +8 -1
  5. data/lib/methadone/execution_strategy/jvm.rb +2 -0
  6. data/lib/methadone/execution_strategy/mri.rb +2 -0
  7. data/lib/methadone/execution_strategy/open_3.rb +2 -0
  8. data/lib/methadone/execution_strategy/open_4.rb +2 -0
  9. data/lib/methadone/execution_strategy/rbx_open_4.rb +2 -0
  10. data/lib/methadone/exit_now.rb +18 -3
  11. data/lib/methadone/main.rb +34 -6
  12. data/lib/methadone/process_status.rb +45 -0
  13. data/lib/methadone/sh.rb +52 -29
  14. data/lib/methadone/version.rb +1 -1
  15. data/methadone.gemspec +10 -0
  16. data/test/test_main.rb +20 -0
  17. data/test/test_sh.rb +104 -3
  18. metadata +23 -47
  19. data/tutorial/.vimrc +0 -6
  20. data/tutorial/1_intro.md +0 -52
  21. data/tutorial/2_bootstrap.md +0 -174
  22. data/tutorial/3_ui.md +0 -336
  23. data/tutorial/4_happy_path.md +0 -405
  24. data/tutorial/5_more_features.md +0 -693
  25. data/tutorial/6_refactor.md +0 -220
  26. data/tutorial/7_logging_debugging.md +0 -274
  27. data/tutorial/8_conclusion.md +0 -11
  28. data/tutorial/code/.rvmrc +0 -1
  29. data/tutorial/code/fullstop/.gitignore +0 -5
  30. data/tutorial/code/fullstop/Gemfile +0 -4
  31. data/tutorial/code/fullstop/LICENSE.txt +0 -202
  32. data/tutorial/code/fullstop/README.rdoc +0 -23
  33. data/tutorial/code/fullstop/Rakefile +0 -31
  34. data/tutorial/code/fullstop/bin/fullstop +0 -43
  35. data/tutorial/code/fullstop/features/fullstop.feature +0 -40
  36. data/tutorial/code/fullstop/features/step_definitions/fullstop_steps.rb +0 -64
  37. data/tutorial/code/fullstop/features/support/env.rb +0 -22
  38. data/tutorial/code/fullstop/fullstop.gemspec +0 -28
  39. data/tutorial/code/fullstop/lib/fullstop.rb +0 -2
  40. data/tutorial/code/fullstop/lib/fullstop/repo.rb +0 -38
  41. data/tutorial/code/fullstop/lib/fullstop/version.rb +0 -3
  42. data/tutorial/code/fullstop/test/tc_something.rb +0 -7
  43. data/tutorial/en.utf-8.add +0 -18
  44. data/tutorial/toc.md +0 -27
data/methadone.gemspec CHANGED
@@ -11,6 +11,16 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "http://github.com/davetron5000/methadone"
12
12
  s.summary = %q{Kick the bash habit and start your command-line apps off right}
13
13
  s.description = %q{Methadone provides a lot of small but useful features for developing a command-line app, including an opinionated bootstrapping process, some helpful cucumber steps, and some classes to bridge logging and output into a simple, unified, interface}
14
+ s.post_install_message = "
15
+
16
+ !!!!!!!!!!!!!!!!!!!!!!
17
+
18
+ If you are on Ruby 1.8 or REE, you MUST
19
+
20
+ gem install open4
21
+
22
+ !!!!!!!!!!!!!!!!!!!!!!
23
+ "
14
24
 
15
25
  s.rubyforge_project = "methadone"
16
26
 
data/test/test_main.rb CHANGED
@@ -209,6 +209,26 @@ class TestMain < BaseTest
209
209
  }
210
210
  end
211
211
 
212
+ test_that "when we help_now! we exit and show help" do
213
+ Given {
214
+ @message = any_sentence
215
+ main do
216
+ help_now!(@message)
217
+ end
218
+
219
+ opts.on("--switch") { options[:switch] = true }
220
+ opts.on("--flag FLAG") { |value| options[:flag] = value }
221
+
222
+ set_argv []
223
+ }
224
+
225
+ Then {
226
+ assert_exits(64) { When run_go! }
227
+ assert $stdout.string.include?(opts.to_s),"Expected #{$stdout.string} to contain #{opts.to_s}"
228
+ assert_logged_at_error @message
229
+ }
230
+ end
231
+
212
232
  test_that "opts allows us to more expediently set up OptionParser" do
213
233
  Given {
214
234
  @switch = nil
data/test/test_sh.rb CHANGED
@@ -108,6 +108,30 @@ class TestSH < Clean::Test::TestCase
108
108
  assert_successful_command_execution(@exit_code,@logger,@command,test_command_stdout)
109
109
  }
110
110
  end
111
+
112
+ test_that "#{method}, when the command succeeds and given a block of three arguments, calls the block with the stdout, stderr, and exit code" do
113
+ Given {
114
+ use_capturing_logger
115
+ @command = test_command
116
+ @block_called = false
117
+ @stdout_received = nil
118
+ @stderr_received = nil
119
+ @exitstatus_received = nil
120
+ }
121
+ When {
122
+ @exit_code = self.send(method,@command) do |stdout,stderr,exitstatus|
123
+ @stdout_received = stdout
124
+ @stderr_received = stderr
125
+ @exitstatus_received = exitstatus
126
+ end
127
+ }
128
+ Then {
129
+ @stdout_received.should == test_command_stdout
130
+ @stderr_received.length.should == 0
131
+ @exitstatus_received.should == 0
132
+ assert_successful_command_execution(@exit_code,@logger,@command,test_command_stdout)
133
+ }
134
+ end
111
135
  end
112
136
 
113
137
  test_that "sh, when the command fails and given a block, doesn't call the block" do
@@ -115,7 +139,7 @@ class TestSH < Clean::Test::TestCase
115
139
  use_capturing_logger
116
140
  @command = test_command("foo")
117
141
  @block_called = false
118
- }
142
+ }
119
143
  When {
120
144
  @exit_code = sh @command do
121
145
  @block_called = true
@@ -127,6 +151,50 @@ class TestSH < Clean::Test::TestCase
127
151
  }
128
152
  end
129
153
 
154
+ test_that "sh, when the command fails with an unexpected status, and given a block, doesn't call the block" do
155
+ Given {
156
+ use_capturing_logger
157
+ @command = test_command("foo")
158
+ @block_called = false
159
+ }
160
+ When {
161
+ @exit_code = sh @command, :expected => [2] do
162
+ @block_called = true
163
+ end
164
+ }
165
+ Then {
166
+ @exit_code.should == 1
167
+ assert_logger_output_for_failure(@logger,@command,test_command_stdout,test_command_stderr)
168
+ }
169
+ end
170
+
171
+ [1,[1],[1,2]].each do |expected|
172
+ [:sh,:sh!].each do |method|
173
+ test_that "#{method}, when the command fails with an expected error code (using syntax #{expected}/#{expected.class}), treats it as success" do
174
+ Given {
175
+ use_capturing_logger
176
+ @command = test_command("foo")
177
+ @block_called = false
178
+ @exitstatus_received = nil
179
+ }
180
+ When {
181
+ @exit_code = self.send(method,@command,:expected => expected) do |_,_,exitstatus|
182
+ @block_called = true
183
+ @exitstatus_received = exitstatus
184
+ end
185
+ }
186
+ Then {
187
+ @exit_code.should == 1
188
+ @block_called.should == true
189
+ @exitstatus_received.should == 1
190
+ @logger.debugs[0].should == "Executing '#{test_command}foo'"
191
+ @logger.debugs[1].should == "Output of '#{test_command}foo': #{test_command_stdout}"
192
+ @logger.warns[0].should == "Error output of '#{test_command}foo': #{test_command_stderr}"
193
+ }
194
+ end
195
+ end
196
+ end
197
+
130
198
  test_that "sh runs a command that will fail and logs about it" do
131
199
  Given {
132
200
  use_capturing_logger
@@ -219,7 +287,11 @@ class TestSH < Clean::Test::TestCase
219
287
 
220
288
  def run_command(command)
221
289
  @command = command
222
- [any_string,any_string,OpenStruct.new(:exitstatus => @exit_code)]
290
+ if @exitcode.kind_of? Fixnum
291
+ [any_string,any_string,OpenStruct.new(:exitstatus => @exitcode)]
292
+ else
293
+ [any_string,any_string,@exitcode]
294
+ end
223
295
  end
224
296
 
225
297
  def exception_meaning_command_not_found
@@ -251,7 +323,35 @@ class TestSH < Clean::Test::TestCase
251
323
  }
252
324
  Then {
253
325
  @app.strategy.command.should == @command
254
- @results.should == @exitstatus
326
+ @results.should == @exit_code
327
+ }
328
+ end
329
+
330
+ test_that "when the execution strategy returns a non-int, but truthy value, it gets coerced into a 0" do
331
+ Given {
332
+ @app = MyExecutionStrategyApp.new(true)
333
+ @command = "ls"
334
+ }
335
+ When {
336
+ @results = @app.sh(@command)
337
+ }
338
+ Then {
339
+ @app.strategy.command.should == @command
340
+ @results.should == 0
341
+ }
342
+ end
343
+
344
+ test_that "when the execution strategy returns a non-int, but falsey value, it gets coerced into a 1" do
345
+ Given {
346
+ @app = MyExecutionStrategyApp.new(false)
347
+ @command = "ls"
348
+ }
349
+ When {
350
+ @results = @app.sh(@command)
351
+ }
352
+ Then {
353
+ @app.strategy.command.should == @command
354
+ @results.should == 1
255
355
  }
256
356
  end
257
357
 
@@ -276,6 +376,7 @@ private
276
376
  change_logger(@logger)
277
377
  end
278
378
 
379
+ # Runs the test command which exits with the length of ARGV/args
279
380
  def test_command(args='')
280
381
  File.join(File.dirname(__FILE__),'command_for_tests.rb') + ' ' + args
281
382
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: methadone
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc5
4
+ version: 1.0.0.rc6
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-28 00:00:00.000000000Z
12
+ date: 2012-03-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &70123273030540 !ruby/object:Gem::Requirement
16
+ requirement: &70347550918840 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70123273030540
24
+ version_requirements: *70347550918840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-expectations
27
- requirement: &70123273030040 !ruby/object:Gem::Requirement
27
+ requirement: &70347550918300 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '2.6'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70123273030040
35
+ version_requirements: *70347550918300
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70123273029560 !ruby/object:Gem::Requirement
38
+ requirement: &70347550917880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70123273029560
46
+ version_requirements: *70347550917880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rdoc
49
- requirement: &70123273028900 !ruby/object:Gem::Requirement
49
+ requirement: &70347550917340 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '3.9'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70123273028900
57
+ version_requirements: *70347550917340
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: cucumber
60
- requirement: &70123273028320 !ruby/object:Gem::Requirement
60
+ requirement: &70347550916840 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.1.1
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70123273028320
68
+ version_requirements: *70347550916840
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: aruba
71
- requirement: &70123273027800 !ruby/object:Gem::Requirement
71
+ requirement: &70347550916460 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70123273027800
79
+ version_requirements: *70347550916460
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: simplecov
82
- requirement: &70123273027220 !ruby/object:Gem::Requirement
82
+ requirement: &70347550915860 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0.5'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70123273027220
90
+ version_requirements: *70347550915860
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: clean_test
93
- requirement: &70123273026680 !ruby/object:Gem::Requirement
93
+ requirement: &70347550915300 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0.10'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70123273026680
101
+ version_requirements: *70347550915300
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: mocha
104
- requirement: &70123273026220 !ruby/object:Gem::Requirement
104
+ requirement: &70347550914780 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70123273026220
112
+ version_requirements: *70347550914780
113
113
  description: Methadone provides a lot of small but useful features for developing
114
114
  a command-line app, including an opinionated bootstrapping process, some helpful
115
115
  cucumber steps, and some classes to bridge logging and output into a simple, unified,
@@ -152,6 +152,7 @@ files:
152
152
  - lib/methadone/execution_strategy/rbx_open_4.rb
153
153
  - lib/methadone/exit_now.rb
154
154
  - lib/methadone/main.rb
155
+ - lib/methadone/process_status.rb
155
156
  - lib/methadone/sh.rb
156
157
  - lib/methadone/version.rb
157
158
  - methadone.gemspec
@@ -179,35 +180,10 @@ files:
179
180
  - test/test_exit_now.rb
180
181
  - test/test_main.rb
181
182
  - test/test_sh.rb
182
- - tutorial/.vimrc
183
- - tutorial/1_intro.md
184
- - tutorial/2_bootstrap.md
185
- - tutorial/3_ui.md
186
- - tutorial/4_happy_path.md
187
- - tutorial/5_more_features.md
188
- - tutorial/6_refactor.md
189
- - tutorial/7_logging_debugging.md
190
- - tutorial/8_conclusion.md
191
- - tutorial/code/.rvmrc
192
- - tutorial/code/fullstop/.gitignore
193
- - tutorial/code/fullstop/Gemfile
194
- - tutorial/code/fullstop/LICENSE.txt
195
- - tutorial/code/fullstop/README.rdoc
196
- - tutorial/code/fullstop/Rakefile
197
- - tutorial/code/fullstop/bin/fullstop
198
- - tutorial/code/fullstop/features/fullstop.feature
199
- - tutorial/code/fullstop/features/step_definitions/fullstop_steps.rb
200
- - tutorial/code/fullstop/features/support/env.rb
201
- - tutorial/code/fullstop/fullstop.gemspec
202
- - tutorial/code/fullstop/lib/fullstop.rb
203
- - tutorial/code/fullstop/lib/fullstop/repo.rb
204
- - tutorial/code/fullstop/lib/fullstop/version.rb
205
- - tutorial/code/fullstop/test/tc_something.rb
206
- - tutorial/en.utf-8.add
207
- - tutorial/toc.md
208
183
  homepage: http://github.com/davetron5000/methadone
209
184
  licenses: []
210
- post_install_message:
185
+ post_install_message: ! "\n\n!!!!!!!!!!!!!!!!!!!!!!\n\nIf you are on Ruby 1.8 or REE,
186
+ you MUST\n\ngem install open4\n\n!!!!!!!!!!!!!!!!!!!!!!\n "
211
187
  rdoc_options: []
212
188
  require_paths:
213
189
  - lib
data/tutorial/.vimrc DELETED
@@ -1,6 +0,0 @@
1
- set spell spelllang=en_us
2
- syn spell toplevel
3
- set spf=~/Projects/methadone/tutorial/en.utf-8.add
4
- ab taht that
5
- ab builting built-in
6
- ab builtin built-in
data/tutorial/1_intro.md DELETED
@@ -1,52 +0,0 @@
1
- # Awesome Ruby Command Line Apps with Methadone
2
-
3
- Kick the bash habit, and make all your command-line apps with Ruby.
4
-
5
- In [Build Awesome Command-Line Applications in Ruby][clibook], I lay out how to make an awesome command-line application using
6
- Ruby. The book focuses on tools like `OptionParser` to create the app. As I wrote and researched, it became clear that there
7
- was a gap between `OptionParser`, which is very powerful, yet verbose, and other command line tools like [trollop][trollop],
8
- [main][main], and [thor][thor], which have simple APIs, but aren't very powerful.
9
-
10
- [clibook]: http://www.awesomecommandlineapps.com
11
- [main]: http://github.com/ahoward/main
12
- [trollop]: http://trollop.rubyforge.org
13
- [thor]: http://www.github.com/wycats/thor
14
-
15
- I created Methadone to bridge that gap. Methadone provides all the power of `OptionParser`, but has a simple, clean API.
16
- Methadone also includes additional tools and classes to make your command-line apps even better.
17
-
18
- This tutorial will show you how to make a simple command-line app using Methadone that will be easy-to-use, easy-to-maintain, and
19
- fully tested.
20
-
21
- ## What you'll need
22
-
23
- You'll need an installation of Ruby and the ability to install Ruby gems. I would recommend that you use rvm and a gemset to
24
- work through these, but they aren't required. There's a decent [walkthrough][setup] on my book's website of setting this up the
25
- way I work. Although Methadone works on most versions of Ruby, I would recommend you use Ruby
26
- 1.9.3, if you can. If not, try to use an MRI Ruby as those versions (1.8.7, REE, 1.9.2, or 1.9.3) have the highest compatibility
27
- with other gems.
28
-
29
- [setup]: http://www.awesomecommandlineapps.com/setup.html
30
-
31
- ## How this is organized
32
-
33
- This is a tutorial for making a simple command-line app. Unlike some tutorials and books, we will be working through this using
34
- a "test-first" approach. One thing that Methadone tries to enable is using [TDD][tdd] for creating and writing your command-line
35
- app. As such, we'll write tests as much as possible to drive our work.
36
-
37
- [tdd]: http://en.wikipedia.org/wiki/Test-driven_development
38
-
39
- ## The tutorial app
40
-
41
- The app we'll build is going to manage "dot files". These are the files that live in your home directory and configure your
42
- shell, editor, and various other programs. For example, `~/.bashrc` is the file to configure `bash`. Many developers keep these
43
- files on [Github][github] so that they can maintain the same files across multiple computers.
44
-
45
- [github]: http://www.github.com
46
-
47
- To set this up on a new computer, you have to checkout the repo, and symlink all the files to your home directory. To update the
48
- files you have to update the repo and then check if any new files were added. This is the sort of tedious manual process that is
49
- ripe for automation via a command-line app.
50
-
51
- We'll develop a simplified version to demonstrate how to use Methadone.
52
-
@@ -1,174 +0,0 @@
1
- # Bootstrapping our app
2
-
3
- One thing that's great about writing a webapp with Ruby on Rails is that, with one command, you have a skeleton app, including
4
- a fully functional test framework set up. You can start writing tests immediately. There's no common equivalent for a
5
- command-line app, which is what Methadone aims to provide.
6
-
7
- Methadone will also bootstrap other aspects of your app, such a `Rakefile`, a gemspec, a shell of an executable, a license, and a
8
- README. First, let's install Methadone via RubyGems (note that if your aren't using rvm, you may need to use `sudo` to install
9
- gems):
10
-
11
- ```sh
12
- $ gem install methadone
13
- Fetching: methadone-1.0.0.gem (100%)
14
- Successfully installed methadone-1.0.0
15
- 1 gem installed
16
- Installing ri documentation for methadone-1.0.0...
17
- Installing RDoc documentation for methadone-1.0.0...
18
- ```
19
-
20
- Methadone comes bundled with a command-line app that will do the bootstrapping:
21
-
22
- ```sh
23
- $ methadone --help
24
- Usage: methadone [options] app_name
25
-
26
- Kick the bash habit by bootstrapping your Ruby command-line apps
27
-
28
- v1.0.0
29
-
30
- Options:
31
- --force Overwrite files if they exist
32
- --[no-]readme [Do not ]produce a README file
33
- -l, --license LICENSE Specify the license for your project (mit|apache|custom|NONE)
34
- --log-level LEVEL Set the logging level (debug|info|warn|error|fatal)
35
- (Default: info)
36
- --version Show help/version info
37
-
38
- Default values can be placed in the METHODONE_OPTS environment variable
39
- ```
40
-
41
- The app that we'll be building in this tutorial is be called `fullstop`, which is derived from the [British name][fullstop] for a period, which is the character used as a prefix to our dotfiles, and, is the reason they are called "dot" files in the first place. Based on the command-line syntax for `methadone`, we can create our app right now with one simple command. We'll use the Apache license as well as a README.
42
-
43
- [fullstop]: http://en.wikipedia.org/wiki/Full_stop
44
-
45
- ```sh
46
- $ methadone --readme --license apache fullstop
47
- $ ls fullstop
48
- Gemfile README.rdoc bin/
49
- fullstop.gemspec test/ LICENSE.txt
50
- Rakefile features/ lib/
51
- ```
52
-
53
- As you can see, we've got a generic gemified project. Before we can start developing, we'll need to install a few gems using Bundler first:
54
-
55
- ```sh
56
- $ cd fullstop
57
- $ bundle install
58
- Fetching source index for http://rubygems.org/
59
- Installing rake (0.9.2.2)
60
- Installing ffi (1.0.11) with native extensions
61
- Installing childprocess (0.3.1)
62
- Installing builder (3.0.0)
63
- Installing diff-lcs (1.1.3)
64
- Installing json (1.6.5) with native extensions
65
- Installing gherkin (2.7.6) with native extensions
66
- Installing term-ansicolor (1.0.7)
67
- Installing cucumber (1.1.4)
68
- Installing rspec-core (2.8.0)
69
- Installing rspec-expectations (2.8.0)
70
- Installing rspec-mocks (2.8.0)
71
- Installing rspec (2.8.0)
72
- Installing aruba (0.4.11)
73
- Using bundler (1.0.21)
74
- Installing methadone (0.5.1)
75
- Using fullstop (0.0.1) from source at /Users/davec/Projects/methadone/tutorial/code/fullstop
76
- Installing rdoc (3.12)
77
- Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
78
- ```
79
-
80
- Your versions might not match up, but this should be more or less what you see. The first thing you'll notice is that this seems
81
- like a *lot* of gems! Most of them are brought in by our acceptance testing framework, [aruba][aruba], which is a library on top
82
- of [cucumber][cucumber] tailor-made for testing command-line apps. Methadone also assumes you'll be unit
83
- testing with `Test::Unit`, which is a fine default. In fact, both unit and acceptance tests are set up for you and available
84
- via `rake` tasks. Let's see them in action.
85
-
86
- [aruba]: http://www.github.com/cucumber/aruba
87
- [cucumber]: http://cukes.info
88
-
89
- ```sh
90
- $ rake
91
- Run options:
92
-
93
- # Running tests:
94
-
95
- .
96
-
97
- Finished tests in 0.000623s, 1605.1364 tests/s, 1605.1364 assertions/s.
98
-
99
- 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
100
- ......
101
-
102
- 1 scenario (1 passed)
103
- 6 steps (6 passed)
104
- 0m0.136s
105
- ```
106
-
107
- As you can see, we ran one unit test and one cucumber scenario. These were provided by Methadone as placeholders for your tests.
108
- Just like what Ruby on Rails does when you create an app, Methadone has reduced the friction between your need to write software
109
- and your ability to do so.
110
-
111
- Methadone also generated a very basic scaffold of the command-line app itself. It's in `bin` and is called `fullstop` (the
112
- argument we gave to `methadone`). Let's run it now:
113
-
114
- ```sh
115
- $ bin/fullstop
116
- /Users/davec/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- fullstop (LoadError)
117
- from /Users/davec/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
118
- from bin/fullstop:5:in `<main>'
119
- ```
120
-
121
- Oops! What happened?
122
-
123
- Methadone is encouraging you to develop your app with best practices, and one such practice is to not have your executables mess with the load path. In many Ruby command-line applications, you'll see code like this at the top of the file:
124
-
125
- ```ruby
126
- $: << File.join(File.dirname(__FILE__),'..','lib')
127
- ```
128
-
129
- This puts the `lib` directory, that is relative to the `bin` directory (where our executable lives), into Ruby's load path. This will allow *us* to run the app easily, but for your users, it's not necessary if you distribute your app with RubyGems (which you should do) and it's generally not a good idea to modify the load path. In order to run the app directly during development, we'll need to use `bundle exec`, like so (note that we won't be running our app a lot in development, but scripting it using Aruba so we can test its behavior in an automated way):
130
-
131
- ```sh
132
- $ bundle exec bin/fullstop --help
133
- Usage: fullstop [options]
134
-
135
- v0.0.1
136
-
137
- Options:
138
- --version Show help/version info
139
- --log-level LEVEL Set the logging level (debug|info|warn|error|fatal)
140
- (Default: info)
141
- ```
142
-
143
-
144
- Not too bad! We've got the makings of a reasonable help system, versioning support, a usage statement and a working executable.
145
- Just remember to run the app with `bundle exec` while you're developing. Remember, your users won't have to worry about as long
146
- as they installed it with RubyGems.
147
-
148
- Before we move on, let's look at the cucumber scenario that Methadone generated for us. We're going to work "outside in" on our
149
- app, so this will be a sneak peek at what we'll be doing next.
150
-
151
- ```sh
152
- $ cat features/fullstop.feature
153
- ```
154
- ```cucumber
155
- Feature: My bootstrapped app kinda works
156
- In order to get going on coding my awesome app
157
- I want to have aruba and cucumber setup
158
- So I don't have to do it myself
159
-
160
- Scenario: App just runs
161
- When I get help for "fullstop"
162
- Then the exit status should be 0
163
- And the banner should be present
164
- And the banner should document that this app takes options
165
- And the following options should be documented:
166
- |--version|
167
- And the banner should document that this app takes no arguments
168
- ```
169
-
170
- We probably won't keep this exactly scenario around, but it's a good demonstration of Aruba and Cucumber, and will help to get us
171
- going. Since this scenario passes, that means that we already have the cucumber steps defined somewhere. As we'll see, the
172
- combination of Aruba and Methadone results in a lot of pre-defined steps that make acceptance testing a snap.
173
-
174
- In the next section, we'll expand this scenario to create the user interface we'll need to get our app going.