rcomp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +39 -0
- data/LICENSE +7 -0
- data/README.md +124 -0
- data/Rakefile +7 -0
- data/bin/rcomp +6 -0
- data/contributing.md +7 -0
- data/features/generate.feature +224 -0
- data/features/init.feature +44 -0
- data/features/set_command.feature +24 -0
- data/features/set_directory.feature +22 -0
- data/features/support/env.rb +66 -0
- data/features/test.feature +169 -0
- data/features/version.feature +6 -0
- data/lib/rcomp/actions.rb +35 -0
- data/lib/rcomp/cli.rb +124 -0
- data/lib/rcomp/conf.rb +128 -0
- data/lib/rcomp/helper.rb +22 -0
- data/lib/rcomp/path.rb +28 -0
- data/lib/rcomp/reporter.rb +81 -0
- data/lib/rcomp/runner.rb +104 -0
- data/lib/rcomp/suite.rb +32 -0
- data/lib/rcomp/test.rb +27 -0
- data/lib/rcomp/version.rb +3 -0
- data/lib/rcomp.rb +9 -0
- data/rcomp.gemspec +29 -0
- metadata +147 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
Feature: Test
|
2
|
+
Users should have the ability to run tests
|
3
|
+
|
4
|
+
# faulty configuration
|
5
|
+
Scenario: Test without command
|
6
|
+
When I run `rcomp test`
|
7
|
+
Then the output should contain "No command present"
|
8
|
+
And the exit status should be 1
|
9
|
+
|
10
|
+
Scenario: Test without init
|
11
|
+
Given I run `rcomp c ./exec`
|
12
|
+
When I run `rcomp test`
|
13
|
+
Then the output should contain "No RComp directory"
|
14
|
+
And the exit status should be 1
|
15
|
+
|
16
|
+
Scenario: Test with partial init
|
17
|
+
Given I run `rcomp c ./exec`
|
18
|
+
And a directory named "rcomp"
|
19
|
+
And a directory named "rcomp/tests"
|
20
|
+
When I run `rcomp test`
|
21
|
+
Then the output should contain "Missing RComp directories"
|
22
|
+
And the exit status should be 1
|
23
|
+
|
24
|
+
# no tests
|
25
|
+
@basic-conf
|
26
|
+
Scenario: Test with no tests
|
27
|
+
When I run `rcomp test`
|
28
|
+
Then the output should contain "0 tests ()"
|
29
|
+
And the exit status should be 0
|
30
|
+
|
31
|
+
# stdout single test
|
32
|
+
@basic-conf
|
33
|
+
Scenario: Test with single test passing
|
34
|
+
Given a file named "rcomp/tests/test1.test" with:
|
35
|
+
"""
|
36
|
+
ABC
|
37
|
+
|
38
|
+
"""
|
39
|
+
And a file named "rcomp/expected/test1.out" with:
|
40
|
+
"""
|
41
|
+
ABC
|
42
|
+
|
43
|
+
"""
|
44
|
+
When I run `rcomp test`
|
45
|
+
Then the output should contain "1 test (1 passed)"
|
46
|
+
And the exit status should be 0
|
47
|
+
|
48
|
+
@basic-conf
|
49
|
+
Scenario: Test with single test skipped
|
50
|
+
Given a file named "rcomp/tests/test1.test" with:
|
51
|
+
"""
|
52
|
+
ABC
|
53
|
+
|
54
|
+
"""
|
55
|
+
When I run `rcomp test`
|
56
|
+
Then the output should contain "1 test (1 skipped)"
|
57
|
+
And the exit status should be 0
|
58
|
+
|
59
|
+
@basic-conf
|
60
|
+
Scenario: Test with single test failing
|
61
|
+
Given a file named "rcomp/tests/test1.test" with:
|
62
|
+
"""
|
63
|
+
ABC
|
64
|
+
|
65
|
+
"""
|
66
|
+
And a file named "rcomp/expected/test1.out" with:
|
67
|
+
"""
|
68
|
+
XYZ
|
69
|
+
|
70
|
+
"""
|
71
|
+
When I run `rcomp test`
|
72
|
+
Then the output should contain "1 test (1 failed)"
|
73
|
+
And the exit status should be 1
|
74
|
+
|
75
|
+
# stdout multiple tests
|
76
|
+
@basic-conf
|
77
|
+
@load-assorted-tests
|
78
|
+
Scenario: Test multiple
|
79
|
+
When I run `rcomp test`
|
80
|
+
Then the output should contain "3 tests (1 failed, 1 skipped, 1 passed)"
|
81
|
+
And the exit status should be 1
|
82
|
+
|
83
|
+
# stderr single test
|
84
|
+
@err-conf
|
85
|
+
Scenario: Test err with single test passing
|
86
|
+
Given a file named "rcomp/tests/test1.test" with:
|
87
|
+
"""
|
88
|
+
ABC
|
89
|
+
|
90
|
+
"""
|
91
|
+
And a file named "rcomp/expected/test1.err" with:
|
92
|
+
"""
|
93
|
+
ABC
|
94
|
+
|
95
|
+
"""
|
96
|
+
When I run `rcomp test`
|
97
|
+
Then the output should contain "1 test (1 passed)"
|
98
|
+
And the exit status should be 0
|
99
|
+
|
100
|
+
@err-conf
|
101
|
+
Scenario: Test err with single test failing
|
102
|
+
Given a file named "rcomp/tests/test1.test" with:
|
103
|
+
"""
|
104
|
+
ABC
|
105
|
+
|
106
|
+
"""
|
107
|
+
And a file named "rcomp/expected/test1.err" with:
|
108
|
+
"""
|
109
|
+
XYZ
|
110
|
+
|
111
|
+
"""
|
112
|
+
When I run `rcomp test`
|
113
|
+
Then the output should contain "1 test (1 failed)"
|
114
|
+
And the exit status should be 1
|
115
|
+
|
116
|
+
# stderr multiple tests
|
117
|
+
@err-conf
|
118
|
+
@load-assorted-err-tests
|
119
|
+
Scenario: Test multiple err: passing, skipped and failing
|
120
|
+
When I run `rcomp test`
|
121
|
+
Then the output should contain "3 tests (1 failed, 1 skipped, 1 passed)"
|
122
|
+
And the exit status should be 1
|
123
|
+
|
124
|
+
# alias
|
125
|
+
@basic-conf
|
126
|
+
@load-assorted-tests
|
127
|
+
Scenario: Test alias t
|
128
|
+
When I run `rcomp t`
|
129
|
+
Then the output should contain "3 tests (1 failed, 1 skipped, 1 passed)"
|
130
|
+
And the exit status should be 1
|
131
|
+
|
132
|
+
# filters
|
133
|
+
@basic-conf
|
134
|
+
@load-assorted-tests
|
135
|
+
Scenario: Test with filter: catches all
|
136
|
+
When I run `rcomp test --grep=test`
|
137
|
+
Then the output should contain "3 tests (1 failed, 1 skipped, 1 passed)"
|
138
|
+
And the exit status should be 1
|
139
|
+
|
140
|
+
@basic-conf
|
141
|
+
@load-assorted-tests
|
142
|
+
Scenario: Test with filter: catches some
|
143
|
+
When I run `rcomp t --grep=dir`
|
144
|
+
Then the output should contain "2 tests (1 failed, 1 skipped)"
|
145
|
+
And the exit status should be 1
|
146
|
+
|
147
|
+
@basic-conf
|
148
|
+
@load-assorted-tests
|
149
|
+
Scenario: Test with filter: catches none
|
150
|
+
When I run `rcomp t --grep=xyz`
|
151
|
+
Then the output should contain "0 tests ()"
|
152
|
+
And the exit status should be 0
|
153
|
+
|
154
|
+
# custom tests directory
|
155
|
+
@custom-conf
|
156
|
+
Scenario: Custom conf test
|
157
|
+
Given a file named "test/integration/rcomp/tests/test1.test" with:
|
158
|
+
"""
|
159
|
+
ABC
|
160
|
+
|
161
|
+
"""
|
162
|
+
And a file named "test/integration/rcomp/expected/test1.out" with:
|
163
|
+
"""
|
164
|
+
ABC
|
165
|
+
|
166
|
+
"""
|
167
|
+
When I run `rcomp test`
|
168
|
+
Then the output should contain "1 test (1 passed)"
|
169
|
+
And the exit status should be 0
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module RComp
|
4
|
+
module Actions
|
5
|
+
def rm_rf(directory)
|
6
|
+
if File.exist? directory
|
7
|
+
FileUtils.rm_rf directory
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def rm(file)
|
12
|
+
if File.exist? file
|
13
|
+
FileUtils.rm file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def mkdir(path)
|
18
|
+
unless File.exist? path
|
19
|
+
FileUtils.mkdir path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def mkpath_to(path)
|
24
|
+
unless File.exists? path
|
25
|
+
FileUtils.mkpath File.dirname(path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def touch(path)
|
30
|
+
unless File.exist? path
|
31
|
+
FileUtils.touch path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rcomp/cli.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module RComp
|
4
|
+
class CLI < Thor
|
5
|
+
|
6
|
+
include RComp::Actions
|
7
|
+
include RComp::Runner
|
8
|
+
include RComp::Suite
|
9
|
+
|
10
|
+
def initialize(args=[], options={}, config={})
|
11
|
+
super
|
12
|
+
# load Conf singleton
|
13
|
+
@conf = Conf.instance
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
## CLI Commands
|
18
|
+
##
|
19
|
+
|
20
|
+
# init
|
21
|
+
desc "init", "Setup rcomp test directory"
|
22
|
+
def init
|
23
|
+
if initialized?
|
24
|
+
puts "RComp already initialized"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
unless Dir.exists?(File.dirname(@conf.root))
|
29
|
+
puts "No directory #{File.dirname(@conf.root)}"
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
|
33
|
+
# Create RComp directories
|
34
|
+
mkdir @conf.root
|
35
|
+
mkdir @conf.test_root
|
36
|
+
mkdir @conf.expected_root
|
37
|
+
mkdir @conf.result_root
|
38
|
+
|
39
|
+
puts "RComp successfully initialized"
|
40
|
+
end
|
41
|
+
|
42
|
+
# version
|
43
|
+
desc "version", "Prints RComp's version information"
|
44
|
+
def version
|
45
|
+
puts "RComp version #{RComp::VERSION}"
|
46
|
+
end
|
47
|
+
map %w(-v --version) => :version
|
48
|
+
|
49
|
+
# set-command
|
50
|
+
desc "set_command COMMAND", "Sets the command RComp will run tests with"
|
51
|
+
def set_command(command)
|
52
|
+
@conf.set_conf_value("command", command)
|
53
|
+
end
|
54
|
+
map "c" => :set_command
|
55
|
+
|
56
|
+
# set-directory
|
57
|
+
desc "set_directory PATH", "Set the directory RComp will store files"
|
58
|
+
def set_directory(path)
|
59
|
+
@conf.set_conf_value("directory", path)
|
60
|
+
end
|
61
|
+
map "d" => :set_directory
|
62
|
+
|
63
|
+
# test
|
64
|
+
desc "test", "Run all tests"
|
65
|
+
method_option :grep,
|
66
|
+
:type => :string,
|
67
|
+
:desc => "Only test files that match pattern"
|
68
|
+
def test
|
69
|
+
@conf.require_basic_conf
|
70
|
+
if @options[:grep]
|
71
|
+
run_suite(load_suite(@options[:grep]), :test)
|
72
|
+
else
|
73
|
+
run_suite(load_suite, :test)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
map "t" => :test
|
77
|
+
|
78
|
+
# generate
|
79
|
+
desc "generate", "Generate expected output for all tests"
|
80
|
+
method_option :grep,
|
81
|
+
:type => :string,
|
82
|
+
:desc => "Only test files that match pattern"
|
83
|
+
method_option :overwrite,
|
84
|
+
:type => :boolean,
|
85
|
+
:default => false,
|
86
|
+
:aliases => "-O",
|
87
|
+
:desc => "Overwrite expected output file for test if present"
|
88
|
+
def generate
|
89
|
+
@conf.require_basic_conf
|
90
|
+
|
91
|
+
# Display confirmation dialouge when -O is passed without filter
|
92
|
+
if !@options[:grep] && options.overwrite
|
93
|
+
confirm_action "This will overwrite all existing expected results."
|
94
|
+
end
|
95
|
+
|
96
|
+
if @options[:grep]
|
97
|
+
run_suite(load_suite(@options[:grep]), :generate, @options)
|
98
|
+
else
|
99
|
+
run_suite(load_suite, :generate, @options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
map "g" => :generate
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def confirm_action(warning)
|
107
|
+
puts warning
|
108
|
+
print 'Are you sure? (Y/N) '
|
109
|
+
confirm = STDIN.gets.chomp
|
110
|
+
|
111
|
+
unless confirm.downcase == 'y'
|
112
|
+
say 'Aborting...'
|
113
|
+
exit 1
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def initialized?
|
118
|
+
File.exists?(@conf.root) &&
|
119
|
+
File.exists?(@conf.test_root) &&
|
120
|
+
File.exists?(@conf.result_root) &&
|
121
|
+
File.exists?(@conf.expected_root)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/rcomp/conf.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module RComp
|
5
|
+
class Conf
|
6
|
+
|
7
|
+
include Singleton
|
8
|
+
include RComp::Actions
|
9
|
+
|
10
|
+
attr_reader :root, :test_root, :result_root, :expected_root,
|
11
|
+
:command
|
12
|
+
|
13
|
+
# Initialize a new config object
|
14
|
+
#
|
15
|
+
# Loads options from config file, merges with defaults
|
16
|
+
# and stores everything in memory
|
17
|
+
def initialize
|
18
|
+
# Config file path
|
19
|
+
@path = '.rcomp'
|
20
|
+
|
21
|
+
# Set valid keys for config file
|
22
|
+
@valid_keys = ['directory',
|
23
|
+
'command']
|
24
|
+
|
25
|
+
# Set default options and overwrite with config file options
|
26
|
+
@default = { 'directory' => 'rcomp' }
|
27
|
+
@custom = read_conf_file
|
28
|
+
@conf = @default.merge(@custom)
|
29
|
+
|
30
|
+
# Load configuration values into attributes
|
31
|
+
@command = @conf['command']
|
32
|
+
@root = @conf['directory']
|
33
|
+
@test_root = @root + '/tests'
|
34
|
+
@result_root = @root + '/results'
|
35
|
+
@expected_root = @root + '/expected'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set a configuration value and write it to the config file
|
39
|
+
#
|
40
|
+
# Returns nothing
|
41
|
+
def set_conf_value(key, value)
|
42
|
+
@custom[key] = value
|
43
|
+
puts "#{key} set to #{value}"
|
44
|
+
write_conf_file
|
45
|
+
end
|
46
|
+
|
47
|
+
# Emit error unless all required conf keys are present in conf file
|
48
|
+
#
|
49
|
+
# Returns nothing
|
50
|
+
def require_basic_conf
|
51
|
+
require_command
|
52
|
+
require_root_exists
|
53
|
+
require_root_subdirs
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Write the current config options to the config file
|
60
|
+
#
|
61
|
+
# Returns nothing
|
62
|
+
def write_conf_file
|
63
|
+
exit 1 unless @path
|
64
|
+
touch @path unless File.exists?(@path)
|
65
|
+
conf_file = File.open(@path, 'w')
|
66
|
+
conf_file.puts YAML.dump @custom
|
67
|
+
end
|
68
|
+
|
69
|
+
# Read the config options from RComp's configuration file
|
70
|
+
#
|
71
|
+
# Returns a Hash of config options
|
72
|
+
def read_conf_file
|
73
|
+
conf = {}
|
74
|
+
|
75
|
+
if File.exists?(@path) && File.size?(@path)
|
76
|
+
|
77
|
+
# Store valid conf keys
|
78
|
+
YAML.load_file(@path).each do |key, value|
|
79
|
+
|
80
|
+
if @valid_keys.include? key
|
81
|
+
conf[key] = value
|
82
|
+
else
|
83
|
+
say "Invalid configuration key: #{key}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
conf
|
89
|
+
end
|
90
|
+
|
91
|
+
# Require the command config option to be set
|
92
|
+
# Print error and exit otherwise
|
93
|
+
#
|
94
|
+
# Returns nothing
|
95
|
+
def require_command
|
96
|
+
unless @command
|
97
|
+
puts "No command present"
|
98
|
+
puts "Run rcomp c COMMAND to add a command to test with"
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Require the existance of the root directory
|
104
|
+
# Print error and exit otherwise
|
105
|
+
#
|
106
|
+
# Returns nothing
|
107
|
+
def require_root_exists
|
108
|
+
unless File.exists? @root
|
109
|
+
puts "No RComp directory. Run rcomp init to create"
|
110
|
+
exit 1
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Require all sudirectories of the root directory to exist
|
115
|
+
# Print error and exit otherwise
|
116
|
+
#
|
117
|
+
# Returns nothing
|
118
|
+
def require_root_subdirs
|
119
|
+
unless File.exists?(@test_root) &&
|
120
|
+
File.exists?(@result_root) &&
|
121
|
+
File.exists?(@expected_root)
|
122
|
+
puts "Missing RComp directories at #{@root}"
|
123
|
+
puts "Run rcomp init to repair"
|
124
|
+
exit 1
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/rcomp/helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module RComp
|
2
|
+
module Helper
|
3
|
+
|
4
|
+
##
|
5
|
+
# Pluralizes a number / phrase pair
|
6
|
+
#
|
7
|
+
# ex:
|
8
|
+
# plural(1, noun) # '1 noun'
|
9
|
+
# plural(3, noun) # '3 nouns'
|
10
|
+
# plural(3, geese, geese) # '3 geese'
|
11
|
+
|
12
|
+
def plural(n, singular, plural=nil)
|
13
|
+
if n == 1
|
14
|
+
"1 #{singular}"
|
15
|
+
elsif plural
|
16
|
+
"#{n} #{plural}"
|
17
|
+
else
|
18
|
+
"#{n} #{singular}s"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/rcomp/path.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module RComp
|
2
|
+
module Path
|
3
|
+
def rel_path(test_path)
|
4
|
+
test_path.gsub(Conf.instance.test_root, '')
|
5
|
+
end
|
6
|
+
|
7
|
+
def result_path(test_path, type)
|
8
|
+
cmpnts = []
|
9
|
+
cmpnts << Conf.instance.result_root
|
10
|
+
cmpnts << rel_path(File.dirname(test_path))
|
11
|
+
cmpnts << File.basename(test_path, ".*") + (type == :out ? '.out' : '.err')
|
12
|
+
File.join(cmpnts)
|
13
|
+
end
|
14
|
+
|
15
|
+
def expected_path(test_path, type)
|
16
|
+
puts Conf.instance.expected_root
|
17
|
+
puts rel_path(File.dirname(test_path))
|
18
|
+
puts File.basename(test_path, ".*") + (type == :out ? '.out' : '.err')
|
19
|
+
|
20
|
+
cmpnts = []
|
21
|
+
cmpnts << Conf.instance.expected_root
|
22
|
+
cmpnts << rel_path(File.dirname(test_path))
|
23
|
+
cmpnts << File.basename(test_path, ".*") + (type == :out ? '.out' : '.err')
|
24
|
+
puts File.join(cmpnts)
|
25
|
+
File.join(cmpnts)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module RComp
|
2
|
+
class Reporter
|
3
|
+
|
4
|
+
include RComp::Helper
|
5
|
+
|
6
|
+
# Initialize a new Reporter
|
7
|
+
#
|
8
|
+
# type - The type (Symbol) of the suite
|
9
|
+
#
|
10
|
+
# Initialize counters for all result types
|
11
|
+
def initialize(type)
|
12
|
+
@type = type
|
13
|
+
@success = 0
|
14
|
+
@skipped = 0
|
15
|
+
@failed = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def report(test)
|
19
|
+
case test.result
|
20
|
+
# success
|
21
|
+
when :success
|
22
|
+
case @type
|
23
|
+
when :test
|
24
|
+
puts "\t passed : #{test.relative_path}"
|
25
|
+
when :generate
|
26
|
+
puts "\tgenerated : #{test.relative_path}"
|
27
|
+
end
|
28
|
+
@success += 1
|
29
|
+
|
30
|
+
# skipped
|
31
|
+
when :skipped
|
32
|
+
case @type
|
33
|
+
when :test
|
34
|
+
puts "\tskipped : #{test.relative_path}"
|
35
|
+
when :generate
|
36
|
+
puts "\t skipped : #{test.relative_path}"
|
37
|
+
end
|
38
|
+
@skipped += 1
|
39
|
+
|
40
|
+
# failed
|
41
|
+
when :failed
|
42
|
+
case @type
|
43
|
+
when :test
|
44
|
+
puts "\t failed : #{test.relative_path}"
|
45
|
+
end
|
46
|
+
@failed += 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def summary
|
51
|
+
case @type
|
52
|
+
when :test
|
53
|
+
print_test_summary
|
54
|
+
when :generate
|
55
|
+
print_generate_summary
|
56
|
+
end
|
57
|
+
exit 1 if @failed > 0
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def print_test_summary
|
63
|
+
desc = []
|
64
|
+
summary = "#{plural((@failed + @skipped + @success), 'test')} ("
|
65
|
+
desc << "#{@failed} failed" unless @failed == 0
|
66
|
+
desc << "#{@skipped} skipped" unless @skipped == 0
|
67
|
+
desc << "#{@success} passed" unless @success == 0
|
68
|
+
summary += desc.join(", ") + ")"
|
69
|
+
puts summary
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_generate_summary
|
73
|
+
desc = []
|
74
|
+
summary = "#{plural((@skipped + @success), 'file')} ("
|
75
|
+
desc << "#{@skipped} skipped" unless @skipped == 0
|
76
|
+
desc << "#{@success} generated" unless @success == 0
|
77
|
+
summary += desc.join(", ") + ")"
|
78
|
+
puts summary
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/rcomp/runner.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module RComp
|
4
|
+
module Runner
|
5
|
+
|
6
|
+
include RComp::Actions
|
7
|
+
|
8
|
+
# Run a suite of tests
|
9
|
+
#
|
10
|
+
# suite - An Array of Test objects
|
11
|
+
# type - The type (Symbol) of the suite
|
12
|
+
# options - A Hash of runner options
|
13
|
+
#
|
14
|
+
# Returns nothing
|
15
|
+
def run_suite(suite, type, options={})
|
16
|
+
@conf = Conf.instance
|
17
|
+
reporter = Reporter.new(type)
|
18
|
+
|
19
|
+
suite.each do |test|
|
20
|
+
case type
|
21
|
+
when :test
|
22
|
+
if expected_exists?(test)
|
23
|
+
run_test(test)
|
24
|
+
end
|
25
|
+
|
26
|
+
when :generate
|
27
|
+
if expected_exists?(test)
|
28
|
+
run_generate(test) if options[:overwrite]
|
29
|
+
else
|
30
|
+
run_generate(test)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
reporter.report(test)
|
35
|
+
end
|
36
|
+
|
37
|
+
reporter.summary
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Check the existance of expected out/err for a test
|
44
|
+
#
|
45
|
+
# test - A Test object
|
46
|
+
#
|
47
|
+
# Returns a boolean
|
48
|
+
def expected_exists?(test)
|
49
|
+
File.exists?(test.expected_out_path) ||
|
50
|
+
File.exists?(test.expected_err_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Run a test storing it's result out and err
|
54
|
+
#
|
55
|
+
# test - A Test object
|
56
|
+
#
|
57
|
+
# Returns nothing
|
58
|
+
def run_test(test)
|
59
|
+
mkpath_to test.result_out_path
|
60
|
+
mkpath_to test.result_err_path
|
61
|
+
system "#{@conf.command} #{test.test_path} > #{test.result_out_path} 2> #{test.result_err_path}"
|
62
|
+
test.result = compare_output(test)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generate expected output for a test
|
66
|
+
#
|
67
|
+
# test - A Test object
|
68
|
+
#
|
69
|
+
# Returns nothing
|
70
|
+
def run_generate(test)
|
71
|
+
mkpath_to test.expected_out_path
|
72
|
+
mkpath_to test.expected_err_path
|
73
|
+
system "#{@conf.command} #{test.test_path} > #{test.expected_out_path} 2> #{test.expected_err_path}"
|
74
|
+
test.result = :success
|
75
|
+
end
|
76
|
+
|
77
|
+
# Compare the result and expected output of a test that has been run
|
78
|
+
#
|
79
|
+
# test - A Test object that has been run
|
80
|
+
# precondition: expected_exists?(test) is true
|
81
|
+
#
|
82
|
+
# Returns a Symbol, :success or :failure, conditionally if the test passed
|
83
|
+
def compare_output(test)
|
84
|
+
exp_out_exists = File.exists?(test.expected_out_path)
|
85
|
+
exp_err_exists = File.exists?(test.expected_err_path)
|
86
|
+
|
87
|
+
if exp_out_exists && exp_err_exists # test out and err
|
88
|
+
if FileUtils.identical?(test.expected_out_path, test.result_out_path) &&
|
89
|
+
FileUtils.identical?(test.expected_err_path, test.result_err_path)
|
90
|
+
return :success
|
91
|
+
end
|
92
|
+
elsif exp_out_exists # test only out
|
93
|
+
if FileUtils.identical?(test.expected_out_path, test.result_out_path)
|
94
|
+
return :success
|
95
|
+
end
|
96
|
+
else # test only err
|
97
|
+
if FileUtils.identical?(test.expected_err_path, test.result_err_path)
|
98
|
+
return :success
|
99
|
+
end
|
100
|
+
end
|
101
|
+
return :failed
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|