tddium-preview 0.9.3 → 0.9.4
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/.gitignore +1 -2
- data/Gemfile.lock +4 -4
- data/features/account_command.feature +11 -0
- data/features/heroku_command.feature +6 -0
- data/features/password_command.feature +46 -0
- data/features/spec_command.feature +15 -0
- data/features/status_command.feature +15 -0
- data/features/step_definitions/git_steps.rb +31 -0
- data/features/step_definitions/login_steps.rb +1 -2
- data/features/step_definitions/password_steps.rb +12 -0
- data/features/step_definitions/suite_steps.rb +4 -26
- data/features/step_definitions/upgrade_steps.rb +4 -0
- data/features/upgrade_required.feature +12 -0
- data/lib/tddium/commands/account.rb +51 -0
- data/lib/tddium/commands/activate.rb +58 -0
- data/lib/tddium/commands/heroku.rb +38 -0
- data/lib/tddium/commands/login.rb +20 -0
- data/lib/tddium/commands/logout.rb +15 -0
- data/lib/tddium/commands/password.rb +32 -0
- data/lib/tddium/commands/spec.rb +127 -0
- data/lib/tddium/commands/status.rb +56 -0
- data/lib/tddium/commands/suite.rb +62 -0
- data/lib/tddium/constant.rb +18 -15
- data/lib/tddium/version.rb +1 -1
- data/lib/tddium.rb +35 -428
- data/tddium.gemspec +1 -1
- metadata +41 -24
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tddium-preview (0.9.
|
4
|
+
tddium-preview (0.9.4)
|
5
5
|
bundler
|
6
6
|
highline
|
7
7
|
json
|
8
|
-
tddium_client (
|
8
|
+
tddium_client (~> 0.1.0)
|
9
9
|
tddium_reporting (>= 0.0.5)
|
10
10
|
thor
|
11
11
|
|
@@ -74,10 +74,10 @@ GEM
|
|
74
74
|
sinatra (1.2.6)
|
75
75
|
rack (~> 1.1)
|
76
76
|
tilt (< 2.0, >= 1.2.2)
|
77
|
-
tddium_client (0.0
|
77
|
+
tddium_client (0.1.0)
|
78
78
|
httparty
|
79
79
|
json
|
80
|
-
tddium_reporting (0.0.
|
80
|
+
tddium_reporting (0.0.6)
|
81
81
|
term-ansicolor (1.0.6)
|
82
82
|
thor (0.14.6)
|
83
83
|
tilt (1.3.3)
|
@@ -24,6 +24,17 @@ Feature: Account command
|
|
24
24
|
[member] member@example.com
|
25
25
|
[admin] admin@example.com
|
26
26
|
"""
|
27
|
+
And the output should contain "alpha/master"
|
28
|
+
|
29
|
+
Scenario: Handle API failure
|
30
|
+
Given the user is logged in
|
31
|
+
And there is a problem retrieving suite information
|
32
|
+
When I run `tddium account`
|
33
|
+
Then the output should contain "someone@example.com"
|
34
|
+
And the output should contain:
|
35
|
+
"""
|
36
|
+
API Error
|
37
|
+
"""
|
27
38
|
|
28
39
|
Scenario: Fail if user isn't logged in
|
29
40
|
When I run `tddium account`
|
@@ -0,0 +1,46 @@
|
|
1
|
+
@mimic
|
2
|
+
Feature: Password command
|
3
|
+
As a Tddium user
|
4
|
+
I want to change my password
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given the command is "tddium password"
|
8
|
+
|
9
|
+
Scenario: Fail if user isn't logged in
|
10
|
+
When I run `tddium password`
|
11
|
+
Then the exit status should not be 0
|
12
|
+
And the output should contain "tddium login"
|
13
|
+
And the output should contain "tddium heroku"
|
14
|
+
|
15
|
+
Scenario: Successfully change password interactively
|
16
|
+
Given the user is logged in
|
17
|
+
And the password change succeeds
|
18
|
+
When I run `tddium password` interactively
|
19
|
+
And I respond to "old password" with "foobar"
|
20
|
+
And I respond to "new password" with "foobar3"
|
21
|
+
And I respond to "new password" with "foobar3"
|
22
|
+
Then the output from "tddium password" should contain "Your password has been changed"
|
23
|
+
When the console session ends
|
24
|
+
Then the exit status should be 0
|
25
|
+
|
26
|
+
Scenario: Old password incorrect
|
27
|
+
Given the user is logged in
|
28
|
+
And the old password is invalid
|
29
|
+
When I run `tddium password` interactively
|
30
|
+
And I respond to "old password" with "foobar"
|
31
|
+
And I respond to "new password" with "foobar3"
|
32
|
+
And I respond to "new password" with "foobar3"
|
33
|
+
Then the output from "tddium password" should contain "Current password is invalid"
|
34
|
+
When the console session ends
|
35
|
+
Then the exit status should not be 0
|
36
|
+
|
37
|
+
Scenario: Confirmation mismatch
|
38
|
+
Given the user is logged in
|
39
|
+
And the confirmation doesn't match
|
40
|
+
When I run `tddium password` interactively
|
41
|
+
And I respond to "old password" with "foobar"
|
42
|
+
And I respond to "new password" with "foobar3"
|
43
|
+
And I respond to "new password" with "foobar2"
|
44
|
+
Then the output from "tddium password" should contain "Password doesn't match confirmation"
|
45
|
+
When the console session ends
|
46
|
+
Then the exit status should not be 0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
@mimic
|
2
|
+
Feature: spec command
|
3
|
+
As a tddium user
|
4
|
+
In order to run tests
|
5
|
+
I want to start a test session
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given the command is "tddium spec"
|
9
|
+
|
10
|
+
Scenario: Fail if user isn't logged in
|
11
|
+
Given a git repo is initialized
|
12
|
+
When I run `tddium spec`
|
13
|
+
Then the exit status should not be 0
|
14
|
+
And the output should contain "tddium login"
|
15
|
+
And the output should contain "tddium heroku"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
@mimic
|
2
|
+
Feature: "tddium status" command
|
3
|
+
As a Tddium user
|
4
|
+
In order to view my recent sessions
|
5
|
+
I want a simple status display
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given the command is "tddium status"
|
9
|
+
|
10
|
+
Scenario: Fail if user isn't logged in
|
11
|
+
Given a git repo is initialized
|
12
|
+
When I run `tddium status`
|
13
|
+
Then the exit status should not be 0
|
14
|
+
And the output should contain "tddium login"
|
15
|
+
And the output should contain "tddium heroku"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
Given /^the destination repo exists$/ do
|
3
|
+
steps %Q{
|
4
|
+
Given a directory named "repo"
|
5
|
+
And I cd to "repo"
|
6
|
+
And I successfully run `git init --bare .`
|
7
|
+
And I cd to ".."
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
Given /^a git repo is initialized(?: on branch "([^"]*)")?$/ do |branch|
|
12
|
+
steps %Q{
|
13
|
+
Given a directory named "work"
|
14
|
+
And I cd to "work"
|
15
|
+
And I successfully run `git init .`
|
16
|
+
And a file named "testfile" with:
|
17
|
+
"""
|
18
|
+
some data
|
19
|
+
"""
|
20
|
+
And I successfully run `git config user.email "a@b.com"`
|
21
|
+
And I successfully run `git config user.name "A User"`
|
22
|
+
And I successfully run `git add .`
|
23
|
+
And I successfully run `git commit -am 'testfile'`
|
24
|
+
}
|
25
|
+
if branch && branch != 'master'
|
26
|
+
steps %Q{
|
27
|
+
And I successfully run `git checkout -b #{branch}`
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -23,7 +23,6 @@ end
|
|
23
23
|
Then /^dotfiles should be updated$/ do
|
24
24
|
steps %Q{
|
25
25
|
And the file ".tddium.mimic" should contain "apikey"
|
26
|
-
And the file ".gitignore" should contain ".tddium
|
27
|
-
And the file ".gitignore" should contain ".tddium-deploy-key.mimic"
|
26
|
+
And the file ".gitignore" should contain ".tddium*"
|
28
27
|
}
|
29
28
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Given /^the password change succeeds$/ do
|
2
|
+
Antilles.install(:put, "/1/users/1/", {:status=>0})
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^the old password is invalid$/ do
|
6
|
+
Antilles.install(:put, "/1/users/1/", {:status=>1, :explanation=>"Current password is invalid"})
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^the confirmation doesn't match$/ do
|
10
|
+
Antilles.install(:put, "/1/users/1/", {:status=>1, :explanation=>"Password doesn't match confirmation"})
|
11
|
+
end
|
12
|
+
|
@@ -16,34 +16,12 @@ Given /^the user has no suites/ do
|
|
16
16
|
Antilles.install(:get, "/1/suites", {:status=>0, :suites=>[]})
|
17
17
|
end
|
18
18
|
|
19
|
-
Given /^
|
20
|
-
Antilles.install(:
|
21
|
-
end
|
22
|
-
|
23
|
-
Given /^the destination repo exists$/ do
|
24
|
-
steps %Q{
|
25
|
-
Given a directory named "repo"
|
26
|
-
And I cd to "repo"
|
27
|
-
And I successfully run `git init --bare .`
|
28
|
-
And I cd to ".."
|
29
|
-
}
|
19
|
+
Given /^there is a problem retrieving suite information$/ do
|
20
|
+
Antilles.install(:get, "/1/suites", {:status=>1, :explanation=>"Some error"})
|
30
21
|
end
|
31
22
|
|
32
|
-
Given /^a
|
33
|
-
|
34
|
-
Given a directory named "work"
|
35
|
-
And I cd to "work"
|
36
|
-
And I successfully run `git init .`
|
37
|
-
And a file named "testfile" with:
|
38
|
-
"""
|
39
|
-
some data
|
40
|
-
"""
|
41
|
-
And I successfully run `git config user.email "a@b.com"`
|
42
|
-
And I successfully run `git config user.name "A User"`
|
43
|
-
And I successfully run `git add .`
|
44
|
-
And I successfully run `git commit -am 'testfile'`
|
45
|
-
And I successfully run `git checkout -b #{branch}`
|
46
|
-
}
|
23
|
+
Given /^the user can create a suite named "([^"]*)" on branch "([^"]*)"$/ do |name, branch|
|
24
|
+
Antilles.install(:post, "/1/suites", {:status=>0, :suite=>make_suite_response(name, branch)}, :code=>201)
|
47
25
|
end
|
48
26
|
|
49
27
|
Given /^I choose defaults for test pattern, CI and campfire settings$/ do
|
@@ -0,0 +1,12 @@
|
|
1
|
+
@mimic
|
2
|
+
Feature: Detect upgrade required
|
3
|
+
As a Tddium user
|
4
|
+
In order to notice when my gem is out of date
|
5
|
+
I want the tddium gem to be notified when it needs to be upgraded
|
6
|
+
|
7
|
+
Scenario: Exit if upgrade is required
|
8
|
+
Given the user is logged in
|
9
|
+
And my gem is out of date
|
10
|
+
When I run `tddium account`
|
11
|
+
Then the output should contain "API Error: tddium-preview-0.9.4 is out of date."
|
12
|
+
And the exit status should not be 0
|
@@ -0,0 +1,51 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
|
7
|
+
desc "account", "View account information"
|
8
|
+
def account
|
9
|
+
set_shell
|
10
|
+
set_default_environment
|
11
|
+
if user_details = user_logged_in?(true, true)
|
12
|
+
# User is already logged in, so just display the info
|
13
|
+
show_user_details(user_details)
|
14
|
+
else
|
15
|
+
exit_failure Text::Error::USE_ACTIVATE
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "account:add [ROLE] [EMAIL]", "Authorize and invite a user to use your account"
|
20
|
+
define_method "account:add" do |role, email|
|
21
|
+
set_shell
|
22
|
+
set_default_environment
|
23
|
+
user_details = user_logged_in?(true, true)
|
24
|
+
exit_failure unless user_details
|
25
|
+
|
26
|
+
params = {:role=>role, :email=>email}
|
27
|
+
begin
|
28
|
+
say Text::Process::ADDING_MEMBER % [params[:email], params[:role]]
|
29
|
+
result = call_api(:post, Api::Path::MEMBERSHIPS, params)
|
30
|
+
say Text::Process::ADDED_MEMBER % email
|
31
|
+
rescue TddiumClient::Error::API => e
|
32
|
+
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, e.message]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "account:remove [EMAIL]", "Remove a user from your account"
|
37
|
+
define_method "account:remove" do |email|
|
38
|
+
set_shell
|
39
|
+
set_default_environment
|
40
|
+
user_details = user_logged_in?(true, true)
|
41
|
+
exit_failure unless user_details
|
42
|
+
|
43
|
+
begin
|
44
|
+
say Text::Process::REMOVING_MEMBER % email
|
45
|
+
result = call_api(:delete, "#{Api::Path::MEMBERSHIPS}/#{email}")
|
46
|
+
say Text::Process::REMOVED_MEMBER % email
|
47
|
+
rescue TddiumClient::Error::API => e
|
48
|
+
exit_failure Text::Error::REMOVE_MEMBER_ERROR % [email, e.message]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "activate", "Activate an account with an invitation token"
|
7
|
+
method_option :email, :type => :string, :default => nil
|
8
|
+
method_option :password, :type => :string, :default => nil
|
9
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
10
|
+
def activate
|
11
|
+
set_shell
|
12
|
+
set_default_environment
|
13
|
+
if user_details = user_logged_in?
|
14
|
+
exit_failure Text::Error::ACTIVATE_LOGGED_IN
|
15
|
+
else
|
16
|
+
params = get_user_credentials(options.merge(:invited => true))
|
17
|
+
|
18
|
+
# Prompt for the password confirmation if password is not from command line
|
19
|
+
unless options[:password]
|
20
|
+
password_confirmation = HighLine.ask(Text::Prompt::PASSWORD_CONFIRMATION) { |q| q.echo = "*" }
|
21
|
+
unless password_confirmation == params[:password]
|
22
|
+
exit_failure Text::Process::PASSWORD_CONFIRMATION_INCORRECT
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
params[:user_git_pubkey] = prompt_ssh_key(options[:ssh_key_file])
|
28
|
+
rescue TddiumError => e
|
29
|
+
exit_failure e.message
|
30
|
+
end
|
31
|
+
|
32
|
+
# Prompt for accepting license
|
33
|
+
content = File.open(License::FILE_NAME) do |file|
|
34
|
+
file.read
|
35
|
+
end
|
36
|
+
say content
|
37
|
+
license_accepted = ask(Text::Prompt::LICENSE_AGREEMENT)
|
38
|
+
exit_failure unless license_accepted.downcase == Text::Prompt::Response::AGREE_TO_LICENSE.downcase
|
39
|
+
|
40
|
+
begin
|
41
|
+
say Text::Process::STARTING_ACCOUNT_CREATION
|
42
|
+
new_user = call_api(:post, Api::Path::USERS, {:user => params}, false, false)
|
43
|
+
write_api_key(new_user["user"]["api_key"])
|
44
|
+
role = new_user["user"]["account_role"]
|
45
|
+
if role.nil? || role == "owner"
|
46
|
+
u = new_user["user"]
|
47
|
+
say Text::Process::ACCOUNT_CREATED % [u["email"], u["trial_remaining"], u["recurly_url"]]
|
48
|
+
else
|
49
|
+
say Text::Process::ACCOUNT_ADDED % [new_user["user"]["email"], new_user["user"]["account_role"], new_user["user"]["account"]]
|
50
|
+
end
|
51
|
+
rescue TddiumClient::Error::API => e
|
52
|
+
exit_failure ((e.status == Api::ErrorCode::INVALID_INVITATION) ? Text::Error::INVALID_INVITATION : e.message)
|
53
|
+
rescue TddiumClient::Error::Base => e
|
54
|
+
exit_failure say e.message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "heroku", "Connect Heroku account with Tddium"
|
7
|
+
method_option :email, :type => :string, :default => nil
|
8
|
+
method_option :password, :type => :string, :default => nil
|
9
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
10
|
+
method_option :app, :type => :string, :default => nil
|
11
|
+
def heroku
|
12
|
+
set_shell
|
13
|
+
set_default_environment
|
14
|
+
if user_details = user_logged_in?
|
15
|
+
# User is already logged in, so just display the info
|
16
|
+
show_user_details(user_details)
|
17
|
+
else
|
18
|
+
begin
|
19
|
+
heroku_config = HerokuConfig.read_config(options[:app])
|
20
|
+
# User has logged in to heroku, and TDDIUM environment variables are
|
21
|
+
# present
|
22
|
+
handle_heroku_user(options, heroku_config)
|
23
|
+
rescue HerokuConfig::HerokuNotFound
|
24
|
+
gemlist = `gem list heroku`
|
25
|
+
msg = Text::Error::Heroku::NOT_FOUND % gemlist
|
26
|
+
exit_failure msg
|
27
|
+
rescue HerokuConfig::TddiumNotAdded
|
28
|
+
exit_failure Text::Error::Heroku::NOT_ADDED
|
29
|
+
rescue HerokuConfig::InvalidFormat
|
30
|
+
exit_failure Text::Error::Heroku::INVALID_FORMAT
|
31
|
+
rescue HerokuConfig::NotLoggedIn
|
32
|
+
exit_failure Text::Error::Heroku::NOT_LOGGED_IN
|
33
|
+
rescue HerokuConfig::AppNotFound
|
34
|
+
exit_failure Text::Error::Heroku::APP_NOT_FOUND % options[:app]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "login", "Log in to tddium using your email address and password"
|
7
|
+
method_option :email, :type => :string, :default => nil
|
8
|
+
method_option :password, :type => :string, :default => nil
|
9
|
+
def login
|
10
|
+
set_shell
|
11
|
+
set_default_environment
|
12
|
+
if user_logged_in?
|
13
|
+
say Text::Process::ALREADY_LOGGED_IN
|
14
|
+
elsif login_user(:params => get_user_credentials(options), :show_error => true)
|
15
|
+
say Text::Process::LOGGED_IN_SUCCESSFULLY
|
16
|
+
else
|
17
|
+
exit_failure
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "logout", "Log out of tddium"
|
7
|
+
def logout
|
8
|
+
set_shell
|
9
|
+
set_default_environment
|
10
|
+
FileUtils.rm(tddium_file_name) if File.exists?(tddium_file_name)
|
11
|
+
say Text::Process::LOGGED_OUT_SUCCESSFULLY
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "password", "Change password"
|
7
|
+
map "passwd" => :password
|
8
|
+
def password
|
9
|
+
set_shell
|
10
|
+
set_default_environment
|
11
|
+
exit_failure unless tddium_settings
|
12
|
+
user_details = user_logged_in?
|
13
|
+
exit_failure unless user_details
|
14
|
+
|
15
|
+
params = {}
|
16
|
+
params[:current_password] = HighLine.ask(Text::Prompt::CURRENT_PASSWORD) { |q| q.echo = "*" }
|
17
|
+
params[:password] = HighLine.ask(Text::Prompt::NEW_PASSWORD) { |q| q.echo = "*" }
|
18
|
+
params[:password_confirmation] = HighLine.ask(Text::Prompt::PASSWORD_CONFIRMATION) { |q| q.echo = "*" }
|
19
|
+
|
20
|
+
begin
|
21
|
+
user_id = user_details["user"]["id"]
|
22
|
+
result = call_api(:put, "#{Api::Path::USERS}/#{user_id}/", {:user=>params},
|
23
|
+
tddium_settings["api_key"], false)
|
24
|
+
say Text::Process::PASSWORD_CHANGED
|
25
|
+
rescue TddiumClient::Error::API => e
|
26
|
+
exit_failure Text::Error::PASSWORD_ERROR % e.explanation
|
27
|
+
rescue TddiumClient::Error::Base => e
|
28
|
+
exit_failure e.message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,127 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
map "cucumber" => :spec
|
7
|
+
map "test" => :spec
|
8
|
+
map "run" => :spec
|
9
|
+
desc "spec", "Run the test suite"
|
10
|
+
method_option :user_data_file, :type => :string, :default => nil
|
11
|
+
method_option :max_parallelism, :type => :numeric, :default => nil
|
12
|
+
method_option :test_pattern, :type => :string, :default => nil
|
13
|
+
method_option :force, :type => :boolean, :default => false
|
14
|
+
def spec
|
15
|
+
set_shell
|
16
|
+
set_default_environment
|
17
|
+
git_version_ok
|
18
|
+
exit_failure unless git_repo? && tddium_settings && suite_for_current_branch?
|
19
|
+
|
20
|
+
if git_changes then
|
21
|
+
exit_failure(Text::Error::GIT_CHANGES_NOT_COMMITTED) if !options[:force]
|
22
|
+
warn(Text::Warning::GIT_CHANGES_NOT_COMMITTED)
|
23
|
+
end
|
24
|
+
|
25
|
+
test_execution_params = {}
|
26
|
+
|
27
|
+
user_data_file_path = get_remembered_option(options, :user_data_file, nil) do |user_data_file_path|
|
28
|
+
if File.exists?(user_data_file_path)
|
29
|
+
user_data = File.open(user_data_file_path) { |file| file.read }
|
30
|
+
test_execution_params[:user_data_text] = Base64.encode64(user_data)
|
31
|
+
test_execution_params[:user_data_filename] = File.basename(user_data_file_path)
|
32
|
+
else
|
33
|
+
exit_failure Text::Error::NO_USER_DATA_FILE % user_data_file_path
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
max_parallelism = get_remembered_option(options, :max_parallelism, nil) do |max_parallelism|
|
38
|
+
test_execution_params[:max_parallelism] = max_parallelism
|
39
|
+
end
|
40
|
+
|
41
|
+
test_pattern = get_remembered_option(options, :test_pattern, nil)
|
42
|
+
|
43
|
+
start_time = Time.now
|
44
|
+
|
45
|
+
# Call the API to get the suite and its tests
|
46
|
+
begin
|
47
|
+
suite_details = call_api(:get, current_suite_path)
|
48
|
+
|
49
|
+
exit_failure Text::Error::GIT_REPO_NOT_READY unless suite_details["suite"]["repoman_current"]
|
50
|
+
|
51
|
+
# Push the latest code to git
|
52
|
+
exit_failure Text::Error::GIT_PUSH_FAILED unless update_git_remote_and_push(suite_details)
|
53
|
+
|
54
|
+
# Create a session
|
55
|
+
new_session = call_api(:post, Api::Path::SESSIONS)
|
56
|
+
session_id = new_session["session"]["id"]
|
57
|
+
|
58
|
+
# Register the tests
|
59
|
+
call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::REGISTER_TEST_EXECUTIONS}", {:suite_id => current_suite_id, :test_pattern => test_pattern})
|
60
|
+
|
61
|
+
# Start the tests
|
62
|
+
start_test_executions = call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::START_TEST_EXECUTIONS}", test_execution_params)
|
63
|
+
|
64
|
+
say Text::Process::STARTING_TEST % start_test_executions["started"]
|
65
|
+
|
66
|
+
tests_not_finished_yet = true
|
67
|
+
finished_tests = {}
|
68
|
+
test_statuses = Hash.new(0)
|
69
|
+
|
70
|
+
say Text::Process::CHECK_TEST_REPORT % start_test_executions["report"]
|
71
|
+
say Text::Process::TERMINATE_INSTRUCTION
|
72
|
+
while tests_not_finished_yet do
|
73
|
+
# Poll the API to check the status
|
74
|
+
current_test_executions = call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::TEST_EXECUTIONS}")
|
75
|
+
|
76
|
+
# Catch Ctrl-C to interrupt the test
|
77
|
+
Signal.trap(:INT) do
|
78
|
+
say Text::Process::INTERRUPT
|
79
|
+
say Text::Process::CHECK_TEST_STATUS
|
80
|
+
tests_not_finished_yet = false
|
81
|
+
end
|
82
|
+
|
83
|
+
# Print out the progress of running tests
|
84
|
+
current_test_executions["tests"].each do |test_name, result_params|
|
85
|
+
test_status = result_params["status"]
|
86
|
+
if result_params["finished"] && !finished_tests[test_name]
|
87
|
+
message = case test_status
|
88
|
+
when "passed" then [".", :green, false]
|
89
|
+
when "failed" then ["F", :red, false]
|
90
|
+
when "error" then ["E", nil, false]
|
91
|
+
when "pending" then ["*", :yellow, false]
|
92
|
+
when "skipped" then [".", :yellow, false]
|
93
|
+
else [".", nil, false]
|
94
|
+
end
|
95
|
+
finished_tests[test_name] = test_status
|
96
|
+
test_statuses[test_status] += 1
|
97
|
+
say *message
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# If all tests finished, exit the loop else sleep
|
102
|
+
if finished_tests.size == current_test_executions["tests"].size
|
103
|
+
tests_not_finished_yet = false
|
104
|
+
else
|
105
|
+
sleep(Default::SLEEP_TIME_BETWEEN_POLLS)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Print out the result
|
110
|
+
say ""
|
111
|
+
say Text::Process::FINISHED_TEST % (Time.now - start_time)
|
112
|
+
say "#{finished_tests.size} tests, #{test_statuses["failed"]} failures, #{test_statuses["error"]} errors, #{test_statuses["pending"]} pending"
|
113
|
+
|
114
|
+
# Save the spec options
|
115
|
+
write_suite(suite_details["suite"].merge({"id" => current_suite_id}),
|
116
|
+
{"user_data_file" => user_data_file_path,
|
117
|
+
"max_parallelism" => max_parallelism,
|
118
|
+
"test_pattern" => test_pattern})
|
119
|
+
|
120
|
+
exit_failure if test_statuses["failed"] > 0 || test_statuses["error"] > 0
|
121
|
+
rescue TddiumClient::Error::Base
|
122
|
+
exit_failure "Failed due to error communicating with Tddium"
|
123
|
+
rescue RuntimeError => e
|
124
|
+
exit_failure "Failed due to internal error: #{e.inspect} #{e.backtrace}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
desc "status", "Display information about this suite, and any open dev sessions"
|
7
|
+
def status
|
8
|
+
set_shell
|
9
|
+
set_default_environment
|
10
|
+
git_version_ok
|
11
|
+
exit_failure unless git_repo? && tddium_settings
|
12
|
+
|
13
|
+
begin
|
14
|
+
current_suites = call_api(:get, Api::Path::SUITES)
|
15
|
+
if current_suites["suites"].size == 0
|
16
|
+
say Text::Status::NO_SUITE
|
17
|
+
else
|
18
|
+
if current_suite = current_suites["suites"].detect {|suite| suite["id"] == current_suite_id}
|
19
|
+
say Text::Status::CURRENT_SUITE % current_suite["repo_name"]
|
20
|
+
display_attributes(DisplayedAttributes::SUITE, current_suite)
|
21
|
+
say Text::Status::SEPARATOR
|
22
|
+
else
|
23
|
+
say Text::Status::CURRENT_SUITE_UNAVAILABLE
|
24
|
+
end
|
25
|
+
end
|
26
|
+
show_session_details({:active => false, :order => "date", :limit => 10}, Text::Status::NO_INACTIVE_SESSION, Text::Status::INACTIVE_SESSIONS)
|
27
|
+
show_session_details({:active => true, :order => "date"}, Text::Status::NO_ACTIVE_SESSION, Text::Status::ACTIVE_SESSIONS)
|
28
|
+
rescue TddiumClient::Error::Base => e
|
29
|
+
exit_failure e.message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def show_session_details(params, no_session_prompt, all_session_prompt)
|
36
|
+
begin
|
37
|
+
current_sessions = call_api(:get, Api::Path::SESSIONS, params)
|
38
|
+
say Text::Status::SEPARATOR
|
39
|
+
if current_sessions["sessions"].size == 0
|
40
|
+
say no_session_prompt
|
41
|
+
else
|
42
|
+
say all_session_prompt
|
43
|
+
current_sessions["sessions"].reverse_each do |session|
|
44
|
+
duration = "(%ds)" % ((session["end_time"] ? Time.parse(session["end_time"]) : Time.now) - Time.parse(session["start_time"])).round
|
45
|
+
say Text::Status::SESSION_DETAIL % [session["report"],
|
46
|
+
duration,
|
47
|
+
session["start_time"],
|
48
|
+
session["test_execution_stats"]]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
rescue TddiumClient::Error::Base
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|