crab 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ # vim: set ft=ruby :
2
+ require 'crab'
3
+
4
+ def add_or_update_options(banner)
5
+ Trollop::options do
6
+ banner banner
7
+ opt :priority, "Priority (one of: #{Crab::TestCase::PRIORITIES.join(" ")}", :default => "important", :short => '-p'
8
+ opt :risk, "Risk (one of: #{Crab::TestCase::RISKS.join(" ")})", :default => "medium", :short => '-r'
9
+ opt :method, "Method (one of: #{Crab::TestCase::METHODS.join(" ")})", :default => "automated", :short => '-m'
10
+ opt :type, "Type (one of: #{Crab::TestCase::TYPES.join(" ")})", :default => "acceptance", :short => '-t'
11
+ opt :pre, "Pre-conditions", :default => "N/A"
12
+ opt :post, "Post-conditions", :default => "N/A"
13
+ opt :desc, "Description", :default => "N/A", :short => '-d'
14
+ end
15
+ end
16
+
17
+ def sanitize_options(opts, creating=true)
18
+ result = {}
19
+ result[:priority] = opts[:priority].capitalize if creating || opts[:priority_given]
20
+ result[:risk] = opts[:risk].capitalize if creating || opts[:risk_given]
21
+ result[:method] = opts[:method].capitalize if creating || opts[:method_given]
22
+ result[:type] = opts[:type].capitalize if creating || opts[:type_given]
23
+ result[:pre_conditions] = opts[:pre] if creating || opts[:pre_given]
24
+ result[:post_conditions] = opts[:post] if creating || opts[:post_given]
25
+ result[:description] = opts[:desc] if creating || opts[:desc_given]
26
+ result
27
+ end
28
+
29
+ rally = Crab::Rally.new
30
+
31
+ Trollop::options do
32
+ banner <<-BANNER
33
+ crab testcase: manage test cases in a story (add, update, delete)
34
+
35
+ Usage: crab testcase add story name [options]
36
+ crab testcase update testcase [options]
37
+ crab testcase delete testcase [options]
38
+ BANNER
39
+ stop_on %w{add update delete}
40
+ end
41
+
42
+ sub = ARGV.shift
43
+ case sub
44
+ when "add"
45
+ opts = add_or_update_options "crab testcase add: add a test case to a story in Rally"
46
+
47
+ story_id = ARGV.shift
48
+ name = ARGV.join(" ")
49
+ add(story_id, name, opts)
50
+
51
+ rally.connect
52
+ tc = rally.create_test_case(story_id, name, sanitize_options(opts))
53
+
54
+ puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
55
+
56
+ when "update"
57
+ opts = add_or_update_options "crab testcase update: update a test case in Rally"
58
+
59
+ tc_id = ARGV.shift
60
+
61
+ rally.connect
62
+ tc = rally.find_test_case(tc_id)
63
+ tc.update(sanitize_options(opts))
64
+ puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
65
+
66
+ when "delete"
67
+ Trollop::options do
68
+ banner "crab testcase delete: delete a test case in Rally"
69
+ end
70
+
71
+ tc_id = ARGV.shift
72
+ rally.connect
73
+ tc = rally.find_test_case(tc_id)
74
+ tc.delete
75
+ puts "Test case #{tc_id} deleted."
76
+
77
+ else
78
+ Trollop::die "Unknown subcommand#{' ' + sub.inspect if sub}"
79
+ end
@@ -0,0 +1,8 @@
1
+ # vim: set ft=ruby :
2
+ require 'crab'
3
+
4
+ Trollop::options do
5
+ banner "crab truncate: Make spohr happy!"
6
+ end
7
+
8
+ puts "You have been truncated! Now back to work!"
@@ -0,0 +1,61 @@
1
+ # vim: set ft=ruby :
2
+ require 'crab'
3
+
4
+ include Crab::Utilities
5
+
6
+ cmd_opts = Trollop::options do
7
+ banner <<-BANNER
8
+ crab update: update a story in Rally
9
+
10
+ Usage: crab update story [options]
11
+ BANNER
12
+ opt :name, "Name (title)", :type => String, :short => "-n"
13
+ opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
14
+ opt :estimate, "Estimate", :type => :int, :short => "-e"
15
+ opt :iteration, "Iteration", :type => String, :short => "-i"
16
+ opt :release, "Release", :type => String, :short => "-r"
17
+ opt :blocked, "Blocked", :short => "-b"
18
+ opt :unblocked, "Unblocked", :short => "-u"
19
+ opt :parent, "Parent", :type => String, :short => "-p"
20
+ end
21
+
22
+ rally = Crab::Rally.new
23
+
24
+ Trollop::die "No story given" if ARGV.empty?
25
+ Trollop::die "Nothing to update. Please provide some options" unless cmd_opts.any? {|k, v| k.to_s =~ /_given$/ }
26
+
27
+ opts = {}
28
+ opts[:name] = cmd_opts[:name] if cmd_opts[:name_given]
29
+ opts[:schedule_state] = state_from(cmd_opts[:state]) if cmd_opts[:state_given]
30
+
31
+ if cmd_opts[:estimate_given]
32
+ opts[:plan_estimate] = cmd_opts[:estimate] # nobody is going to remember "Plan Estimate", really
33
+ end
34
+
35
+ opts[:blocked] = cmd_opts[:blocked] if cmd_opts[:blocked_given]
36
+ opts[:blocked] = !cmd_opts[:unblocked] if cmd_opts[:unblocked_given]
37
+
38
+ rally.connect
39
+
40
+ story = rally.find_story_with_id ARGV.first
41
+
42
+ if cmd_opts[:iteration_given]
43
+ opts[:iteration] = rally.find_iteration_by_name cmd_opts[:iteration]
44
+ Trollop::die "Unknown iteration \"#{cmd_opts[:iteration]}\"" if opts[:iteration].nil?
45
+ end
46
+
47
+ if cmd_opts[:release_given]
48
+ opts[:release] = rally.find_release_by_name cmd_opts[:release]
49
+ Trollop::die "Unknown release \"#{cmd_opts[:release]}\"" if opts[:release].nil?
50
+ end
51
+
52
+ if cmd_opts[:parent_given]
53
+ opts[:parent] = rally.find_story_with_id(cmd_opts[:parent]).rally_object
54
+ Trollop::die "Unknown story \"#{cmd_opts[:parent]}\"" if opts[:parent].nil?
55
+ end
56
+
57
+ opts[:name] = story.name if opts[:name].blank?
58
+
59
+ story.update opts
60
+
61
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
@@ -0,0 +1,61 @@
1
+ # vim: set ft=ruby :
2
+ require 'crab'
3
+
4
+ include Crab::Utilities
5
+
6
+ cmd_opts = Trollop::options do
7
+ banner <<-BANNER
8
+ crab update: update a story in Rally
9
+
10
+ Usage: crab update story [options]
11
+ BANNER
12
+ opt :name, "Name (title)", :type => String, :short => "-n"
13
+ opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
14
+ opt :estimate, "Estimate", :type => :int, :short => "-e"
15
+ opt :iteration, "Iteration", :type => String, :short => "-i"
16
+ opt :release, "Release", :type => String, :short => "-r"
17
+ opt :blocked, "Blocked", :short => "-b"
18
+ opt :unblocked, "Unblocked", :short => "-u"
19
+ opt :parent, "Parent", :type => String, :short => "-p"
20
+ end
21
+
22
+ rally = Crab::Rally.new
23
+
24
+ Trollop::die "No story given" if ARGV.empty?
25
+ Trollop::die "Nothing to update. Please provide some options" unless cmd_opts.any? {|k, v| k.to_s =~ /_given$/ }
26
+
27
+ opts = {}
28
+ opts[:name] = cmd_opts[:name] if cmd_opts[:name_given]
29
+ opts[:schedule_state] = state_from(cmd_opts[:state]) if cmd_opts[:state_given]
30
+
31
+ if cmd_opts[:estimate_given]
32
+ opts[:plan_estimate] = cmd_opts[:estimate] # nobody is going to remember "Plan Estimate", really
33
+ end
34
+
35
+ opts[:blocked] = cmd_opts[:blocked] if cmd_opts[:blocked_given]
36
+ opts[:blocked] = !cmd_opts[:unblocked] if cmd_opts[:unblocked_given]
37
+
38
+ rally.connect
39
+
40
+ story = rally.find_story_with_id ARGV.first
41
+
42
+ if cmd_opts[:iteration_given]
43
+ opts[:iteration] = rally.find_iteration_by_name cmd_opts[:iteration]
44
+ Trollop::die "Unknown iteration \"#{cmd_opts[:iteration]}\"" if opts[:iteration].nil?
45
+ end
46
+
47
+ if cmd_opts[:release_given]
48
+ opts[:release] = rally.find_release_by_name cmd_opts[:release]
49
+ Trollop::die "Unknown release \"#{cmd_opts[:release]}\"" if opts[:release].nil?
50
+ end
51
+
52
+ if cmd_opts[:parent_given]
53
+ opts[:parent] = rally.find_story_with_id(cmd_opts[:parent]).rally_object
54
+ Trollop::die "Unknown story \"#{cmd_opts[:parent]}\"" if opts[:parent].nil?
55
+ end
56
+
57
+ opts[:name] = story.name if opts[:name].blank?
58
+
59
+ story.update opts
60
+
61
+ puts "#{story.formatted_id}: #{story.name} (#{story.state})"
@@ -16,6 +16,8 @@ Gem::Specification.new do |s|
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.default_executable = 'crab'
20
+
19
21
  s.require_paths = ["lib"]
