crab 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Rakefile +9 -0
- data/bin/crab +5 -0
- data/crab.gemspec +33 -0
- data/features/find-text-in-stories.feature +31 -0
- data/features/list-from-rally.feature +27 -0
- data/features/login-and-out-of-rally.feature +14 -0
- data/features/project-selection.feature +27 -0
- data/features/pull-from-rally-into-cucumber.feature +28 -0
- data/features/show-from-rally.feature +25 -0
- data/features/steps/rally_steps.rb +94 -0
- data/features/subcommand-help.feature +84 -0
- data/features/support/aruba.rb +14 -0
- data/features/update-story-in-rally.feature +33 -0
- data/lib/crab.rb +19 -0
- data/lib/crab/cli.rb +112 -0
- data/lib/crab/cucumber_feature.rb +17 -0
- data/lib/crab/cucumber_scenario.rb +11 -0
- data/lib/crab/find.rb +30 -0
- data/lib/crab/list.rb +29 -0
- data/lib/crab/login.rb +25 -0
- data/lib/crab/project.rb +39 -0
- data/lib/crab/pull.rb +32 -0
- data/lib/crab/rally.rb +50 -0
- data/lib/crab/scenario.rb +23 -0
- data/lib/crab/show.rb +17 -0
- data/lib/crab/story.rb +63 -0
- data/lib/crab/update.rb +68 -0
- data/lib/crab/utilities.rb +18 -0
- data/lib/crab/version.rb +3 -0
- data/old/.gitignore +1 -0
- data/old/Gemfile +14 -0
- data/old/Rakefile +277 -0
- data/old/templates/feature-pt.mustache +5 -0
- data/old/templates/feature.mustache +4 -0
- metadata +230 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create ree@rally-cucumber-bridge
|
data/Gemfile
ADDED
data/Rakefile
ADDED
data/bin/crab
ADDED
data/crab.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "crab/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "crab"
|
7
|
+
s.version = Crab::VERSION
|
8
|
+
s.authors = ["Carlos Villela"]
|
9
|
+
s.email = ["cvillela@thoughtworks.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Cucumber-Rally Bridge}
|
12
|
+
s.description = %q{CRaB is a bridge between Cucumber and Rally}
|
13
|
+
|
14
|
+
s.rubyforge_project = "crab"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.executables = 'crab'
|
22
|
+
|
23
|
+
s.add_development_dependency 'aruba'
|
24
|
+
|
25
|
+
s.add_dependency 'aruba'
|
26
|
+
s.add_dependency 'cucumber'
|
27
|
+
s.add_dependency 'rally_rest_api'
|
28
|
+
s.add_dependency 'highline'
|
29
|
+
s.add_dependency 'activesupport'
|
30
|
+
s.add_dependency 'i18n'
|
31
|
+
s.add_dependency 'sanitize'
|
32
|
+
s.add_dependency 'trollop'
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: Find Text in Stories
|
2
|
+
|
3
|
+
In order to find the story ID
|
4
|
+
A lazy developer
|
5
|
+
Wants to search for arbitrary bits of text
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
And I have selected the project "VEJA SP - Migração para o Alexandria"
|
10
|
+
|
11
|
+
Scenario: Matching Name
|
12
|
+
When I run `crab find Sample Crab`
|
13
|
+
Then the output should contain:
|
14
|
+
"""
|
15
|
+
US4988: Sample Crab Story (grooming)
|
16
|
+
US4999: Sample Crab Parent Story (grooming)
|
17
|
+
US5000: Sample Crab Parent Story (grooming)
|
18
|
+
"""
|
19
|
+
|
20
|
+
@quick
|
21
|
+
Scenario: Project Must be Specified If Not Set
|
22
|
+
Given no project is selected
|
23
|
+
When I run `crab find pattern`
|
24
|
+
Then the output should contain "Error: argument --project must be specified."
|
25
|
+
|
26
|
+
Scenario: Project Must Exist
|
27
|
+
When I run `crab find --project "foo" pattern`
|
28
|
+
Then the output should contain:
|
29
|
+
"""
|
30
|
+
Error: Project "foo" not found.
|
31
|
+
"""
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: List Stories in Rally
|
2
|
+
|
3
|
+
In order to figure out which stories she needs to pull
|
4
|
+
A developer who doesn't want to open a browser or click on things
|
5
|
+
Wants to list stories in Rally
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
And I have selected the project "VEJA SP - Migração para o Alexandria"
|
10
|
+
|
11
|
+
@really-slow
|
12
|
+
Scenario: Basic Invocation
|
13
|
+
When I run `crab list`
|
14
|
+
Then the output should contain "US4988: Sample Crab Story (grooming)"
|
15
|
+
|
16
|
+
@quick
|
17
|
+
Scenario: Project Must be Specified When Not Selected
|
18
|
+
Given no project is selected
|
19
|
+
When I run `crab list`
|
20
|
+
Then the output should contain "Error: argument --project must be specified."
|
21
|
+
|
22
|
+
Scenario: Project Must Exist
|
23
|
+
When I run `crab list -p "foo"`
|
24
|
+
Then the output should contain:
|
25
|
+
"""
|
26
|
+
Error: Project "foo" not found.
|
27
|
+
"""
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Log In and Out of Rally
|
2
|
+
|
3
|
+
In order to avoid typing his credentials all the time
|
4
|
+
A lazy and security-conscious developer
|
5
|
+
Wants to log in and out of Rally in order to perform operations
|
6
|
+
|
7
|
+
Scenario: Logged Out, Logging In
|
8
|
+
Given I am logged out
|
9
|
+
When I run `crab login` interactively
|
10
|
+
And I type my username
|
11
|
+
And I type my password
|
12
|
+
Then the exit status should be 0
|
13
|
+
And the user's home directory should have a file named ".rally_credentials"
|
14
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: Project Selection
|
2
|
+
|
3
|
+
In order to work with the find, list etc commands more effectively
|
4
|
+
A lazy developer
|
5
|
+
Wants to set the project persistently across all commands
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
|
10
|
+
Scenario: Selecting a Project
|
11
|
+
Given no project is selected
|
12
|
+
|
13
|
+
When I run `crab project`
|
14
|
+
Then the output should contain "No project currently selected."
|
15
|
+
|
16
|
+
When I run `crab project "VEJA SP - Migração para o Alexandria"`
|
17
|
+
Then the exit status should be 0
|
18
|
+
|
19
|
+
When I run `crab project`
|
20
|
+
Then the output should contain "VEJA SP - Migração para o Alexandria"
|
21
|
+
|
22
|
+
Scenario: Selecting an Invalid Project
|
23
|
+
When I run `crab project "invalid"`
|
24
|
+
Then the output should contain:
|
25
|
+
"""
|
26
|
+
Error: "invalid" is not a valid project.
|
27
|
+
"""
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Pull From Rally Into Cucumber
|
2
|
+
|
3
|
+
In order to begin development of a story that was written in Rally
|
4
|
+
A developer who doesn't want to open a browser or click things
|
5
|
+
Wants the story converted into the much nicer Cucumber format
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
|
10
|
+
Scenario: Pulling a Single Story
|
11
|
+
Given a directory named "crab-pull"
|
12
|
+
And I cd to "crab-pull"
|
13
|
+
When I run `crab pull US4988`
|
14
|
+
Then the output should contain "US4988: features/grooming/US4988-sample-crab-story.feature"
|
15
|
+
And a directory named "features" should exist
|
16
|
+
And a file named "features/grooming/US4988-sample-crab-story.feature" should exist
|
17
|
+
And the file "features/grooming/US4988-sample-crab-story.feature" should contain exactly:
|
18
|
+
"""
|
19
|
+
Feature: [US4988] Sample Crab Story
|
20
|
+
|
21
|
+
Sample Description
|
22
|
+
"""
|
23
|
+
|
24
|
+
Scenario: Pulling Multiple Stories
|
25
|
+
When I run `crab pull US4988 US5000`
|
26
|
+
Then the output should contain "US4988: features/grooming/US4988-sample-crab-story.feature"
|
27
|
+
Then the output should contain "US5000: features/grooming/US5000-sample-crab-parent-story.feature"
|
28
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Show Story From Rally
|
2
|
+
|
3
|
+
In order to see what's in a story
|
4
|
+
A lazy developer
|
5
|
+
Wants to be able to do it from the command line
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
|
10
|
+
Scenario: Show Simple Story
|
11
|
+
When I run `crab show US4988`
|
12
|
+
Then the output should contain:
|
13
|
+
"""
|
14
|
+
Feature: [US4988] Sample Crab Story
|
15
|
+
|
16
|
+
Sample Description
|
17
|
+
"""
|
18
|
+
|
19
|
+
Scenario: Show Story With Test Cases
|
20
|
+
When I run `crab show US5000`
|
21
|
+
Then the output should contain "Feature: [US5000] Sample Crab Parent Story"
|
22
|
+
And the output should contain "Scenario: [TC10388] Sample Testcase"
|
23
|
+
And the output should contain " Given Rally behaves"
|
24
|
+
And the output should contain " When I look at the test case steps"
|
25
|
+
And the output should contain " Then I should be able to export them into Cucumber format"
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rally_rest_api'
|
2
|
+
|
3
|
+
Given /^I am logged out$/ do
|
4
|
+
end
|
5
|
+
|
6
|
+
Given /^an instance of Rally$/ do
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^Rally has a story with ID "([^"]*)"$/ do |arg1|
|
10
|
+
end
|
11
|
+
|
12
|
+
Then /^the user's home directory should have a file named "([^"]*)"$/ do |file|
|
13
|
+
File.exists? File.expand_path("~/#{file}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_rally_credentials
|
17
|
+
username, password = File.read(File.join(File.dirname(__FILE__), '..', '..', '.rally_credentials')).split(/\n/)
|
18
|
+
[ username, password ]
|
19
|
+
end
|
20
|
+
|
21
|
+
When /^I type my username$/ do
|
22
|
+
When %Q{I type "#{get_rally_credentials.first}"}
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^I type my password$/ do
|
26
|
+
When %Q{I type "#{get_rally_credentials.last}"}
|
27
|
+
end
|
28
|
+
|
29
|
+
Given /^I am logged in$/ do
|
30
|
+
username, password = get_rally_credentials
|
31
|
+
steps %Q{
|
32
|
+
Given I am logged out
|
33
|
+
When I run `crab login -u #{username} -p #{password}`
|
34
|
+
Then the output should contain "Logged in as #{username}"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
Then /^a file named "([^"]*)" in the user's home directory should exist$/ do |arg1|
|
39
|
+
pending # express the regexp above with the code you wish you had
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_rally
|
43
|
+
username, password = get_rally_credentials
|
44
|
+
@rally = RallyRestAPI.new :username => username, :password => password
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_story(story_id)
|
48
|
+
get_rally.find(:hierarchical_requirement, :fetch => true) { equal :formatted_i_d, story_id }.first
|
49
|
+
end
|
50
|
+
|
51
|
+
Then /^the story ([A-Z]{2}\d+) should be blocked$/ do |story_id|
|
52
|
+
story = get_story(story_id)
|
53
|
+
story.blocked.should == "true"
|
54
|
+
end
|
55
|
+
|
56
|
+
Then /^the story ([A-Z]{2}\d+) should be unblocked$/ do |story_id|
|
57
|
+
story = get_story(story_id)
|
58
|
+
story.blocked.should == "false"
|
59
|
+
end
|
60
|
+
|
61
|
+
Then /^the story ([A-Z]{2}\d+) should be in iteration "([^"]*)"$/ do |story_id, iteration_name|
|
62
|
+
story = get_story story_id
|
63
|
+
story.iteration.name.should == iteration_name
|
64
|
+
end
|
65
|
+
|
66
|
+
Then /^the story ([A-Z]{2}\d+) should be in release "([^"]*)"$/ do |story_id, release_name|
|
67
|
+
story = get_story story_id
|
68
|
+
story.release.name.should == release_name
|
69
|
+
end
|
70
|
+
|
71
|
+
Then /^the story ([A-Z]{2}\d+) should have ([A-Z]{2}\d+) as its parent$/ do |child, parent|
|
72
|
+
story = get_story child
|
73
|
+
story.parent.should_not be_nil
|
74
|
+
story.parent.formatted_i_d.should == parent
|
75
|
+
end
|
76
|
+
|
77
|
+
Given /^no project is selected$/ do
|
78
|
+
Given 'I run `rm -rf ".rally_project"`'
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_project
|
82
|
+
if File.exists? ".rally_project"
|
83
|
+
File.read(".rally_project").strip
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
Given /^I have selected the project "([^"]*)"$/ do |project|
|
88
|
+
unless get_project == project
|
89
|
+
steps %Q{
|
90
|
+
When I run `crab project #{project}`
|
91
|
+
Then the exit status should be 0
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
@quick
|
2
|
+
Feature: Subcommand Help
|
3
|
+
|
4
|
+
In order to learn how to use crab
|
5
|
+
A newbie developer
|
6
|
+
Wants to see a useful help message when she runs crab with the wrong arguments
|
7
|
+
|
8
|
+
Scenario: No Arguments
|
9
|
+
When I run `crab`
|
10
|
+
Then the output should contain "Error: Unknown subcommand."
|
11
|
+
|
12
|
+
Scenario: Help
|
13
|
+
When I run `crab -h`
|
14
|
+
Then the output should contain " login Persistently authenticate user with Rally"
|
15
|
+
And the output should contain " list Lists stories"
|
16
|
+
And the output should contain " update Update a story (name, estimate, etc)"
|
17
|
+
And the output should contain " show Show a story (and its test cases) as a Cucumber feature"
|
18
|
+
And the output should contain " pull Downloads stories (and its test cases) as Cucumber feature files"
|
19
|
+
|
20
|
+
Scenario: Bogus Subcommand
|
21
|
+
When I run `crab bogus`
|
22
|
+
Then the output should contain:
|
23
|
+
"""
|
24
|
+
Error: Unknown subcommand "bogus".
|
25
|
+
"""
|
26
|
+
|
27
|
+
Scenario: Pull Subcommand
|
28
|
+
When I run `crab pull --help`
|
29
|
+
Then the output should contain:
|
30
|
+
"""
|
31
|
+
crab pull: pulls stories from Rally and writes them out as Cucumber features
|
32
|
+
|
33
|
+
Usage: crab [options] pull story1 [story2 ...]
|
34
|
+
"""
|
35
|
+
|
36
|
+
Scenario: Show Subcommand
|
37
|
+
When I run `crab show --help`
|
38
|
+
Then the output should contain:
|
39
|
+
"""
|
40
|
+
crab show: displays a story in Rally as a Cucumber feature
|
41
|
+
|
42
|
+
Usage: crab [options] show story
|
43
|
+
"""
|
44
|
+
|
45
|
+
Scenario: List Subcommand
|
46
|
+
When I run `crab list --help`
|
47
|
+
Then the output should contain:
|
48
|
+
"""
|
49
|
+
crab list: lists stories in Rally
|
50
|
+
|
51
|
+
Usage: crab [options] list
|
52
|
+
"""
|
53
|
+
|
54
|
+
Scenario: Update Subcommand
|
55
|
+
When I run `crab update --help`
|
56
|
+
Then the output should contain:
|
57
|
+
"""
|
58
|
+
crab update: update a story in Rally
|
59
|
+
|
60
|
+
Usage: crab [options] update story [options]
|
61
|
+
"""
|
62
|
+
|
63
|
+
Scenario: Update Needs a Story Number
|
64
|
+
When I run `crab update`
|
65
|
+
Then the output should contain "Error: No story given."
|
66
|
+
|
67
|
+
Scenario: Update Needs At Least One Switch
|
68
|
+
When I run `crab update US4988`
|
69
|
+
Then the output should contain "Error: Nothing to update. Please provide some options."
|
70
|
+
|
71
|
+
Scenario: Find Subcommand
|
72
|
+
When I run `crab find --help`
|
73
|
+
Then the output should contain:
|
74
|
+
"""
|
75
|
+
crab find: find a story in Rally
|
76
|
+
|
77
|
+
Usage: crab [options] find [options] text
|
78
|
+
"""
|
79
|
+
|
80
|
+
Scenario: Find Needs Text
|
81
|
+
When I run `crab find`
|
82
|
+
Then the output should contain "Error: No search pattern given."
|
83
|
+
|
84
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Feature: Update Story in Rally
|
2
|
+
|
3
|
+
In order to change a story's fields in Rally
|
4
|
+
A developer who doesn't want to open a browser or click on things
|
5
|
+
Wants to update those fields from the command line
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I am logged in
|
9
|
+
|
10
|
+
Scenario: Update Name
|
11
|
+
When I run `crab update US4988 --name "Sample Crab Story"`
|
12
|
+
Then the output should contain "US4988: Sample Crab Story (grooming)"
|
13
|
+
|
14
|
+
Scenario: Block and Unblock
|
15
|
+
When I run `crab update US4988 --blocked`
|
16
|
+
Then the output should contain "US4988: Sample Crab Story (grooming)"
|
17
|
+
And the story US4988 should be blocked
|
18
|
+
|
19
|
+
When I run `crab update US4988 --unblocked`
|
20
|
+
Then the output should contain "US4988: Sample Crab Story (grooming)"
|
21
|
+
And the story US4988 should be unblocked
|
22
|
+
|
23
|
+
Scenario: Setting Iteration
|
24
|
+
When I run `crab update US4988 --iteration "Iteration 0"`
|
25
|
+
Then the story US4988 should be in iteration "Iteration 0"
|
26
|
+
|
27
|
+
Scenario: Setting Release
|
28
|
+
When I run `crab update US4988 --release "Beta release"`
|
29
|
+
Then the story US4988 should be in release "Beta release"
|
30
|
+
|
31
|
+
Scenario: Setting Parent
|
32
|
+
When I run `crab update US4988 --parent US5000`
|
33
|
+
Then the story US4988 should have US5000 as its parent
|