orc-cli 0.1.0
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 +7 -0
- data/Rakefile +30 -0
- data/bin/orc +15 -0
- data/config/commands.yml +15 -0
- data/lib/cli/base.rb +13 -0
- data/lib/cli/client_collector.rb +109 -0
- data/lib/cli/cmd_consts.rb +16 -0
- data/lib/cli/commands/help.rb +13 -0
- data/lib/cli/commands/multiple_tests.rb +137 -0
- data/lib/cli/commands/rerun.rb +29 -0
- data/lib/cli/commands/suites_configure.rb +97 -0
- data/lib/cli/commands/test_suite_management.rb +188 -0
- data/lib/cli/configs.rb +34 -0
- data/lib/cli/consts.rb +8 -0
- data/lib/cli/ctt_extensions.rb +36 -0
- data/lib/cli/errors.rb +24 -0
- data/lib/cli/report.rb +62 -0
- data/lib/cli/runner.rb +134 -0
- data/lib/cli/suites.rb +36 -0
- data/lib/cli/version.rb +6 -0
- data/lib/cli.rb +30 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/unit/help_spec.rb +15 -0
- metadata +198 -0
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "rake"
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
|
5
|
+
desc "build gem file"
|
6
|
+
task :build do
|
7
|
+
config_path = File.expand_path("./config")
|
8
|
+
unless Dir.exists?(config_path)
|
9
|
+
FileUtils.mkdir(config_path)
|
10
|
+
end
|
11
|
+
src = File.join(config_path, "template/commands.yml")
|
12
|
+
dest = File.join(config_path, "commands.yml")
|
13
|
+
FileUtils.cp(src, dest)
|
14
|
+
system("gem build orc-cli.gemspec -V")
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined?(RSpec)
|
18
|
+
namespace :spec do
|
19
|
+
SPEC_OPTS = %w(--format documentation --colour)
|
20
|
+
|
21
|
+
desc "Run unit tests"
|
22
|
+
RSpec::Core::RakeTask.new(:unit) do |t|
|
23
|
+
t.pattern = "spec/unit/**/*_spec.rb"
|
24
|
+
t.rspec_opts = SPEC_OPTS
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Run tests"
|
29
|
+
task :spec => %w(spec:unit)
|
30
|
+
end
|
data/bin/orc
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.expand_path("../../lib", __FILE__))
|
4
|
+
require "cli"
|
5
|
+
|
6
|
+
begin
|
7
|
+
Thread.abort_on_exception = true
|
8
|
+
CTT::Cli::Runner.run(ARGV.dup)
|
9
|
+
rescue Errno::EPIPE
|
10
|
+
puts("pipe closed, exiting...")
|
11
|
+
exit(0)
|
12
|
+
rescue Interrupt
|
13
|
+
puts "\nExiting..."
|
14
|
+
exit(1)
|
15
|
+
end
|
data/config/commands.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
commands:
|
3
|
+
help:
|
4
|
+
usage: help
|
5
|
+
desc: list all avaiable commands
|
6
|
+
tests:
|
7
|
+
usage: tests
|
8
|
+
desc: run default multiple test suites.
|
9
|
+
"add suite":
|
10
|
+
usage: "add suite <Test Suite Path> [alias]"
|
11
|
+
desc: "add specific test suite to orc, and one alias can be given to resolve naming conflict"
|
12
|
+
suites:
|
13
|
+
usage: "suites"
|
14
|
+
desc: "list all available test suites registered "
|
15
|
+
|
data/lib/cli/base.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module CTT::Cli
|
4
|
+
class ClientCollector
|
5
|
+
|
6
|
+
def initialize(command, suite, runner)
|
7
|
+
@info = {}
|
8
|
+
@suite = suite
|
9
|
+
@suites = runner.suites
|
10
|
+
@uuid = runner.uuid
|
11
|
+
|
12
|
+
@info[:suite] = @suite
|
13
|
+
@info[:command] = command
|
14
|
+
end
|
15
|
+
|
16
|
+
def post
|
17
|
+
collect
|
18
|
+
|
19
|
+
payload = @info.dup
|
20
|
+
payload[:file] = File.open(@tar_file_path, "r")
|
21
|
+
payload[:multipart] = true
|
22
|
+
|
23
|
+
#retry 3 times
|
24
|
+
3.times do
|
25
|
+
begin
|
26
|
+
response = RestClient.post("#{RESULTS_SERVER_URL}/tac/upload", payload)
|
27
|
+
break if response.code == 200
|
28
|
+
rescue
|
29
|
+
end
|
30
|
+
end
|
31
|
+
FileUtils.rm(payload[:file].path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def collect
|
35
|
+
get_os
|
36
|
+
get_test_reports
|
37
|
+
get_uuid
|
38
|
+
get_timestamp
|
39
|
+
get_hostname
|
40
|
+
get_username
|
41
|
+
get_ipaddr
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_hostname
|
45
|
+
@info[:hostname] = `hostname`.strip
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_username
|
49
|
+
@info[:username] = Etc.getlogin
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_ipaddr
|
53
|
+
@info[:ip] = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_uuid
|
57
|
+
@info[:uuid] = @uuid.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_timestamp
|
61
|
+
@info[:time] = Time.now.getutc.to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_os
|
65
|
+
@info[:os] = RUBY_PLATFORM
|
66
|
+
|
67
|
+
case 1.size
|
68
|
+
when 4
|
69
|
+
@info[:platform] = "32bit"
|
70
|
+
when 8
|
71
|
+
@info[:platform] = "64bit"
|
72
|
+
else
|
73
|
+
@info[:platform] = nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def get_test_reports
|
79
|
+
suite_config_path = File.absolute_path(File.join(@suites.suites["suites"][@suite], TEST_SUITE_CONFIG_FILE))
|
80
|
+
suite_config = YAML.load_file(suite_config_path)
|
81
|
+
unless suite_config["results"]
|
82
|
+
say("no results field in #{suite_config_path}. abort!", :red)
|
83
|
+
exit(1)
|
84
|
+
end
|
85
|
+
report_path = File.absolute_path(File.join(@suites.suites["suites"][@suite], suite_config["results"]))
|
86
|
+
unless File.exists?(report_path)
|
87
|
+
say("report path did not exists. abort!", :red)
|
88
|
+
exit(1)
|
89
|
+
end
|
90
|
+
@tar_file_path = zip_test_reports(report_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
def zip_test_reports(reports_path)
|
94
|
+
|
95
|
+
temp_file_path = File.join(Dir.tmpdir, "reports-#{@uuid}.tgz")
|
96
|
+
pwd = Dir.pwd
|
97
|
+
Dir.chdir(File.dirname(reports_path))
|
98
|
+
`tar czf #{temp_file_path} #{File.basename(reports_path)} 2>&1`
|
99
|
+
unless $?.exitstatus == 0
|
100
|
+
say("fail to tarball test reports. abort!", :red)
|
101
|
+
FileUtils.rm(temp_file_path)
|
102
|
+
exit(1)
|
103
|
+
end
|
104
|
+
Dir.chdir(pwd)
|
105
|
+
|
106
|
+
temp_file_path
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli
|
3
|
+
STATIC_COMMANDS = {"help" => {"usage" => "help",
|
4
|
+
"desc" => "list all available commands"},
|
5
|
+
"tests" => {"usage" => "tests",
|
6
|
+
"desc" => "run default multiple test suites."},
|
7
|
+
"rerun" => {"usage" => "rerun",
|
8
|
+
"desc" => "rerun failed cases for multiple test suites."},
|
9
|
+
"add suite" => {"usage" => "add suite",
|
10
|
+
"desc" => "add specific test suite to orc"},
|
11
|
+
"delete suite" => {"usage" => "delete suite",
|
12
|
+
"desc" => "list all test suites configuration"},
|
13
|
+
"suites" => {"usage" => "suites",
|
14
|
+
"desc" => "list all test suites configuration"}}
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli::Command
|
3
|
+
|
4
|
+
class MultipleTests < Base
|
5
|
+
|
6
|
+
MAX_RERUN_TIMES = 10
|
7
|
+
|
8
|
+
include CTT::Cli
|
9
|
+
|
10
|
+
def initialize(command, args, runner)
|
11
|
+
super(args, runner)
|
12
|
+
@suites = @runner.suites
|
13
|
+
@command = command
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
eval(@command)
|
18
|
+
end
|
19
|
+
|
20
|
+
def tests
|
21
|
+
say("run multiple test suites", :green)
|
22
|
+
run_tests
|
23
|
+
show_summary
|
24
|
+
end
|
25
|
+
|
26
|
+
def rerun
|
27
|
+
say("rerun failed cases for multiple test suites", :green)
|
28
|
+
rerun_tests
|
29
|
+
show_summary(true)
|
30
|
+
end
|
31
|
+
|
32
|
+
def rerun_tests
|
33
|
+
index = 1
|
34
|
+
@suites.suites["suites"].each do |name, _|
|
35
|
+
say("#{index}) start to run failed cases for test suite: #{name}\n", :yellow)
|
36
|
+
args = @args.insert(0, @command)
|
37
|
+
cmd = TestSuite.new(name, args, @runner)
|
38
|
+
cmd.run
|
39
|
+
index += 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def run_tests
|
44
|
+
say("**** Run multiple tests ****", :yellow)
|
45
|
+
index = 1
|
46
|
+
@suites.suites["suites"].each do |name, _|
|
47
|
+
say("#{index}) start to run test suite: #{name}\n", :yellow)
|
48
|
+
cmd = TestSuite.new(name, @args, @runner)
|
49
|
+
cmd.run
|
50
|
+
index += 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def show_summary(rerun = false)
|
55
|
+
summary = {:total => 0,
|
56
|
+
:failed => 0,
|
57
|
+
:pending => 0,
|
58
|
+
:duration => 0.0,
|
59
|
+
:failed_cases => {},
|
60
|
+
:pending_cases => {}
|
61
|
+
}
|
62
|
+
@suites.suites["suites"].each do |name, path|
|
63
|
+
suite_config_path = File.absolute_path(File.join(path, TEST_SUITE_CONFIG_FILE))
|
64
|
+
suite_config = YAML.load_file(suite_config_path)
|
65
|
+
unless suite_config["results"]
|
66
|
+
say("no results field in #{suite_config_path}. abort!", :red)
|
67
|
+
exit(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
result_path = File.join(path, suite_config["results"])
|
71
|
+
if rerun
|
72
|
+
result_file = File.join(get_rerun_folder(result_path), TEST_RESULT_FILE)
|
73
|
+
else
|
74
|
+
result_file = File.join(result_path, TEST_RESULT_FILE)
|
75
|
+
end
|
76
|
+
|
77
|
+
report = TestReport.new(result_file)
|
78
|
+
report.parse
|
79
|
+
|
80
|
+
summary[:total] += report.summary[:total]
|
81
|
+
summary[:failed] += report.summary[:failed]
|
82
|
+
summary[:pending] += report.summary[:pending]
|
83
|
+
summary[:duration] += report.summary[:duration]
|
84
|
+
summary[:failed_cases][name] = report.summary[:failed_cases]
|
85
|
+
summary[:pending_cases][name] = report.summary[:pending_cases]
|
86
|
+
end
|
87
|
+
|
88
|
+
print_cases_summary(summary)
|
89
|
+
print_failed_cases(summary)
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
def print_cases_summary(summary)
|
94
|
+
say("**** Summary for multiple tests ****", :yellow)
|
95
|
+
say("\nFinished in #{format_time(summary[:duration])}")
|
96
|
+
|
97
|
+
color = :green
|
98
|
+
color = :yellow if summary[:pending] > 0
|
99
|
+
color = :red if summary[:failed] > 0
|
100
|
+
say("#{summary[:total]} examples, #{summary[:failed]} failures, #{summary[:pending]} pendings", color)
|
101
|
+
end
|
102
|
+
|
103
|
+
def print_failed_cases(summary)
|
104
|
+
if summary[:failed] > 0
|
105
|
+
say("\nFailures:")
|
106
|
+
summary[:failed_cases].each do |suite, cases|
|
107
|
+
say(" Test Suite: #{suite}", :yellow)
|
108
|
+
cases.each do |c|
|
109
|
+
say(" #{c.strip}", :red)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
say("execute #{yellow("rerun")} command to run all failed cases.")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def format_time(t)
|
117
|
+
time_str = ''
|
118
|
+
time_str += (t / 3600).to_i.to_s + " hours " if t > 3600
|
119
|
+
time_str += (t % 3600 / 60).to_i.to_s + " minutes " if t > 60
|
120
|
+
time_str += (t % 60).to_f.round(2).to_s + " seconds"
|
121
|
+
time_str
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_rerun_folder(result_folder)
|
125
|
+
rerun_folder = result_folder
|
126
|
+
i = MAX_RERUN_TIMES
|
127
|
+
while(i > 0)
|
128
|
+
if File.exists?(File.join(result_folder, "rerun#{i}"))
|
129
|
+
rerun_folder = File.join(result_folder, "rerun#{i}")
|
130
|
+
break
|
131
|
+
end
|
132
|
+
i -= 1
|
133
|
+
end
|
134
|
+
rerun_folder
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli::Command
|
3
|
+
|
4
|
+
class RerunTests < Base
|
5
|
+
|
6
|
+
include CTT::Cli
|
7
|
+
|
8
|
+
def initialize(args, runner)
|
9
|
+
super(args, runner)
|
10
|
+
@suites = @runner.suites
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
say("rerun failed cases", :green)
|
15
|
+
#run_tests
|
16
|
+
show_summary
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_tests
|
20
|
+
index = 1
|
21
|
+
@suites.suites["suites"].each do |name, _|
|
22
|
+
say("#{index}) start to run test suite: #{name}\n", :yellow)
|
23
|
+
cmd = TestSuite.new(name, @args, @runner)
|
24
|
+
cmd.run
|
25
|
+
index += 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli::Command
|
3
|
+
|
4
|
+
class SuitesConfig < Base
|
5
|
+
|
6
|
+
#TEST_SUITE_CONFIG_FILE = "orc.yml"
|
7
|
+
|
8
|
+
include Interactive, CTT::Cli
|
9
|
+
|
10
|
+
def initialize(command, args, runner)
|
11
|
+
super(args, runner)
|
12
|
+
|
13
|
+
pieces = command.split(" ")
|
14
|
+
pieces.insert(0, "list") if pieces.size == 1
|
15
|
+
@action, _ = pieces
|
16
|
+
|
17
|
+
@configs = @runner.configs
|
18
|
+
@suites = @runner.suites
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
eval(@action)
|
23
|
+
end
|
24
|
+
|
25
|
+
def add
|
26
|
+
puts "add suite"
|
27
|
+
#location = @configs.configs["suites"][@suite]["location"]
|
28
|
+
location = ""
|
29
|
+
invalid_input = true
|
30
|
+
3.times do
|
31
|
+
user_input = ask("test suite source directory").strip
|
32
|
+
if user_input =~ /^~/
|
33
|
+
user_input = File.expand_path(user_input)
|
34
|
+
else
|
35
|
+
user_input = File.absolute_path(user_input)
|
36
|
+
end
|
37
|
+
if Dir.exist?(user_input)
|
38
|
+
if File.exist?(File.join(user_input, TEST_SUITE_CONFIG_FILE))
|
39
|
+
invalid_input = false
|
40
|
+
location = user_input
|
41
|
+
break
|
42
|
+
else
|
43
|
+
say("the configure file: #{yellow(TEST_SUITE_CONFIG_FILE)} " +
|
44
|
+
"cannot be found under #{user_input}.")
|
45
|
+
end
|
46
|
+
else
|
47
|
+
say("the directory: #{user_input} is invalid.")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if invalid_input
|
52
|
+
say("invalid inputs for 3 times. abort!", :red)
|
53
|
+
exit(1)
|
54
|
+
end
|
55
|
+
|
56
|
+
load_test_suite_config(location)
|
57
|
+
suite_alias = @suite_config["name"]
|
58
|
+
|
59
|
+
@suites.suites["suites"][suite_alias] = location
|
60
|
+
@suites.save
|
61
|
+
say("configure suite: #{suite_alias} successfully.", :green)
|
62
|
+
end
|
63
|
+
|
64
|
+
def list
|
65
|
+
print_suites
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_test_suite_config(location)
|
69
|
+
path = File.join(location, TEST_SUITE_CONFIG_FILE)
|
70
|
+
@suite_config = YAML.load_file(path)
|
71
|
+
unless @suite_config.is_a?(Hash)
|
72
|
+
say("#{path} is not valid yml file.", :red)
|
73
|
+
exit(1)
|
74
|
+
end
|
75
|
+
|
76
|
+
# validate test suite config file
|
77
|
+
validate_points = %w(name commands results)
|
78
|
+
validate_points.each do |p|
|
79
|
+
unless @suite_config.keys.include?(p)
|
80
|
+
say("field: '#{p}' is not found in config file #{path}", :red)
|
81
|
+
exit(1)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def print_suites
|
87
|
+
header = ["alias", "path"]
|
88
|
+
rows = []
|
89
|
+
@suites.suites["suites"].each do |suite_alias, path|
|
90
|
+
rows << [suite_alias, path]
|
91
|
+
end
|
92
|
+
table = Terminal::Table.new(:headings => header, :rows => rows)
|
93
|
+
puts table
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli::Command
|
3
|
+
|
4
|
+
class TestSuite < Base
|
5
|
+
|
6
|
+
#USER_INPUT = "USER_INPUT"
|
7
|
+
#TEST_SUITE_CONFIG_FILE = "orc.yml"
|
8
|
+
SUPPORT_OPTIONS = {"--force" => "bypass git dirty state check"}
|
9
|
+
|
10
|
+
include Interactive, CTT::Cli
|
11
|
+
|
12
|
+
def initialize(command, args, runner)
|
13
|
+
super(args, runner)
|
14
|
+
|
15
|
+
pieces = command.split(" ")
|
16
|
+
pieces.insert(0, "") if pieces.size == 1
|
17
|
+
action, suite = pieces
|
18
|
+
|
19
|
+
@action = action
|
20
|
+
@suite = suite
|
21
|
+
@configs = runner.configs
|
22
|
+
@suites = runner.suites
|
23
|
+
end
|
24
|
+
|
25
|
+
def run
|
26
|
+
@action = "test" if @action == ""
|
27
|
+
eval(@action)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def list
|
32
|
+
check_configuration
|
33
|
+
get_suite_configs
|
34
|
+
|
35
|
+
say("all subcommands for test suite: #{@suite}", :yellow)
|
36
|
+
say("Options:", :yellow)
|
37
|
+
SUPPORT_OPTIONS.each do |opt, helper|
|
38
|
+
say("\t[#{opt}] \t#{helper}")
|
39
|
+
end
|
40
|
+
nl
|
41
|
+
|
42
|
+
@suite_configs["commands"].each do |command, details|
|
43
|
+
say("#{@suite} #{command}", :green)
|
44
|
+
say("\t#{details["desc"]}\n")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure
|
49
|
+
puts "configure #{@suite}"
|
50
|
+
location = @configs.configs["suites"][@suite]["location"]
|
51
|
+
location = "" if location == USER_INPUT
|
52
|
+
invalid_input = true
|
53
|
+
3.times do
|
54
|
+
user_input = ask("suite: #{@suite} source directory:", :default => location).strip
|
55
|
+
if user_input =~ /^~/
|
56
|
+
user_input = File.expand_path(user_input)
|
57
|
+
else
|
58
|
+
user_input = File.absolute_path(user_input)
|
59
|
+
end
|
60
|
+
if Dir.exist?(user_input)
|
61
|
+
if File.exist?(File.join(user_input, TEST_SUITE_CONFIG_FILE))
|
62
|
+
invalid_input = false
|
63
|
+
location = user_input
|
64
|
+
break
|
65
|
+
else
|
66
|
+
say("the configure file: #{yellow(TEST_SUITE_CONFIG_FILE)} " +
|
67
|
+
"cannot be found under #{user_input}.")
|
68
|
+
end
|
69
|
+
else
|
70
|
+
say("the directory: #{user_input} is invalid.")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
if invalid_input
|
75
|
+
say("invalid inputs for 3 times. abort!", :red)
|
76
|
+
exit(1)
|
77
|
+
else
|
78
|
+
@configs.configs["suites"][@suite]["location"] = location
|
79
|
+
@configs.save
|
80
|
+
say("configure suite: #{@suite} successfully.", :green)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test
|
85
|
+
check_configuration
|
86
|
+
parse_options
|
87
|
+
check_if_dirty_state unless @options["--force"]
|
88
|
+
get_suite_configs
|
89
|
+
|
90
|
+
dependencies, command = parse_command
|
91
|
+
|
92
|
+
threads = []
|
93
|
+
pwd = Dir.pwd
|
94
|
+
Dir.chdir(@suites.suites["suites"][@suite])
|
95
|
+
threads << Thread.new do
|
96
|
+
# dependency should be successful before run testing command
|
97
|
+
say("preparing test suite: #{@suite}...")
|
98
|
+
dependencies.each do |d|
|
99
|
+
output = `#{d}`
|
100
|
+
unless $? == 0
|
101
|
+
say(output)
|
102
|
+
say("fail to execute dependency command: #{d}. abort!", :red)
|
103
|
+
exit(1)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
say("\nrun command: #{yellow(command)}")
|
108
|
+
system(command)
|
109
|
+
end
|
110
|
+
|
111
|
+
threads.each { |t| t.join }
|
112
|
+
Dir.chdir(pwd)
|
113
|
+
collector = ClientCollector.new(@runner.command, @suite, @runner)
|
114
|
+
collector.post
|
115
|
+
end
|
116
|
+
|
117
|
+
def check_configuration
|
118
|
+
unless @suites.suites["suites"].has_key?(@suite)
|
119
|
+
say("suite configure file: #{@suites.file} did not has key: #{@suite}")
|
120
|
+
exit(1)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def check_if_dirty_state
|
125
|
+
if dirty_state?
|
126
|
+
say("\n%s\n" % [`git status`])
|
127
|
+
say("Your current directory has some local modifications, " +
|
128
|
+
"please discard or commit them first.\n" +
|
129
|
+
"Or use #{yellow("--force")} to bypass git dirty check.")
|
130
|
+
exit(1)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def dirty_state?
|
135
|
+
`which git`
|
136
|
+
return false unless $? == 0
|
137
|
+
|
138
|
+
Dir.chdir(@suites.suites["suites"][@suite])
|
139
|
+
(File.directory?(".git") || File.directory?(File.join("..", ".git"))) \
|
140
|
+
&& `git status --porcelain | wc -l`.to_i > 0
|
141
|
+
end
|
142
|
+
|
143
|
+
def parse_options
|
144
|
+
@options = {}
|
145
|
+
opts = SUPPORT_OPTIONS.keys
|
146
|
+
@args.each do |arg|
|
147
|
+
if opts.index(arg)
|
148
|
+
@options[arg] = true
|
149
|
+
@args.delete(arg)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def parse_command
|
155
|
+
subcmd = ""
|
156
|
+
dependencies = []
|
157
|
+
if @args.empty?
|
158
|
+
subcmd = @suite_configs["commands"]["default"]["exec"]
|
159
|
+
dependencies = @suite_configs["commands"]["default"]["dependencies"]
|
160
|
+
elsif @suite_configs["commands"].has_key?(@args[0])
|
161
|
+
subcmd = @suite_configs["commands"][@args[0]]["exec"]
|
162
|
+
dependencies = @suite_configs["commands"][@args[0]]["dependencies"]
|
163
|
+
@args.delete(@args[0])
|
164
|
+
else
|
165
|
+
say("#{@args[0]} is not invalid sub-command, run as default command")
|
166
|
+
subcmd = @suite_configs["commands"]["default"]["exec"]
|
167
|
+
dependencies = @suite_configs["commands"]["default"]["dependencies"]
|
168
|
+
end
|
169
|
+
|
170
|
+
unless @args.empty?
|
171
|
+
subcmd = subcmd + " " + @args.join(" ")
|
172
|
+
end
|
173
|
+
|
174
|
+
[dependencies, subcmd]
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_suite_configs
|
178
|
+
suite_configs_path = File.join(@suites.suites["suites"][@suite],
|
179
|
+
CTT::Cli::TEST_SUITE_CONFIG_FILE)
|
180
|
+
@suite_configs ||= YAML.load_file(suite_configs_path)
|
181
|
+
unless @suite_configs.is_a?(Hash)
|
182
|
+
say("invalid yaml format for file: #{suite_configs_path}", :red)
|
183
|
+
exit(1)
|
184
|
+
end
|
185
|
+
@suite_configs
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
data/lib/cli/configs.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli
|
3
|
+
class Configs
|
4
|
+
|
5
|
+
attr_accessor :configs, :suites
|
6
|
+
|
7
|
+
attr_reader :commands
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@suites = Suites.new.suites
|
11
|
+
load_commands
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_commands
|
15
|
+
@commands = STATIC_COMMANDS.dup
|
16
|
+
commands = {}
|
17
|
+
@suites["suites"].each do |suite, _|
|
18
|
+
# for each suite, three commands should be added.
|
19
|
+
# - configure suite
|
20
|
+
# - suite [subcommand]
|
21
|
+
# - list suite
|
22
|
+
commands[suite] = {"usage" => "#{suite} [subcommand]",
|
23
|
+
"desc" => "run default test for test suite: #{suite}," +
|
24
|
+
" if no subcommand is specified"}
|
25
|
+
|
26
|
+
key = "list #{suite}"
|
27
|
+
commands[key] = {"usage" => key,
|
28
|
+
"desc" => "list all available subcommands for test suite: #{suite}"}
|
29
|
+
end
|
30
|
+
|
31
|
+
@commands.merge!(commands)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/cli/consts.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
module CTTExtensions
|
3
|
+
|
4
|
+
def say(message, color = nil, sep = "\n")
|
5
|
+
msg = message
|
6
|
+
puts Paint[msg, color]
|
7
|
+
end
|
8
|
+
|
9
|
+
def nl
|
10
|
+
puts ""
|
11
|
+
end
|
12
|
+
|
13
|
+
def err(message)
|
14
|
+
raise CTT::Cli::CliError, message
|
15
|
+
end
|
16
|
+
|
17
|
+
def red(message)
|
18
|
+
Paint[message, :red]
|
19
|
+
end
|
20
|
+
|
21
|
+
def yellow(message)
|
22
|
+
Paint[message, :yellow]
|
23
|
+
end
|
24
|
+
|
25
|
+
def green(message)
|
26
|
+
Paint[message, :green]
|
27
|
+
end
|
28
|
+
|
29
|
+
def cyan(message)
|
30
|
+
Paint[message, :cyan]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Object
|
35
|
+
include CTTExtensions
|
36
|
+
end
|
data/lib/cli/errors.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli
|
3
|
+
class CliError < StandardError
|
4
|
+
attr_reader :exit_code
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
@exit_code = 1
|
8
|
+
super(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.error_code(code = nil)
|
12
|
+
define_method(:error_code) { code }
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.exit_code(code = nil)
|
16
|
+
define_method(:exit_code) { code }
|
17
|
+
end
|
18
|
+
|
19
|
+
error_code(42)
|
20
|
+
end
|
21
|
+
|
22
|
+
class UnknownCommand < CliError; error_code(100); end
|
23
|
+
|
24
|
+
end
|
data/lib/cli/report.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli
|
3
|
+
class TestReport
|
4
|
+
|
5
|
+
attr_reader :summary
|
6
|
+
|
7
|
+
def initialize(xml_file)
|
8
|
+
unless File.exists?(xml_file)
|
9
|
+
say("Test result file: #{xml_file} does not exist. abort!", :red)
|
10
|
+
exit(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
@doc = LibXML::XML::Document.file(xml_file)
|
15
|
+
rescue Exception => e
|
16
|
+
say("Test result file: #{xml_file} is not a valid xml document. abort!", :red)
|
17
|
+
exit(1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse
|
22
|
+
@summary = {:total => 0,
|
23
|
+
:failed => 0,
|
24
|
+
:pending => 0,
|
25
|
+
:duration => 0.0,
|
26
|
+
:failed_cases => [],
|
27
|
+
:pending_cases => []}
|
28
|
+
|
29
|
+
cases = @doc.find("//case")
|
30
|
+
@summary[:total] = cases.size
|
31
|
+
get_duration
|
32
|
+
cases.each do |c|
|
33
|
+
get_failed_case(c)
|
34
|
+
get_pending_case(c)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_duration
|
39
|
+
# duration
|
40
|
+
duration = @doc.find_first("/result/duration")
|
41
|
+
@summary[:duration] += duration.content.to_f
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_failed_case(case_node)
|
45
|
+
# failed
|
46
|
+
failed = case_node.find_first("errorDetails")
|
47
|
+
if failed
|
48
|
+
@summary[:failed] += 1
|
49
|
+
@summary[:failed_cases] << case_node.find_first("rerunCommand").content
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_pending_case(case_node)
|
54
|
+
# pending
|
55
|
+
pending = case_node.find_first("skipped")
|
56
|
+
if pending.content == "true"
|
57
|
+
@summary[:pending] += 1
|
58
|
+
@summary[:pending_cases] << case_node.find_first("testName").content
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/cli/runner.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
module CTT::Cli
|
3
|
+
|
4
|
+
class Runner
|
5
|
+
|
6
|
+
attr_reader :commands, :uuid, :command
|
7
|
+
attr_accessor :configs, :suites
|
8
|
+
|
9
|
+
|
10
|
+
# @param [Array] args
|
11
|
+
def self.run(args)
|
12
|
+
new(args).run
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(args)
|
16
|
+
@args = args
|
17
|
+
|
18
|
+
banner = "Usage: orc [<options>] <command> [<args>]"
|
19
|
+
@option_parser = OptionParser.new(banner)
|
20
|
+
|
21
|
+
@configs = Configs.new
|
22
|
+
@commands = @configs.commands
|
23
|
+
@suites = Suites.new
|
24
|
+
@uuid = UUIDTools::UUID.random_create
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
#puts "the args: #{@args}"
|
29
|
+
parse_global_options
|
30
|
+
|
31
|
+
if @args.empty? && @options.empty?
|
32
|
+
say(usage)
|
33
|
+
exit(0)
|
34
|
+
end
|
35
|
+
|
36
|
+
if @options[:help]
|
37
|
+
Command::Help.new(@args, self).run
|
38
|
+
exit(0)
|
39
|
+
end
|
40
|
+
|
41
|
+
find, command, args = search_commands
|
42
|
+
unless find
|
43
|
+
say("invalid command. abort!", :red)
|
44
|
+
exit(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
@command = command
|
48
|
+
execute(command, args)
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_global_options
|
53
|
+
@options = {}
|
54
|
+
opts = @option_parser
|
55
|
+
|
56
|
+
opts.on("-v", "--version", "Show version") do
|
57
|
+
@options[:version] = true
|
58
|
+
say("orc %s" % [CTT::Cli::VERSION])
|
59
|
+
exit(0)
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-h", "--help", "Show help message") do
|
63
|
+
@options[:help] = true
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
@args = @option_parser.order!(@args)
|
68
|
+
rescue
|
69
|
+
say("invalid command. abort!", :red)
|
70
|
+
exit(1)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def usage
|
75
|
+
@option_parser.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def search_commands
|
79
|
+
cmds = @commands.keys
|
80
|
+
|
81
|
+
find = nil
|
82
|
+
longest_cmd = ""
|
83
|
+
args = []
|
84
|
+
size = @args.size
|
85
|
+
size.times do |index|
|
86
|
+
|
87
|
+
longest_cmd = @args[0..(size - index - 1)].join(" ")
|
88
|
+
find = cmds.index(longest_cmd)
|
89
|
+
if find
|
90
|
+
args = @args[(size - index)..-1]
|
91
|
+
break
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
[find, longest_cmd, args]
|
96
|
+
end
|
97
|
+
|
98
|
+
def execute(command, args)
|
99
|
+
handler = get_command_handler(command, args)
|
100
|
+
handler.run
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_command_handler(command, args)
|
104
|
+
# handle runtime commands
|
105
|
+
#
|
106
|
+
@configs.suites["suites"].keys.each do |s|
|
107
|
+
if command =~ /#{s}/
|
108
|
+
#pieces = command.split(" ")
|
109
|
+
#pieces.insert(0, "") if pieces.size == 1
|
110
|
+
#action, suite = pieces
|
111
|
+
return Command::TestSuite.new(command, args, self)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# handle user defined alias
|
116
|
+
#
|
117
|
+
# TODO
|
118
|
+
|
119
|
+
# handle static commands
|
120
|
+
#
|
121
|
+
handler =
|
122
|
+
case command
|
123
|
+
when "help"
|
124
|
+
Command::Help.new(args, self)
|
125
|
+
when "add suite", "delete suite", "suites"
|
126
|
+
Command::SuitesConfig.new(command, args, self)
|
127
|
+
when "tests", "rerun"
|
128
|
+
Command::MultipleTests.new(command, args, self)
|
129
|
+
else
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/cli/suites.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module CTT::Cli
|
4
|
+
class Suites
|
5
|
+
|
6
|
+
SUITES_CONFIG_FILE =
|
7
|
+
File.absolute_path(File.join(ENV["HOME"], ".orc/suites.yml"))
|
8
|
+
|
9
|
+
attr_accessor :suites
|
10
|
+
|
11
|
+
attr_reader :file
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
load
|
15
|
+
save
|
16
|
+
end
|
17
|
+
|
18
|
+
def load
|
19
|
+
@file = SUITES_CONFIG_FILE
|
20
|
+
unless Dir.exists?(File.dirname(@file))
|
21
|
+
Dir.mkdir(File.dirname(@file))
|
22
|
+
end
|
23
|
+
|
24
|
+
if File.exists?(@file)
|
25
|
+
@suites = YAML.load_file(@file)
|
26
|
+
else
|
27
|
+
@suites = {"suites" => {}}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def save
|
32
|
+
File.open(@file, "w") { |f| f.write YAML.dump(@suites) }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/cli/version.rb
ADDED
data/lib/cli.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "yaml"
|
5
|
+
require "paint"
|
6
|
+
require "interact"
|
7
|
+
require "terminal-table"
|
8
|
+
require "libxml"
|
9
|
+
require "tempfile"
|
10
|
+
require "uuidtools"
|
11
|
+
require "etc"
|
12
|
+
require "restclient"
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
require "cli/version"
|
17
|
+
require "cli/consts"
|
18
|
+
require "cli/ctt_extensions"
|
19
|
+
require "cli/cmd_consts"
|
20
|
+
require "cli/suites"
|
21
|
+
require "cli/configs"
|
22
|
+
require "cli/errors"
|
23
|
+
require "cli/runner"
|
24
|
+
require "cli/base"
|
25
|
+
require "cli/report"
|
26
|
+
require "cli/client_collector"
|
27
|
+
require "cli/commands/help"
|
28
|
+
require "cli/commands/suites_configure"
|
29
|
+
require "cli/commands/multiple_tests"
|
30
|
+
require "cli/commands/test_suite_management"
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
require "rspec/core"
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
$:.unshift(File.expand_path("../../lib", __FILE__))
|
6
|
+
require "cli"
|
7
|
+
|
8
|
+
RSpec.configure do |c|
|
9
|
+
c.before(:each) do
|
10
|
+
config_path = File.expand_path("./config")
|
11
|
+
unless Dir.exists?(config_path)
|
12
|
+
FileUtils.mkdir(config_path)
|
13
|
+
end
|
14
|
+
src = File.join(config_path, "template/commands.yml")
|
15
|
+
dest = File.join(config_path, "commands.yml")
|
16
|
+
FileUtils.cp(src, dest)
|
17
|
+
end
|
18
|
+
|
19
|
+
c.color_enabled = true
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe CTT::Cli::Command::Help do
|
5
|
+
|
6
|
+
it "list help command" do
|
7
|
+
args = "help abc def"
|
8
|
+
output = `./bin/orc #{args}`
|
9
|
+
keywords = ["help", "tests",
|
10
|
+
"add suite <Test Suite Path> [alias]"]
|
11
|
+
keywords.each do |w|
|
12
|
+
output.should include w
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: orc-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pin Xie
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-18 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json_pure
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.6.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: progressbar
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: terminal-table
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.4.2
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.2
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: paint
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.8.5
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.8.5
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: interact
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.4.8
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.4.8
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: libxml-ruby
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.3.3
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.3.3
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: uuidtools
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.1.3
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 2.1.3
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rest-client
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.6.7
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 1.6.7
|
142
|
+
description: Test automation client tool
|
143
|
+
email: pxie@vmware.com
|
144
|
+
executables:
|
145
|
+
- orc
|
146
|
+
extensions: []
|
147
|
+
extra_rdoc_files: []
|
148
|
+
files:
|
149
|
+
- bin/orc
|
150
|
+
- lib/cli.rb
|
151
|
+
- lib/cli/base.rb
|
152
|
+
- lib/cli/client_collector.rb
|
153
|
+
- lib/cli/cmd_consts.rb
|
154
|
+
- lib/cli/commands/help.rb
|
155
|
+
- lib/cli/commands/multiple_tests.rb
|
156
|
+
- lib/cli/commands/rerun.rb
|
157
|
+
- lib/cli/commands/suites_configure.rb
|
158
|
+
- lib/cli/commands/test_suite_management.rb
|
159
|
+
- lib/cli/configs.rb
|
160
|
+
- lib/cli/consts.rb
|
161
|
+
- lib/cli/ctt_extensions.rb
|
162
|
+
- lib/cli/errors.rb
|
163
|
+
- lib/cli/report.rb
|
164
|
+
- lib/cli/runner.rb
|
165
|
+
- lib/cli/suites.rb
|
166
|
+
- lib/cli/version.rb
|
167
|
+
- README.md
|
168
|
+
- Rakefile
|
169
|
+
- config/commands.yml
|
170
|
+
- spec/spec_helper.rb
|
171
|
+
- spec/unit/help_spec.rb
|
172
|
+
homepage: http://www.vmware.com
|
173
|
+
licenses: []
|
174
|
+
post_install_message:
|
175
|
+
rdoc_options: []
|
176
|
+
require_paths:
|
177
|
+
- lib
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
none: false
|
180
|
+
requirements:
|
181
|
+
- - ! '>='
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
requirements: []
|
191
|
+
rubyforge_project:
|
192
|
+
rubygems_version: 1.8.19
|
193
|
+
signing_key:
|
194
|
+
specification_version: 3
|
195
|
+
summary: ORC CLI
|
196
|
+
test_files:
|
197
|
+
- spec/spec_helper.rb
|
198
|
+
- spec/unit/help_spec.rb
|