20
22
 
21
23
  s.add_development_dependency 'aruba'
@@ -0,0 +1,15 @@
1
+ Feature: Move in Rally
2
+
3
+ In order to update a story status without the hassle of figuring out 'crab update'
4
+ An incredibly lazy develper
5
+ Wants to use a simple command to move a story to the next available state
6
+
7
+ Background:
8
+ Given I am logged in
9
+
10
+ Scenario: Move Then Go Back
11
+ When I run `crab move US4988`
12
+ Then the output should contain "US4988: Sample Crab Story (defined)"
13
+
14
+ When I run `crab move US4988 --back`
15
+ Then the output should contain "US4988: Sample Crab Story (grooming)"
@@ -14,8 +14,14 @@ Then /^the user's home directory should have a file named "([^"]*)"$/ do |file|
14
14
  end
15
15
 
16
16
  def get_rally_credentials
17
- username, password = File.read(File.join(File.dirname(__FILE__), '..', '..', '.crab', 'credentials')).split(/\n/)
18
- [ username, password ]
17
+ file = File.expand_path("~/.crab/tests/credentials")
18
+
19
+ if File.exists? file
20
+ username, password = File.read(file).split(/\n/)
21
+ [ username, password ]
22
+ else
23
+ raise "Please run rake cucumber:setup first"
24
+ end
19
25
  end
