rcomp 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/.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
|