dtf 0.2.1
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/LICENSE +13 -0
- data/README.md +66 -0
- data/bin/dtf +7 -0
- data/lib/dtf.rb +94 -0
- data/lib/dtf/active_patches.rb +21 -0
- data/lib/dtf/plugins.rb +102 -0
- data/lib/plugins/dtf/comment_test_input.rb +40 -0
- data/lib/plugins/dtf/env_match_test.rb +18 -0
- data/lib/plugins/dtf/error_summary_output.rb +93 -0
- data/lib/plugins/dtf/output_match_test.rb +17 -0
- data/lib/plugins/dtf/stats_output.rb +73 -0
- data/lib/plugins/dtf/status_test.rb +17 -0
- data/lib/plugins/dtf/text_output.rb +52 -0
- metadata +92 -0
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2011 Michal Papis
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Deryls Testing Framework
|
2
|
+
|
3
|
+
DTF is a pluggable framework for testing shell scripts (at least now).
|
4
|
+
DTF also is an umbrella which incorporates (eventually) multiple gems, each of which provides additional functionality
|
5
|
+
to DTF. DTF is the skeleton upon which all other dtf-* gems build.
|
6
|
+
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
$ gem install dtf
|
11
|
+
$ dtf <path/to/file>_comment_test.sh
|
12
|
+
|
13
|
+
## Comment tests
|
14
|
+
|
15
|
+
Filename has to end with _comment_test.sh
|
16
|
+
|
17
|
+
Example test file:
|
18
|
+
|
19
|
+
## User comments start with double #
|
20
|
+
## command can be writen in one line with multiple tests:
|
21
|
+
true # status=0; match=/^$/
|
22
|
+
## or tests can be placed in following lines:
|
23
|
+
false
|
24
|
+
# status=1
|
25
|
+
|
26
|
+
### Matchers
|
27
|
+
|
28
|
+
The test can be negated by replacing `=` with `!=`
|
29
|
+
|
30
|
+
- status=<number> - check if command returned given status (0 is success)
|
31
|
+
- match=/<regexp>/ - regexp match command output
|
32
|
+
- env[<var_name>]=/<regexp>/ - regexp match the given environment variable name
|
33
|
+
|
34
|
+
## Example
|
35
|
+
|
36
|
+
$ bin/dtf example_tests/comment/*
|
37
|
+
F..
|
38
|
+
##### Processed commands 2 of 2, success tests 2 of 3, failure tests 1 of 3.
|
39
|
+
$ false
|
40
|
+
# failed: status = 0 # was 1
|
41
|
+
|
42
|
+
$ bin/dtf example_tests/comment/* --text
|
43
|
+
##### starting test failure.
|
44
|
+
$ false
|
45
|
+
# failed: status = 0 # was 1
|
46
|
+
##### starting test success.
|
47
|
+
$ true
|
48
|
+
# passed: status = 0
|
49
|
+
# passed: status != 1
|
50
|
+
##### Processed commands 2 of 2, success tests 2 of 3, failure tests 1 of 3.
|
51
|
+
|
52
|
+
## Internal architecture
|
53
|
+
|
54
|
+
Framework will load plugins from any available gem and local `lib/` path, for example:
|
55
|
+
|
56
|
+
lib/plugins/dtf/text_output.rb
|
57
|
+
lib/plugins/dtf/status_test.rb
|
58
|
+
lib/plugins/dtf/comment_test_input.rb
|
59
|
+
|
60
|
+
The search pattern is:
|
61
|
+
|
62
|
+
lib/plugins/dtf/*.rb
|
63
|
+
|
64
|
+
And plugins are selected with:
|
65
|
+
|
66
|
+
lib/plugins/dtf/*_{input,test,output}.rb
|
data/bin/dtf
ADDED
data/lib/dtf.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'singleton'
|
3
|
+
require 'yaml'
|
4
|
+
require 'session'
|
5
|
+
|
6
|
+
lib_root = File.dirname( __FILE__ )
|
7
|
+
|
8
|
+
# include lib in path so plugins get found with Gem.find_files
|
9
|
+
$:.unshift "#{lib_root}"
|
10
|
+
|
11
|
+
class DTF; end
|
12
|
+
# load dtf/*.rb
|
13
|
+
Dir["#{lib_root}/dtf/*.rb"].each{|lib| require lib }
|
14
|
+
|
15
|
+
class DTF
|
16
|
+
def initialize
|
17
|
+
@ruby = File.join(RbConfig::CONFIG["bindir"],RbConfig::CONFIG["ruby_install_name"])
|
18
|
+
@plugins = DTF::Plugins.instance
|
19
|
+
@failures = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_tests args
|
23
|
+
@plugins.load(%w( all_test ))
|
24
|
+
input_files, not_processed = @plugins.parse_args(args)
|
25
|
+
if not_processed.size > 0
|
26
|
+
$stderr.puts "No plugin recognized this option '#{not_processed*" "}'."
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
@plugins.load(%w( ErrorSummaryOutput )) if @plugins.output_plugins.empty?
|
30
|
+
process(input_files)
|
31
|
+
@failures == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def process input_files
|
35
|
+
@plugins.output_plugins(:start_processing)
|
36
|
+
input_files.each do |plugin,file|
|
37
|
+
process_test( plugin.load(file) )
|
38
|
+
end
|
39
|
+
@plugins.output_plugins(:end_processing)
|
40
|
+
end
|
41
|
+
|
42
|
+
def env shell
|
43
|
+
Hash[ shell.execute(
|
44
|
+
@ruby + ' -e \'ENV.each{|k,v| printf "#{k}=#{v}\0"}\''
|
45
|
+
)[0].split("\0").map{|var| var.split('=', 2) } ]
|
46
|
+
end
|
47
|
+
|
48
|
+
def process_test test
|
49
|
+
name, commands = test[:name], test[:commands]
|
50
|
+
shell = Session::Bash.new
|
51
|
+
_env = env(shell)
|
52
|
+
@plugins.output_plugins(:start_test, test, _env)
|
53
|
+
commands.each do |line|
|
54
|
+
command, tests = line[:cmd], line[:tests]
|
55
|
+
@plugins.output_plugins(:start_command, line)
|
56
|
+
_stdout = StringIO.new
|
57
|
+
_stderr = StringIO.new
|
58
|
+
_stdboth = StringIO.new
|
59
|
+
shell.execute "#{command}" do |out, err|
|
60
|
+
if out
|
61
|
+
@plugins.output_plugins(:command_out, out)
|
62
|
+
_stdout << out
|
63
|
+
_stdboth << out
|
64
|
+
end
|
65
|
+
if err
|
66
|
+
@plugins.output_plugins(:command_err, err)
|
67
|
+
_stderr << err
|
68
|
+
_stdboth << err
|
69
|
+
end
|
70
|
+
end
|
71
|
+
_status = shell.status
|
72
|
+
_env = env(shell)
|
73
|
+
@plugins.output_plugins(:end_command, line, _status, _env)
|
74
|
+
process_command_tests _stdout.string, _stderr.string, _stdboth.string, _status, _env, tests
|
75
|
+
end
|
76
|
+
@plugins.output_plugins(:end_test, test)
|
77
|
+
end
|
78
|
+
|
79
|
+
def process_command_tests _stdout, _stderr, _stdboth, _status, env, tests
|
80
|
+
tests.each do |test|
|
81
|
+
plugin = @plugins.test_plugins.find{|_plugin| _plugin.matches? test }
|
82
|
+
if plugin.nil?
|
83
|
+
status, msg = false, "Could not find plugin for test '#{test}'."
|
84
|
+
else
|
85
|
+
status, msg = plugin.execute(test, _stdout, _stderr, _stdboth, _status, env)
|
86
|
+
end
|
87
|
+
@failures+=1 unless status
|
88
|
+
@plugins.output_plugins(:test_processed, test, status, msg)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class << self
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
unless String.method_defined? :blank?
|
2
|
+
String.class_eval do
|
3
|
+
def blank?
|
4
|
+
self == ""
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
unless Array.method_defined? :blank?
|
9
|
+
Array.class_eval do
|
10
|
+
def blank?
|
11
|
+
size == 0
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
unless NilClass.method_defined? :blank?
|
16
|
+
NilClass.class_eval do
|
17
|
+
def blank?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/dtf/plugins.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
class DTF::Plugins
|
2
|
+
include Singleton
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
detect
|
6
|
+
@additional_plugins = []
|
7
|
+
@input_plugins = []
|
8
|
+
@output_plugins = []
|
9
|
+
@test_plugins = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def detect
|
13
|
+
@plugins = Gem.find_files('plugins/dtf/*.rb')
|
14
|
+
end
|
15
|
+
|
16
|
+
def add plugin
|
17
|
+
@additional_plugins << plugin
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete plugin
|
21
|
+
@additional_plugins.delete plugin
|
22
|
+
end
|
23
|
+
|
24
|
+
def file_to_class item
|
25
|
+
File.basename(item,'.rb').capitalize.gsub(/_(.)/){ $1.upcase }
|
26
|
+
end
|
27
|
+
|
28
|
+
def list pattern=nil
|
29
|
+
# collect to lists
|
30
|
+
_list = @plugins + @additional_plugins
|
31
|
+
# filter by pattern if given
|
32
|
+
_list = _list.select{|item| item.match("_#{pattern}.rb$") } unless pattern.nil?
|
33
|
+
# get path and class name
|
34
|
+
_list.map!{|item| [ item, file_to_class(item), pattern ] }
|
35
|
+
# TODO: limit plugin versions (highest || use bundler)
|
36
|
+
_list.each{|item, klass, type| require item }
|
37
|
+
_list
|
38
|
+
end
|
39
|
+
|
40
|
+
def load wanted
|
41
|
+
[ :input, :test, :output ].each do |type|
|
42
|
+
_list = list(type)
|
43
|
+
if ! wanted.include?("all") && ! wanted.include?("all_#{type}")
|
44
|
+
_list = _list.select{|item, klass, _type| wanted.include?(klass) }
|
45
|
+
end
|
46
|
+
_list.each{|item, klass, _type|
|
47
|
+
klass = DTF.const_get(klass)
|
48
|
+
instance_variable_get("@#{type}_plugins".to_sym) << klass.new
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def match_arg_klass arg, klass, type
|
54
|
+
klass = DTF.const_get(klass)
|
55
|
+
return nil unless klass.respond_to? :argument_matches?
|
56
|
+
matches = klass.argument_matches? arg
|
57
|
+
return nil if matches.nil?
|
58
|
+
matches.each do |match|
|
59
|
+
case match
|
60
|
+
when :load
|
61
|
+
instance_variable_get("@#{type}_plugins".to_sym) << klass.new
|
62
|
+
when :input
|
63
|
+
@input_files << [klass.new, arg]
|
64
|
+
else
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
return matches
|
69
|
+
rescue NameError
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_args args
|
74
|
+
@input_files, not_processed = [], []
|
75
|
+
available_plugins = [ :input, :test, :output ].map{ |type| list(type) }.flatten(1)
|
76
|
+
args.each do |arg|
|
77
|
+
matched = available_plugins.map do |item, klass, type|
|
78
|
+
match_arg_klass arg, klass, type
|
79
|
+
end.flatten.reject(&:nil?)
|
80
|
+
if matched.empty?
|
81
|
+
not_processed << arg
|
82
|
+
end
|
83
|
+
end
|
84
|
+
[ @input_files, not_processed ]
|
85
|
+
end
|
86
|
+
|
87
|
+
def input_plugins
|
88
|
+
@input_plugins
|
89
|
+
end
|
90
|
+
|
91
|
+
def output_plugins *args
|
92
|
+
if args.empty?
|
93
|
+
@output_plugins
|
94
|
+
else
|
95
|
+
@output_plugins.each{|plugin| plugin.send(*args) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_plugins
|
100
|
+
@test_plugins
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class DTF::CommentTestInput
|
2
|
+
def initialize
|
3
|
+
end
|
4
|
+
|
5
|
+
def self.argument_matches? argument
|
6
|
+
if argument =~ /_comment_test\.sh$/ && File.exist?(argument)
|
7
|
+
[:load, :input]
|
8
|
+
else
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def load file_name
|
14
|
+
lines = []
|
15
|
+
File.readlines(file_name).each{|line|
|
16
|
+
# Fix jruby-1.6.6-d19 bug with empty strings from files
|
17
|
+
line = "#{line}"
|
18
|
+
# remove human comments
|
19
|
+
line.sub!(/##.*$/,'')
|
20
|
+
# reject empty lines
|
21
|
+
line.strip!
|
22
|
+
next if line =~ /^$/
|
23
|
+
# extract command and tests
|
24
|
+
cmd, tests = line.split("#")
|
25
|
+
cmd.strip!
|
26
|
+
tests = if tests.blank?
|
27
|
+
[]
|
28
|
+
else
|
29
|
+
tests.split(";").map(&:strip)
|
30
|
+
end
|
31
|
+
if cmd.blank?
|
32
|
+
lines.last[:tests] += tests unless lines.last.nil?
|
33
|
+
else
|
34
|
+
lines << { :cmd => cmd, :tests => tests }
|
35
|
+
end
|
36
|
+
}
|
37
|
+
name = file_name.gsub(/^.*\//,'').sub(/_comment_test\.sh$/,'')
|
38
|
+
{ :name => name, :commands => lines }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class DTF::EnvMatchTest
|
2
|
+
MATCHER = /^env\[(.*)\]([!]?=)[~]?\/(.*)\//
|
3
|
+
|
4
|
+
def matches? test
|
5
|
+
test =~ DTF::EnvMatchTest::MATCHER
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute test, _stdout, _stderr, _stdboth, _status, env
|
9
|
+
test =~ DTF::EnvMatchTest::MATCHER
|
10
|
+
variable, sign, value = $1.strip, $2, $3
|
11
|
+
var_val = env[ variable ]
|
12
|
+
if ( sign == "=" ) ^ ( Regexp.new(value) =~ "#{var_val}" )
|
13
|
+
[ false, "failed: env #{variable} #{sign} /#{value}/ # was '#{var_val}'" ]
|
14
|
+
else
|
15
|
+
[ true, "passed: env #{variable} #{sign} /#{value}/" ]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class DTF::ErrorSummaryOutput
|
2
|
+
RED = `tput setaf 1`
|
3
|
+
GREEN = `tput setaf 2`
|
4
|
+
YELLOW = `tput setaf 3`
|
5
|
+
BLUE = `tput setaf 4`
|
6
|
+
RESET = `tput setaf 9`
|
7
|
+
|
8
|
+
def self.argument_matches? argument
|
9
|
+
[:load] if argument == "--dotted"
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize output=nil
|
13
|
+
@counts={}
|
14
|
+
@counts[:commands] = 0
|
15
|
+
@counts[:tests] = 0
|
16
|
+
@counts[:commands_started] = 0
|
17
|
+
@counts[:commands_finished] = 0
|
18
|
+
@counts[:tests_success] = 0
|
19
|
+
@counts[:tests_failure] = 0
|
20
|
+
@counter_id = 0
|
21
|
+
@summary = {}
|
22
|
+
@output = output || $stdout
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_processing
|
26
|
+
end
|
27
|
+
|
28
|
+
def status
|
29
|
+
text = "#{BLUE}##### Processed commands #{@counts[:commands_finished]} of #{@counts[:commands]}"
|
30
|
+
if @counts[:tests_success] > 0
|
31
|
+
text += ", #{GREEN}success tests #{@counts[:tests_success]} of #{@counts[:tests]}"
|
32
|
+
end
|
33
|
+
if @counts[:tests_failure] > 0
|
34
|
+
text += ", #{RED}failure tests #{@counts[:tests_failure]} of #{@counts[:tests]}"
|
35
|
+
end
|
36
|
+
skipped = @counts[:tests] - @counts[:tests_success] - @counts[:tests_failure]
|
37
|
+
if skipped > 0
|
38
|
+
text += ", #{YELLOW}skipped tests #{skipped} of #{@counts[:tests]}"
|
39
|
+
end
|
40
|
+
text += ".#{RESET}"
|
41
|
+
text
|
42
|
+
end
|
43
|
+
|
44
|
+
def summary
|
45
|
+
@summary.sort{|a,b| ak,_=a ; bk,_=b ; ak <=> bk }.each{|k,v|
|
46
|
+
@output.puts "#{YELLOW}$ #{v[:cmd]}#{RESET}"
|
47
|
+
v[:failed_tests].each{|t| puts "#{RED}# #{t}#{RESET}" }
|
48
|
+
}
|
49
|
+
text = ""
|
50
|
+
text
|
51
|
+
end
|
52
|
+
|
53
|
+
def end_processing
|
54
|
+
@output.printf "\n"
|
55
|
+
@output.puts status
|
56
|
+
@output.puts summary
|
57
|
+
end
|
58
|
+
|
59
|
+
def start_test test, env
|
60
|
+
@counts[:commands] += test[:commands].size
|
61
|
+
tests_counts = test[:commands].map{|line| line[:tests].nil? ? 0 : line[:tests].size }
|
62
|
+
@counts[:tests] += tests_counts.empty? ? 0 : tests_counts.inject(&:+)
|
63
|
+
end
|
64
|
+
|
65
|
+
def end_test test
|
66
|
+
end
|
67
|
+
|
68
|
+
def start_command line
|
69
|
+
@counts[:commands_started] += 1
|
70
|
+
@current_line = line.merge(:counter_id => @counts[:commands_started])
|
71
|
+
end
|
72
|
+
|
73
|
+
def end_command line, status, env
|
74
|
+
@counts[:commands_finished] += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
def command_out out
|
78
|
+
end
|
79
|
+
|
80
|
+
def command_err err
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_processed test, status, msg
|
84
|
+
@output.printf status ? "." : "F"
|
85
|
+
if status
|
86
|
+
@counts[:tests_success] += 1
|
87
|
+
else
|
88
|
+
@counts[:tests_failure] += 1
|
89
|
+
@summary[@current_line[:counter_id]] ||= @current_line.merge({:failed_tests=>[]})
|
90
|
+
@summary[@current_line[:counter_id]][:failed_tests] << msg
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class DTF::OutputMatchTest
|
2
|
+
MATCHER = /^match([!]?=)[~]?\/(.*)\//
|
3
|
+
|
4
|
+
def matches? test
|
5
|
+
test =~ DTF::OutputMatchTest::MATCHER
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute test, _stdout, _stderr, _stdboth, _status, env
|
9
|
+
test =~ DTF::OutputMatchTest::MATCHER
|
10
|
+
sign, value = $1, $2
|
11
|
+
if ( sign == "=" ) ^ ( Regexp.new(value) =~ "#{_stdboth}" )
|
12
|
+
[ false, "failed: match #{sign} /#{value}/" ]
|
13
|
+
else
|
14
|
+
[ true, "passed: match #{sign} /#{value}/" ]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class DTF::StatsOutput
|
2
|
+
RED = `tput setaf 1`
|
3
|
+
GREEN = `tput setaf 2`
|
4
|
+
YELLOW = `tput setaf 3`
|
5
|
+
BLUE = `tput setaf 4`
|
6
|
+
RESET = `tput setaf 9`
|
7
|
+
|
8
|
+
def self.argument_matches? argument
|
9
|
+
[:load] if argument == "--text"
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@counts={}
|
14
|
+
@counts[:commands] = 0
|
15
|
+
@counts[:tests] = 0
|
16
|
+
@counts[:commands_finished] = 0
|
17
|
+
@counts[:tests_success] = 0
|
18
|
+
@counts[:tests_failure] = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_processing
|
22
|
+
end
|
23
|
+
|
24
|
+
def status
|
25
|
+
text = "#{BLUE}##### Processed commands #{@counts[:commands_finished]} of #{@counts[:commands]}"
|
26
|
+
if @counts[:tests_success] > 0
|
27
|
+
text += ", #{GREEN}success tests #{@counts[:tests_success]} of #{@counts[:tests]}"
|
28
|
+
end
|
29
|
+
if @counts[:tests_failure] > 0
|
30
|
+
text += ", #{RED}failure tests #{@counts[:tests_failure]} of #{@counts[:tests]}"
|
31
|
+
end
|
32
|
+
skipped = @counts[:tests] - @counts[:tests_success] - @counts[:tests_failure]
|
33
|
+
if skipped > 0
|
34
|
+
text += ", #{YELLOW}skipped tests #{skipped} of #{@counts[:tests]}"
|
35
|
+
end
|
36
|
+
text += ".#{RESET}"
|
37
|
+
text
|
38
|
+
end
|
39
|
+
|
40
|
+
def end_processing
|
41
|
+
puts status
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_test test, env
|
45
|
+
@counts[:commands] += test[:commands].size
|
46
|
+
tests_counts = test[:commands].map{|line| line[:tests].nil? ? 0 : line[:tests].size }
|
47
|
+
@counts[:tests] += tests_counts.empty? ? 0 : tests_counts.inject(&:+)
|
48
|
+
end
|
49
|
+
|
50
|
+
def end_test test
|
51
|
+
end
|
52
|
+
|
53
|
+
def start_command line
|
54
|
+
end
|
55
|
+
|
56
|
+
def end_command line, status, env
|
57
|
+
@counts[:commands_finished] += 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def command_out out
|
61
|
+
end
|
62
|
+
|
63
|
+
def command_err err
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_processed test, status, msg
|
67
|
+
if status
|
68
|
+
@counts[:tests_success] += 1
|
69
|
+
else
|
70
|
+
@counts[:tests_failure] += 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class DTF::StatusTest
|
2
|
+
MATCHER = /^status([!]?=)([[:digit:]]+)$/
|
3
|
+
|
4
|
+
def matches? test
|
5
|
+
test =~ DTF::StatusTest::MATCHER
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute test, _stdout, _stderr, _stdboth, _status, env
|
9
|
+
test =~ DTF::StatusTest::MATCHER
|
10
|
+
sign, value = $1, $2.to_i
|
11
|
+
if ( sign == "=" ) ^ ( _status == value )
|
12
|
+
[ false, "failed: status #{sign} #{value} # was #{_status}" ]
|
13
|
+
else
|
14
|
+
[ true, "passed: status #{sign} #{value}" ]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class DTF::TextOutput
|
2
|
+
RED = `tput setaf 1`
|
3
|
+
GREEN = `tput setaf 2`
|
4
|
+
YELLOW = `tput setaf 3`
|
5
|
+
BLUE = `tput setaf 4`
|
6
|
+
RESET = `tput setaf 9`
|
7
|
+
|
8
|
+
def self.argument_matches? argument
|
9
|
+
[:load] if argument == "--text"
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_processing
|
16
|
+
end
|
17
|
+
|
18
|
+
def end_processing
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_test test, env
|
22
|
+
puts "#{BLUE}##### starting test #{test[:name]}.#{RESET}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_test test
|
26
|
+
#puts "#{BLUE}##### finished test #{test[:name]}.#{RESET}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def start_command line
|
30
|
+
puts "#{YELLOW}$ #{line[:cmd]}#{RESET}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_command line, status, env
|
34
|
+
#puts ": $?=#{status}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def command_out out
|
38
|
+
puts out
|
39
|
+
end
|
40
|
+
|
41
|
+
def command_err err
|
42
|
+
puts err
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_processed test, status, msg
|
46
|
+
if status
|
47
|
+
puts "#{GREEN}# #{msg}#{RESET}"
|
48
|
+
else
|
49
|
+
puts "#{RED}# #{msg}#{RESET}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dtf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Deryl R. Doucette
|
14
|
+
- Michal Papis
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2012-05-08 00:00:00 Z
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: session
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: Testing Framework solely based on plugins. For now only tests using Bash.
|
37
|
+
email: mpapis+dtf@gmail.com
|
38
|
+
executables:
|
39
|
+
- dtf
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- lib/dtf.rb
|
46
|
+
- lib/dtf/active_patches.rb
|
47
|
+
- lib/dtf/plugins.rb
|
48
|
+
- lib/plugins/dtf/output_match_test.rb
|
49
|
+
- lib/plugins/dtf/error_summary_output.rb
|
50
|
+
- lib/plugins/dtf/stats_output.rb
|
51
|
+
- lib/plugins/dtf/text_output.rb
|
52
|
+
- lib/plugins/dtf/status_test.rb
|
53
|
+
- lib/plugins/dtf/env_match_test.rb
|
54
|
+
- lib/plugins/dtf/comment_test_input.rb
|
55
|
+
- bin/dtf
|
56
|
+
- LICENSE
|
57
|
+
- README.md
|
58
|
+
homepage: http://github.com/dtf-gems/dtf
|
59
|
+
licenses: []
|
60
|
+
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 3
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.8.23
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Deryl Testing Framework
|
91
|
+
test_files: []
|
92
|
+
|