20
26
 
21
27
  When /^I type my username$/ do
@@ -79,8 +85,10 @@ Given /^no project is selected$/ do
79
85
  end
80
86
 
81
87
  def get_project
82
- if File.exists? ".crab/project"
83
- File.read(".crab/project").strip
88
+ if File.exists? ".crab/tests/project"
89
+ File.read(".crab/tests/project").strip
90
+ else
91
+ raise "Please run rake cucumber:setup first"
84
92
  end
85
93
  end
86
94
 
@@ -95,7 +103,7 @@ end
95
103
 
96
104
  def get_test_project
97
105
  begin
98
- test_project = File.read(File.expand_path("~/.crab/test_project"))
106
+ test_project = File.read(File.expand_path("~/.crab/tests/project"))
99
107
  rescue
100
108
  raise "Looks like your test project isn't set up. Please run 'rake cucumber:setup'"
101
109
  end
@@ -35,7 +35,7 @@ Feature: Subcommand Help
35
35
  """
36
36
  crab pull: pulls stories from Rally and writes them out as Cucumber features
37
37
 
38
- Usage: crab [options] pull story1 [story2 ...]
38
+ Usage: crab pull [options] story1 [story2 ...]
39
39
  """
40
40
 
41
41
  Scenario: Show Subcommand
@@ -44,7 +44,7 @@ Feature: Subcommand Help
44
44
  """
45
45
  crab show: displays a story in Rally as a Cucumber feature
46
46
 
47
- Usage: crab [options] show story
47
+ Usage: crab show story
48
48
  """
49
49
 
50
50
  Scenario: Create Subcommand
@@ -53,7 +53,7 @@ Feature: Subcommand Help
53
53
  """
54
54
  crab create: create a new story in Rally
55
55
 
56
- Usage: crab [options] create name [options]
56
+ Usage: crab create name [options]
57
57
  """
58
58
 
