crab 0.1.7 → 0.1.8

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.
@@ -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