crab 0.1.6 → 0.1.7
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.
- data/README.md +21 -10
- data/features/show-from-rally.feature +3 -3
- data/features/subcommand-help.feature +19 -9
- data/lib/crab.rb +9 -9
- data/lib/crab/cli.rb +14 -11
- data/lib/crab/commands/move.rb +46 -0
- data/lib/crab/commands/testcase.rb +1 -1
- data/lib/crab/commands/update.rb +2 -5
- data/lib/crab/cucumber_scenario.rb +1 -2
- data/lib/crab/rally.rb +1 -1
- data/lib/crab/story.rb +1 -1
- data/lib/crab/testcase.rb +4 -0
- data/lib/crab/utilities.rb +8 -0
- data/lib/crab/version.rb +1 -1
- metadata +5 -5
- data/lib/crab/scenario.rb +0 -30
data/README.md
CHANGED
@@ -139,25 +139,36 @@ If you have any problems, please let us know.
|
|
139
139
|
[4]: http://gembundler.com
|
140
140
|
[5]: https://github.com/cucumber/aruba
|
141
141
|
|
142
|
-
To do
|
143
|
-
|
142
|
+
To do / Roadmap
|
143
|
+
---------------
|
144
144
|
|
145
|
-
|
146
|
-
|
145
|
+
### 0.2.0
|
146
|
+
|
147
|
+
- Add a `move` subcommand which moves the story from one state to the next (potentially, `move --back`)
|
147
148
|
- `pull` is not very smart and could detect feature files being moved from one dir to another
|
148
149
|
- Recursively look for a `.crab` directory like Git does with `.git`
|
149
|
-
- Encrypt password in generated `~/.crab/credentials`
|
150
150
|
- Verbose logging (especially before any change or destructive operations in Rally)
|
151
|
-
- Dry-run mode
|
152
151
|
- Figure out how to stub or simulate Rally (tests are taking way too long already)
|
152
|
+
|
153
|
+
### 0.3.0
|
154
|
+
|
155
|
+
- Add a `push` subcommand which parses a Cucumber feature and adds or updates it in Rally
|
156
|
+
- Add a config command + .crab/config file to hold settings like project, etc
|
153
157
|
- Error messages are still more cryptic than we'd like
|
154
|
-
- Add a `move` subcommand which moves the story from one state to the next (potentially, `move --back`)
|
155
|
-
- Add a Cucumber Formatter that updates Test Runs in Rally with results from CI
|
156
|
-
- Investigate use of other fields like Priority and Risk in Rally Test Cases
|
157
158
|
- Make it possible to associate defects with Features (essentially treating defects like stories)
|
158
|
-
- Test in Ruby 1.9
|
159
159
|
- Use the Gherkin models and formatters instead of dumb string templates to generate feature files
|
160
160
|
|
161
|
+
### Later / before 1.0.0
|
162
|
+
|
163
|
+
- Dry-run mode
|
164
|
+
- Encrypt password in generated `~/.crab/credentials`
|
165
|
+
- Add a Cucumber Formatter that updates Test Runs in Rally with results from CI
|
166
|
+
- Test in Ruby 1.9
|
167
|
+
|
168
|
+
### After 1.0.0
|
169
|
+
|
170
|
+
- Bash completion scripts
|
171
|
+
|
161
172
|
Suggestions? Please get in touch!
|
162
173
|
|
163
174
|
Authors and Contributors
|
@@ -1,10 +1,10 @@
|
|
1
1
|
Feature: Show Story From Rally
|
2
|
-
|
2
|
+
|
3
3
|
In order to see what's in a story
|
4
4
|
A lazy developer
|
5
5
|
Wants to be able to do it from the command line
|
6
6
|
|
7
|
-
Background:
|
7
|
+
Background:
|
8
8
|
Given I am logged in
|
9
9
|
|
10
10
|
Scenario: Show Simple Story
|
@@ -19,7 +19,7 @@ Feature: Show Story From Rally
|
|
19
19
|
Scenario: Show Story With Test Cases
|
20
20
|
When I run `crab show US5000`
|
21
21
|
Then the output should contain "Feature: [US5000] Sample Crab Parent Story"
|
22
|
-
And the output should contain "@manual @
|
22
|
+
And the output should contain "@important @medium @manual @acceptance"
|
23
23
|
And the output should contain "Scenario: [TC10388] Sample Testcase"
|
24
24
|
And the output should contain " Given Rally behaves"
|
25
25
|
And the output should contain " When I look at the test case steps"
|
@@ -11,15 +11,16 @@ Feature: Subcommand Help
|
|
11
11
|
|
12
12
|
Scenario: Help
|
13
13
|
When I run `crab -h`
|
14
|
-
Then the output should contain "
|
15
|
-
|
16
|
-
And the output should contain "
|
17
|
-
And the output should contain "
|
18
|
-
And the output should contain "
|
19
|
-
And the output should contain "
|
20
|
-
And the output should contain "
|
21
|
-
And the output should contain "
|
22
|
-
And the output should contain "
|
14
|
+
Then the output should contain "create Create a new story in Rally"
|
15
|
+
And the output should contain "delete Delete an existing story in Rally"
|
16
|
+
And the output should contain "find Find stories by text in name, description or notes"
|
17
|
+
And the output should contain "login Persistently authenticate user with Rally"
|
18
|
+
And the output should contain "move Move a story from one status to the next (or previous)"
|
19
|
+
And the output should contain "project Persistently select project to work with in Rally"
|
20
|
+
And the output should contain "pull Downloads stories (and its test cases) as Cucumber feature files"
|
21
|
+
And the output should contain "show Show a story (and its test cases) as a Cucumber feature"
|
22
|
+
And the output should contain "testcase Manage test cases in a story (add, update, delete)"
|
23
|
+
And the output should contain "update Update a story (name, estimate, etc)"
|
23
24
|
|
24
25
|
Scenario: Bogus Subcommand
|
25
26
|
When I run `crab bogus`
|
@@ -97,3 +98,12 @@ Feature: Subcommand Help
|
|
97
98
|
Usage: crab [options] find [options] [text]
|
98
99
|
"""
|
99
100
|
|
101
|
+
Scenario: Move Subcommand
|
102
|
+
When I run `crab move --help`
|
103
|
+
Then the output should contain:
|
104
|
+
"""
|
105
|
+
crab move: move a story from one status to the next (or previous)
|
106
|
+
|
107
|
+
Usage: crab [options] move story [options]
|
108
|
+
"""
|
109
|
+
|
data/lib/crab.rb
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
require "crab/version"
|
2
2
|
|
3
3
|
# common dependencies
|
4
|
-
require '
|
4
|
+
require 'active_support/all'
|
5
5
|
require 'fileutils'
|
6
6
|
require 'gherkin/i18n'
|
7
7
|
require 'highline/import'
|
8
|
-
require 'active_support/all'
|
9
8
|
require 'rally_rest_api'
|
10
9
|
require 'sanitize'
|
10
|
+
require 'trollop'
|
11
11
|
|
12
12
|
# internals
|
13
13
|
require "crab/utilities"
|
14
|
+
require "crab/cli"
|
14
15
|
require "crab/rally"
|
15
16
|
require "crab/story"
|
16
17
|
require "crab/testcase"
|
17
|
-
require "crab/cli"
|
18
|
-
require "crab/scenario"
|
19
18
|
|
20
19
|
# supported commands
|
21
|
-
require "crab/commands/
|
22
|
-
require "crab/commands/
|
20
|
+
require "crab/commands/create"
|
21
|
+
require "crab/commands/delete"
|
23
22
|
require "crab/commands/find"
|
24
23
|
require "crab/commands/login"
|
25
|
-
require "crab/commands/
|
24
|
+
require "crab/commands/move"
|
26
25
|
require "crab/commands/project"
|
27
|
-
require "crab/commands/
|
28
|
-
require "crab/commands/
|
26
|
+
require "crab/commands/pull"
|
27
|
+
require "crab/commands/show"
|
29
28
|
require "crab/commands/testcase"
|
29
|
+
require "crab/commands/update"
|
30
30
|
|
31
31
|
# cucumber support
|
32
32
|
require "crab/cucumber_feature"
|
data/lib/crab/cli.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module Crab
|
2
2
|
|
3
|
-
SUB_COMMANDS =
|
3
|
+
SUB_COMMANDS = {
|
4
|
+
"create" => "Create a new story in Rally",
|
5
|
+
"delete" => "Delete an existing story in Rally",
|
6
|
+
"find" => "Find stories by text in name, description or notes",
|
7
|
+
"login" => "Persistently authenticate user with Rally",
|
8
|
+
"project" => "Persistently select project to work with in Rally",
|
9
|
+
"pull" => "Downloads stories (and its test cases) as Cucumber feature files",
|
10
|
+
"show" => "Show a story (and its test cases) as a Cucumber feature",
|
11
|
+
"testcase" => "Manage test cases in a story (add, update, delete)",
|
12
|
+
"update" => "Update a story (name, estimate, etc)",
|
13
|
+
"move" => "Move a story from one status to the next (or previous)",
|
14
|
+
}
|
4
15
|
|
5
16
|
class CLI
|
6
17
|
def self.start
|
@@ -9,17 +20,9 @@ module Crab
|
|
9
20
|
banner """
|
10
21
|
crab version #{Crab::VERSION}: A Cucumber-Rally bridge
|
11
22
|
|
12
|
-
|
13
|
-
delete Delete an existing story in Rally
|
14
|
-
find Find stories by text in name, description or notes
|
15
|
-
login Persistently authenticate user with Rally
|
16
|
-
project Persistently select project to work with in Rally
|
17
|
-
pull Downloads stories (and its test cases) as Cucumber feature files
|
18
|
-
show Show a story (and its test cases) as a Cucumber feature
|
19
|
-
testcase Manage test cases in a story (add, update, delete)
|
20
|
-
update Update a story (name, estimate, etc)
|
23
|
+
#{SUB_COMMANDS.keys.sort.map {|k| sprintf "%10s %s\n", k, SUB_COMMANDS[k] }.join}
|
21
24
|
"""
|
22
|
-
stop_on SUB_COMMANDS
|
25
|
+
stop_on SUB_COMMANDS.keys
|
23
26
|
end
|
24
27
|
|
25
28
|
cmd = ARGV.shift # get the subcommand
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Crab::Commands
|
2
|
+
|
3
|
+
class Move
|
4
|
+
|
5
|
+
include Crab::Utilities
|
6
|
+
|
7
|
+
def initialize(global_opts, args)
|
8
|
+
@global_opts = global_opts
|
9
|
+
@args = args
|
10
|
+
|
11
|
+
@cmd_opts = Trollop::options do
|
12
|
+
banner "crab move: move a story from one status to the next (or previous)
|
13
|
+
|
14
|
+
Usage: crab [options] move story [options]"
|
15
|
+
opt :back, "Move story backwards (from accepted to completed, for example)"
|
16
|
+
end
|
17
|
+
|
18
|
+
@rally = Crab::Rally.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
story_id = @args.join(" ")
|
23
|
+
Trollop::die "No story given" if story_id.empty?
|
24
|
+
|
25
|
+
@rally.connect
|
26
|
+
|
27
|
+
story = @rally.find_story_with_id story_id
|
28
|
+
state = state_from(story.state)
|
29
|
+
|
30
|
+
story.update :schedule_state => (@cmd_opts[:back] ? state_before(state) : state_after(state))
|
31
|
+
|
32
|
+
puts "#{story.formatted_id}: #{story.name} (#{story.state})"
|
33
|
+
end
|
34
|
+
|
35
|
+
def state_before(state)
|
36
|
+
i = (Crab::Story::VALID_STATES.index(state) || 0) - 1
|
37
|
+
Crab::Story::VALID_STATES[i < 0 ? 0 : i]
|
38
|
+
end
|
39
|
+
|
40
|
+
def state_after(state)
|
41
|
+
i = (Crab::Story::VALID_STATES.index(state) || 0) + 1
|
42
|
+
max = Crab::Story::VALID_STATES.size
|
43
|
+
Crab::Story::VALID_STATES[i >= max ? max -1 : i]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -76,7 +76,7 @@ Usage: crab [options] testcase add story name [options]
|
|
76
76
|
@rally.connect
|
77
77
|
tc = @rally.find_test_case(tc_id)
|
78
78
|
tc.update(sanitize_options(opts))
|
79
|
-
puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")}"
|
79
|
+
puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
|
80
80
|
end
|
81
81
|
|
82
82
|
def delete(tc_id)
|
data/lib/crab/commands/update.rb
CHANGED
@@ -2,6 +2,8 @@ module Crab::Commands
|
|
2
2
|
|
3
3
|
class Update
|
4
4
|
|
5
|
+
include Crab::Utilities
|
6
|
+
|
5
7
|
def initialize(global_opts, args)
|
6
8
|
@global_opts = global_opts
|
7
9
|
@args = args
|
@@ -74,10 +76,5 @@ Usage: crab [options] update story [options]"
|
|
74
76
|
opts
|
75
77
|
end
|
76
78
|
|
77
|
-
def state_from(option)
|
78
|
-
fixed_option = option.gsub(/(^\w|[-_]\w)/) { $1.upcase.gsub(/_/, '-') }
|
79
|
-
Trollop::die :state, "has an invalid value" unless Crab::Story::VALID_STATES.include? fixed_option
|
80
|
-
fixed_option
|
81
|
-
end
|
82
79
|
end
|
83
80
|
end
|
@@ -6,10 +6,9 @@ module Crab
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def generate_from(scenario)
|
9
|
-
tags = [scenario.method, scenario.test_type]
|
10
9
|
return <<-SCENARIO
|
11
10
|
|
12
|
-
#{tags.map {|
|
11
|
+
#{scenario.tags.map {|tag| "@" + tag }.join(" ")}
|
13
12
|
#{@language.keywords('scenario').last}: [#{scenario.formatted_id}] #{scenario.name}
|
14
13
|
#{scenario.steps.join("\n ")}
|
15
14
|
SCENARIO
|
data/lib/crab/rally.rb
CHANGED
data/lib/crab/story.rb
CHANGED
data/lib/crab/testcase.rb
CHANGED
data/lib/crab/utilities.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Crab
|
2
2
|
module Utilities
|
3
|
+
|
3
4
|
def credentials_file
|
4
5
|
FileUtils.mkdir_p File.expand_path("~/.crab")
|
5
6
|
File.expand_path("~/.crab/credentials")
|
@@ -15,5 +16,12 @@ module Crab
|
|
15
16
|
Trollop::die :project, "must be specified" if project_name.blank?
|
16
17
|
project_name
|
17
18
|
end
|
19
|
+
|
20
|
+
def state_from(option)
|
21
|
+
fixed_option = option.gsub(/(^\w|[-_]\w)/) { $1.upcase.gsub(/_/, '-') }
|
22
|
+
Trollop::die :state, "has an invalid value" unless Crab::Story::VALID_STATES.include? fixed_option
|
23
|
+
fixed_option
|
24
|
+
end
|
25
|
+
|
18
26
|
end
|
19
27
|
end
|
data/lib/crab/version.rb
CHANGED
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:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 7
|
10
|
+
version: 0.1.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Carlos Villela
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-28 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- lib/crab/commands/delete.rb
|
178
178
|
- lib/crab/commands/find.rb
|
179
179
|
- lib/crab/commands/login.rb
|
180
|
+
- lib/crab/commands/move.rb
|
180
181
|
- lib/crab/commands/project.rb
|
181
182
|
- lib/crab/commands/pull.rb
|
182
183
|
- lib/crab/commands/show.rb
|
@@ -185,7 +186,6 @@ files:
|
|
185
186
|
- lib/crab/cucumber_feature.rb
|
186
187
|
- lib/crab/cucumber_scenario.rb
|
187
188
|
- lib/crab/rally.rb
|
188
|
-
- lib/crab/scenario.rb
|
189
189
|
- lib/crab/story.rb
|
190
190
|
- lib/crab/testcase.rb
|
191
191
|
- lib/crab/utilities.rb
|
data/lib/crab/scenario.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Crab
|
2
|
-
|
3
|
-
class Scenario
|
4
|
-
|
5
|
-
def initialize(rally_test_case)
|
6
|
-
@rally_test_case = rally_test_case
|
7
|
-
end
|
8
|
-
|
9
|
-
def formatted_id
|
10
|
-
@rally_test_case.formatted_i_d
|
11
|
-
end
|
12
|
-
|
13
|
-
def name
|
14
|
-
@rally_test_case.name
|
15
|
-
end
|
16
|
-
|
17
|
-
def steps
|
18
|
-
Array(@rally_test_case.steps).map {|step| step.input }
|
19
|
-
end
|
20
|
-
|
21
|
-
def method
|
22
|
-
@rally_test_case.elements[:method].parameterize
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_type
|
26
|
-
@rally_test_case.elements[:type].parameterize
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|