59
59
  Scenario: Delete Subcommand
@@ -62,15 +62,15 @@ Feature: Subcommand Help
62
62
  """
63
63
  crab delete: delete an existing story in Rally
64
64
 
65
- Usage: crab [options] delete story [options]
65
+ Usage: crab delete story [options]
66
66
  """
67
67
 
68
68
  Scenario: Testcase Subcommand
69
69
  When I run `crab testcase --help`
70
70
  Then the output should contain "crab testcase: manage test cases in a story (add, update, delete)"
71
- And the output should contain "Usage: crab [options] testcase add story name [options]"
72
- And the output should contain "crab [options] testcase update testcase [options]"
73
- And the output should contain "crab [options] testcase delete testcase [options]"
71
+ And the output should contain "Usage: crab testcase add story name [options]"
72
+ And the output should contain "crab testcase update testcase [options]"
73
+ And the output should contain "crab testcase delete testcase [options]"
74
74
 
75
75
  Scenario: Update Subcommand
76
76
  When I run `crab update --help`
@@ -78,7 +78,7 @@ Feature: Subcommand Help
78
78
  """
79
79
  crab update: update a story in Rally
80
80
 
81
- Usage: crab [options] update story [options]
81
+ Usage: crab update story [options]
82
82
  """
83
83
 
84
84
  Scenario: Update Needs a Story Number
@@ -95,7 +95,7 @@ Feature: Subcommand Help
95
95
  """
96
96
  crab find: find a story in Rally
97
97
 
98
- Usage: crab [options] find [options] [text]
98
+ Usage: crab find [options] [text]
99
99
  """
100
100
 
101
101
  Scenario: Move Subcommand
@@ -104,6 +104,6 @@ Feature: Subcommand Help
104
104
  """
105
105
  crab move: move a story from one status to the next (or previous)
106
106
 
107
- Usage: crab [options] move story [options]
107
+ Usage: crab move story [options]
108
108
  """
109
109
 
@@ -16,18 +16,6 @@ require "crab/rally"
16
16
  require "crab/story"
17
17
  require "crab/testcase"
18
18
 
19
- # supported commands
20
- require "crab/commands/create"
21
- require "crab/commands/delete"
22
- require "crab/commands/find"
23
- require "crab/commands/login"
24
- require "crab/commands/move"
25
- require "crab/commands/project"
26
- require "crab/commands/pull"
27
- require "crab/commands/show"
28
- require "crab/commands/testcase"
29
- require "crab/commands/update"
30
-
31
19
  # cucumber support
32
20
  require "crab/cucumber_feature"
33
21
  require "crab/cucumber_scenario"
@@ -11,11 +11,12 @@ module Crab
11
11
  "testcase" => "Manage test cases in a story (add, update, delete)",
12
12
  "update" => "Update a story (name, estimate, etc)",
13
13
  "move" => "Move a story from one status to the next (or previous)",
14
+ "truncate" => "Make sphor happy!",
14
15
  }
15
16
 
16
17
  class CLI
17
18
  def self.start
18
- global_opts = Trollop::options do
19
+ Trollop::options do
19
20
  version "crab version #{Crab::VERSION}"
