turn 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,98 @@
1
+ module Turn
2
+
3
+ #
4
+ class TestCase
5
+
6
+ # Name of test case.
7
+ attr_accessor :name
8
+
9
+ # Test methods.
10
+ attr_accessor :tests
11
+
12
+ # Some runners marshal tests per file.
13
+ attr_accessor :files
14
+
15
+ #attr_accessor :count_passes
16
+ #attr_accessor :count_failures
17
+ #attr_accessor :count_errors
18
+ #attr_accessor :count_tests
19
+
20
+ # This can;t be calculated, so it must be
21
+ # assigned by the runner.
22
+ attr_accessor :count_assertions
23
+
24
+ # Holds dump of test output (optional depending on runner).
25
+ attr_accessor :message
26
+
27
+ # Command used to run test (optional depending on runner).
28
+ #attr_accessor :command
29
+
30
+ #
31
+ def initialize(name, *files)
32
+ @name = name
33
+ @files = (files.empty? ? [name] : files)
34
+ @tests = []
35
+
36
+ @message = nil
37
+ @count_assertions = 0
38
+
39
+ #@count_tests = 0
40
+ #@count_failures = 0
41
+ #@count_errors = 0
42
+
43
+ #@command = command
44
+ end
45
+
46
+ def new_test(name)
47
+ c = TestMethod.new(name)
48
+ @tests << c
49
+ c
50
+ end
51
+
52
+ # Whne used by a per-file runner.
53
+ #alias_method :file, :name
54
+
55
+ # Were there any errors?
56
+ def error?
57
+ count_errors != 0
58
+ end
59
+
60
+ # Were there any failures?
61
+ def fail?
62
+ count_failures != 0
63
+ end
64
+
65
+ # Did all tests/assertion pass?
66
+ def pass?
67
+ not(fail? or error?)
68
+ end
69
+
70
+ def count_tests
71
+ tests.size
72
+ end
73
+
74
+ def count_failures
75
+ sum = 0; tests.each{ |t| sum += 1 if t.fail? }; sum
76
+ end
77
+
78
+ def count_errors
79
+ sum = 0; tests.each{ |t| sum += 1 if t.error? }; sum
80
+ end
81
+
82
+ def count_passes
83
+ sum = 0; tests.each{ |t| sum += 1 if t.pass? }; sum
84
+ end
85
+
86
+ #
87
+ def counts
88
+ return count_tests, count_assertions, count_failures, count_errors
89
+ end
90
+
91
+ def message
92
+ tests.collect{ |t| t.message }.join("\n")
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+
@@ -0,0 +1,32 @@
1
+ module Turn
2
+
3
+ #
4
+ class TestMethod
5
+ attr_accessor :name
6
+ attr_accessor :file
7
+ attr_accessor :message
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ @fail = false
12
+ @error = false
13
+ @message = nil
14
+ end
15
+
16
+ def fail!(message=nil)
17
+ @fail, @error = true, false
18
+ @message = message if message
19
+ end
20
+
21
+ def error!(message=nil)
22
+ @fail, @error = false, true
23
+ @message = message if message
24
+ end
25
+
26
+ def fail? ; @fail ; end
27
+ def error? ; @error ; end
28
+ def pass? ; !(@fail or @error) ; end
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,82 @@
1
+ module Turn
2
+
3
+ #
4
+ class TestSuite
5
+
6
+ include Enumerable
7
+
8
+ attr_accessor :name
9
+ attr_accessor :size
10
+ attr_accessor :cases
11
+
12
+ # This one can be set manually since it
13
+ # is not calculatable (beyond the case level).
14
+ attr_accessor :count_assertions
15
+
16
+ #
17
+ def initialize(name=nil)
18
+ @name = name
19
+ @size = nil
20
+ @cases = []
21
+
22
+ #@count_tests = nil
23
+ #@count_assertions = nil
24
+ #@count_failures = nil
25
+ #@count_errors = nil
26
+ #@count_passes = nil
27
+ end
28
+
29
+ #
30
+ def new_case(name, *files)
31
+ c = TestCase.new(name, *files)
32
+ @cases << c
33
+ c
34
+ end
35
+
36
+ def count_failures
37
+ #@count_failures ||= (
38
+ sum = 0; each{ |c| sum += c.count_failures }; sum
39
+ #)
40
+ end
41
+
42
+ def count_errors
43
+ #@count_errors ||= (
44
+ sum = 0; each{ |c| sum += c.count_errors }; sum
45
+ #)
46
+ end
47
+
48
+ def count_passes
49
+ #@count_passes ||= (
50
+ sum = 0; each{ |c| sum += c.count_passes }; sum
51
+ #)
52
+ end
53
+
54
+ def count_tests
55
+ #@count_tests ||= (
56
+ sum = 0; each{ |c| sum += c.count_tests }; sum
57
+ #)
58
+ end
59
+
60
+ def count_assertions
61
+ #@count_assertions ||= (
62
+ sum = 0; each{ |c| sum += c.count_assertions }; sum
63
+ #)
64
+ end
65
+
66
+ # Convenience methods --this is what is typcially wanted.
67
+ def counts
68
+ return count_tests, count_assertions, count_failures, count_errors
69
+ end
70
+
71
+ def each(&block)
72
+ @cases.each(&block)
73
+ end
74
+
75
+ def size
76
+ @size ||= @cases.size
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
@@ -0,0 +1,146 @@
1
+ require 'fileutils'
2
+
3
+ module Turn
4
+ require 'turn/components/suite.rb'
5
+ require 'turn/components/case.rb'
6
+ require 'turn/components/method.rb'
7
+
8
+ require 'turn/reporters/outline_reporter'
9
+ require 'turn/reporters/marshal_reporter'
10
+ require 'turn/reporters/progress_reporter'
11
+ require 'turn/reporters/dot_reporter'
12
+
13
+ require 'turn/runners/testrunner'
14
+ require 'turn/runners/solorunner'
15
+ require 'turn/runners/crossrunner'
16
+
17
+ # = Controller
18
+ #
19
+ #--
20
+ # TODO: Add support to test run loggging.
21
+ #++
22
+ class Controller
23
+
24
+ # File glob pattern of tests to run.
25
+ # Can be an array of files/globs.
26
+ attr_accessor :tests
27
+
28
+ # Files globs to specially exclude.
29
+ attr_accessor :exclude
30
+
31
+ # Add these folders to the $LOAD_PATH.
32
+ attr_accessor :loadpath
33
+
34
+ # Libs to require when running tests.
35
+ attr_accessor :requires
36
+
37
+ # Instance of Reporter.
38
+ attr_accessor :reporter
39
+
40
+ # Insatance of Runner.
41
+ attr_accessor :runner
42
+
43
+ # Test against live install (i.e. Don't use loadpath option)
44
+ attr_accessor :live
45
+
46
+ # Log results? May be true/false or log file name. (TODO)
47
+ attr_accessor :log
48
+
49
+ # Verbose output?
50
+ attr_accessor :verbose
51
+
52
+ def verbose? ; @verbose ; end
53
+ def live? ; @live ; end
54
+
55
+ private
56
+
57
+ def initialize
58
+ yield(self) if block_given?
59
+ initialize_defaults
60
+ end
61
+
62
+ #
63
+ def initialize_defaults
64
+ @loadpath ||= ['lib']
65
+ @tests ||= "test/**/{test,}*{,test}"
66
+ @exclude ||= []
67
+ @reqiures ||= []
68
+ @live ||= false
69
+ @log ||= true
70
+ @reporter ||= OutlineReporter.new($stdout)
71
+ @runner ||= TestRunner.new
72
+ end
73
+
74
+ # Collect test configuation.
75
+ #def test_configuration(options={})
76
+ # #options = configure_options(options, 'test')
77
+ # #options['loadpath'] ||= metadata.loadpath
78
+ # options['tests'] ||= self.tests
79
+ # options['loadpath'] ||= self.loadpath
80
+ # options['requires'] ||= self.requires
81
+ # options['live'] ||= self.live
82
+ # options['exclude'] ||= self.exclude
83
+ # #options['tests'] = list_option(options['tests'])
84
+ # options['loadpath'] = list_option(options['loadpath'])
85
+ # options['exclude'] = list_option(options['exclude'])
86
+ # options['require'] = list_option(options['require'])
87
+ # return options
88
+ #end
89
+
90
+ #
91
+ def list_option(list)
92
+ case list
93
+ when nil
94
+ []
95
+ when Array
96
+ list
97
+ else
98
+ list.split(/[:;]/)
99
+ end
100
+ end
101
+
102
+ public
103
+
104
+ def loadpath=(paths)
105
+ @loadpath = list_option(paths)
106
+ end
107
+
108
+ def exclude=(paths)
109
+ @exclude = list_option(paths)
110
+ end
111
+
112
+ def requries=(paths)
113
+ @requries = list_option(paths)
114
+ end
115
+
116
+ def files
117
+ @files ||= (
118
+ fs = tests.map do |t|
119
+ File.directory?(t) ? Dir[File.join(t, '**', '*')] : Dir[t]
120
+ end
121
+ fs = fs.flatten.reject{ |f| File.directory?(f) }
122
+ ex = exclude.map do |x|
123
+ File.directory?(x) ? Dir[File.join(x, '**', '*')] : Dir[x]
124
+ end
125
+ ex = ex.flatten.reject{ |f| File.directory?(f) }
126
+ (fs - ex).uniq
127
+ )
128
+ end
129
+
130
+ def start
131
+ @files = nil # reset files just in case
132
+
133
+ if files.empty?
134
+ $stderr.puts "No tests."
135
+ return
136
+ end
137
+
138
+ testrun = runner.new(self)
139
+
140
+ testrun.start
141
+ end
142
+
143
+ end
144
+
145
+ end
146
+
@@ -0,0 +1,56 @@
1
+ module Turn
2
+ require 'turn/colorize'
3
+
4
+ # = Reporter
5
+ #
6
+ # There are two distinct way in which a report may be utilized
7
+ # by a Runner: per-call or per-file. The method #pass, #fail
8
+ # and #error are generic, and will be used in either case.
9
+ # A per-call runner will use all the methods of a Reporter,
10
+ # while a per-file runner will use start_case per file,
11
+ # and will not use the start_test and finish_test methods,
12
+ # since those are beyond it's grainularity.
13
+ #
14
+ class Reporter
15
+
16
+ include Colorize
17
+
18
+ attr :io
19
+
20
+ def initialize(io)
21
+ @io = io || $stdout
22
+ end
23
+
24
+ # These methods are called in the process of running the tests.
25
+
26
+ def start_suite(suite)
27
+ end
28
+
29
+ def start_case(kase)
30
+ end
31
+
32
+ def start_test(test)
33
+ end
34
+
35
+ def pass(message=nil)
36
+ end
37
+
38
+ def fail(message=nil)
39
+ end
40
+
41
+ def error(message=nil)
42
+ end
43
+
44
+ def finish_test(test)
45
+ end
46
+
47
+ def finish_case(kase)
48
+ end
49
+
50
+ def finish_suite(suite)
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
@@ -0,0 +1,78 @@
1
+ require 'turn/reporter'
2
+
3
+ module Turn
4
+
5
+ # = Traditional Dot Reporter
6
+ #
7
+ class DotReporter < Reporter
8
+
9
+ def start_suite(suite)
10
+ @time = Time.now
11
+ io.puts "Loaded suite #{suite.name}"
12
+ io.puts "Started"
13
+ end
14
+
15
+ def start_case(kase)
16
+ end
17
+
18
+ def start_test(test)
19
+ end
20
+
21
+ def pass(message=nil)
22
+ io.print '.'; io.flush
23
+ end
24
+
25
+ def fail(message=nil)
26
+ io.print 'F'; io.flush
27
+ end
28
+
29
+ def error(message=nil)
30
+ io.print 'E'; io.flush
31
+ end
32
+
33
+ def finish_test(test)
34
+ end
35
+
36
+ def finish_case(kase)
37
+ end
38
+
39
+ def finish_suite(suite)
40
+ io.puts("\nFinished in %.5f seconds." % [Time.now - @time])
41
+ io.puts
42
+
43
+ report = ''
44
+
45
+ fails = suite.select do |testrun|
46
+ testrun.fail? || testrun.error?
47
+ end
48
+
49
+ unless fails.empty? # or verbose?
50
+ #report << "\n\n-- Failures and Errors --\n\n"
51
+ fails.uniq.each do |testrun|
52
+ message = testrun.message.tabto(0)
53
+ message = ::ANSICode.magenta(message) if COLORIZE
54
+ report << message << "\n"
55
+ end
56
+ report << "\n"
57
+ end
58
+
59
+ io.puts report
60
+
61
+ io.puts "%s tests, %s assetions, %s failures, %s errors" % test_tally(suite)
62
+ end
63
+
64
+ private
65
+
66
+ def test_tally(suite)
67
+ counts = suite.collect{ |tr| tr.counts }
68
+ tally = [0,0,0,0]
69
+ counts.each do |count|
70
+ 4.times{ |i| tally[i] += count[i] }
71
+ end
72
+ return tally
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+