20
21
  banner """
21
22
  crab version #{Crab::VERSION}: A Cucumber-Rally bridge
@@ -27,9 +28,12 @@ crab version #{Crab::VERSION}: A Cucumber-Rally bridge
27
28
 
28
29
  cmd = ARGV.shift # get the subcommand
29
30
  Trollop::die "Unknown subcommand" unless cmd
30
- Trollop::die "Unknown subcommand #{cmd.inspect}" unless Crab::Commands.const_defined? cmd.capitalize
31
31
 
32
- Crab::Commands.const_get(cmd.capitalize).new(global_opts, ARGV).run
32
+ unless system("crab-#{cmd}", *ARGV)
33
+ if $?.exitstatus == 127 # bash 'command not found error'
34
+ Trollop::die "Unknown subcommand #{cmd.inspect}"
35
+ end
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -12,16 +12,33 @@ module Crab
12
12
  end
13
13
 
14
14
  def valid_project_name(cmd_opts)
15
- project_name = cmd_opts[:project_given] ? cmd_opts[:project] : Crab::Commands::Project.current_project_name
15
+ project_name = cmd_opts[:project_given] ? cmd_opts[:project] : current_project_name
16
16
  Trollop::die :project, "must be specified" if project_name.blank?
17
17
  project_name
18
18
  end
19
19
 
20
+ def current_project_name
21
+ if File.exists? ".crab/project"
22
+ File.read(".crab/project").strip
23
+ end
24
+ end
25
+
20
26
  def state_from(option)
21
27
  fixed_option = option.gsub(/(^\w|[-_]\w)/) { $1.upcase.gsub(/_/, '-') }
22
28
  Trollop::die :state, "has an invalid value" unless Crab::Story::VALID_STATES.include? fixed_option
23
29
  fixed_option
24
30
  end
25
31
 
32
+ def state_before(state)
33
+ i = (Crab::Story::VALID_STATES.index(state) || 0) - 1
34
+ Crab::Story::VALID_STATES[i < 0 ? 0 : i]
35
+ end
36
+
37
+ def state_after(state)
38
+ i = (Crab::Story::VALID_STATES.index(state) || 0) + 1
39
+ max = Crab::Story::VALID_STATES.size
40
+ Crab::Story::VALID_STATES[i >= max ? max -1 : i]
41
+ end
42
+
26
43
  end
27
44
  end
@@ -1,3 +1,3 @@
1
1
  module Crab
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crab
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 7
10
- version: 0.1.7
9
+ - 8
10
+ version: 0.1.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Carlos Villela
@@ -16,7 +16,7 @@ bindir: bin
16
16
  cert_chain: []
17
17
 
18
18
  date: 2011-09-28 00:00:00 -03:00
19
- default_executable:
19
+ default_executable: crab
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: aruba
@@ -149,6 +149,25 @@ email:
149
149
  - cvillela@thoughtworks.com
150
150
  executables:
151
151
  - crab
152
+ - crab-add
153
+ - crab-change
154
+ - crab-create
155
+ - crab-del
156
+ - crab-delete
157
+ - crab-find
158
+ - crab-login
159
+ - crab-move
160
+ - crab-mv
161
+ - crab-project
162
+ - crab-pull
163
+ - crab-remove
164
+ - crab-rm
165
+ - crab-show
166
+ - crab-tc
167
+ - crab-testcase
168
+ - crab-truncate
169
+ - crab-up
170
+ - crab-update
152
171
  extensions: []
153
172
 
154
173
  extra_rdoc_files: []
@@ -160,10 +179,30 @@ files:
160
179
  - README.md
161
180
  - Rakefile
162
181
  - bin/crab
182
+ - bin/crab-add
183
+ - bin/crab-change
184
+ - bin/crab-create
185
+ - bin/crab-del
186
+ - bin/crab-delete
187
+ - bin/crab-find
188
+ - bin/crab-login
189
+ - bin/crab-move
190
+ - bin/crab-mv
191
+ - bin/crab-project
192
+ - bin/crab-pull
193
+ - bin/crab-remove
194
+ - bin/crab-rm
195
+ - bin/crab-show
196
+ - bin/crab-tc
197
+ - bin/crab-testcase
198
+ - bin/crab-truncate
199
+ - bin/crab-up
200
+ - bin/crab-update
163
201
  - crab.gemspec
164
202
  - features/create-and-delete-story.feature
165
203
  - features/find-text-in-stories.feature
166
204
  - features/login-and-out-of-rally.feature
205
+ - features/move-in-rally.feature
167
206
  - features/project-selection.feature
168
207
  - features/pull-from-rally-into-cucumber.feature
169
208
  - features/show-from-rally.feature
@@ -173,16 +212,6 @@ files:
173
212
  - features/update-story-in-rally.feature
174
213
  - lib/crab.rb
175
214
  - lib/crab/cli.rb
176
- - lib/crab/commands/create.rb
177
- - lib/crab/commands/delete.rb
178
- - lib/crab/commands/find.rb
179
- - lib/crab/commands/login.rb
180
- - lib/crab/commands/move.rb
181
- - lib/crab/commands/project.rb
182
- - lib/crab/commands/pull.rb
183
- - lib/crab/commands/show.rb
184
- - lib/crab/commands/testcase.rb
185
- - lib/crab/commands/update.rb
186
215
  - lib/crab/cucumber_feature.rb
187
216
  - lib/crab/cucumber_scenario.rb
188
217
  - lib/crab/rally.rb