fit 1.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.
Files changed (110) hide show
  1. data/README.txt +203 -0
  2. data/Rakefile +111 -0
  3. data/bin/FitServer.rb +6 -0
  4. data/bin/fit +10 -0
  5. data/bin/fit.cgi +36 -0
  6. data/doc/examples/AllCombinations.html +55 -0
  7. data/doc/examples/AllFiles.html +60 -0
  8. data/doc/examples/AllPairs/function/cosine.html +57 -0
  9. data/doc/examples/AllPairs/function/sine.html +57 -0
  10. data/doc/examples/AllPairs/magnitude/180+30.html +45 -0
  11. data/doc/examples/AllPairs/magnitude/30.html +33 -0
  12. data/doc/examples/AllPairs/magnitude/360+30.html +45 -0
  13. data/doc/examples/AllPairs/magnitude/90-30.html +45 -0
  14. data/doc/examples/AllPairs/sign/change-sign.html +27 -0
  15. data/doc/examples/AllPairs/sign/multiply.html +31 -0
  16. data/doc/examples/AllPairs/sign/no-change.html +23 -0
  17. data/doc/examples/AllPairs.html +51 -0
  18. data/doc/examples/BinaryChop.html +89 -0
  19. data/doc/examples/CalculatorExample.html +108 -0
  20. data/doc/examples/ColumnIndex.html +43 -0
  21. data/doc/examples/ExampleTests.html +43 -0
  22. data/doc/examples/FitAcceptanceTests.html +53 -0
  23. data/doc/examples/GeoCoordinate.html +87 -0
  24. data/doc/examples/MusicExample.html +143 -0
  25. data/doc/examples/MusicExampleWithErrors.html +128 -0
  26. data/doc/examples/NetworkExample.html +47 -0
  27. data/doc/examples/WebPageExample.html +92 -0
  28. data/doc/examples/arithmetic.html +211 -0
  29. data/doc/examples/files/hp35bk.jpg +0 -0
  30. data/doc/examples/logo.gif +0 -0
  31. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.FixtureParameters.html +81 -0
  32. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulFixtureNames.html +87 -0
  33. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulMemberNames.html +73 -0
  34. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.ImportFixture.html +61 -0
  35. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.WaysToSpecifyaFixtureNamespace.html +81 -0
  36. data/doc/spec/annotation.html +3833 -0
  37. data/doc/spec/extensions.html +302 -0
  38. data/doc/spec/fixtures.html +5181 -0
  39. data/doc/spec/index.html +947 -0
  40. data/doc/spec/parse.html +3094 -0
  41. data/lib/eg/all_combinations.rb +44 -0
  42. data/lib/eg/all_files.rb +94 -0
  43. data/lib/eg/all_pairs.rb +172 -0
  44. data/lib/eg/arithmetic_column_fixture.rb +35 -0
  45. data/lib/eg/arithmetic_fixture.rb +29 -0
  46. data/lib/eg/binary_chop.rb +100 -0
  47. data/lib/eg/calculator.rb +69 -0
  48. data/lib/eg/column_index.rb +85 -0
  49. data/lib/eg/division.rb +13 -0
  50. data/lib/eg/echo_args_fixture.rb +9 -0
  51. data/lib/eg/example_tests.rb +84 -0
  52. data/lib/eg/music/Music.txt +38 -0
  53. data/lib/eg/music/browser.rb +60 -0
  54. data/lib/eg/music/display.rb +24 -0
  55. data/lib/eg/music/music.rb +67 -0
  56. data/lib/eg/music/music_library.rb +70 -0
  57. data/lib/eg/music/music_player.rb +77 -0
  58. data/lib/eg/music/realtime.rb +39 -0
  59. data/lib/eg/music/simulator.rb +81 -0
  60. data/lib/eg/nested/bob.rb +12 -0
  61. data/lib/eg/nested/bob_the_builder_fixture.rb +11 -0
  62. data/lib/eg/net/simulator.rb +69 -0
  63. data/lib/eg/page.rb +91 -0
  64. data/lib/eg/sqrt.rb +19 -0
  65. data/lib/fat/annotation_fixture.rb +83 -0
  66. data/lib/fat/color.rb +45 -0
  67. data/lib/fat/divide.rb +13 -0
  68. data/lib/fat/document_parse_fixture.rb +67 -0
  69. data/lib/fat/equals.rb +59 -0
  70. data/lib/fat/fixture_name_fixture.rb +67 -0
  71. data/lib/fat/html_to_text_fixture.rb +20 -0
  72. data/lib/fat/money.rb +18 -0
  73. data/lib/fat/output_fixture.rb +32 -0
  74. data/lib/fat/parse_fixture.rb +92 -0
  75. data/lib/fat/reference_fixture.rb +31 -0
  76. data/lib/fat/standard_annotation_fixture.rb +58 -0
  77. data/lib/fat/string_writer.rb +12 -0
  78. data/lib/fat/table.rb +23 -0
  79. data/lib/fat/table_parse_fixture.rb +33 -0
  80. data/lib/fat/text_to_html_fixture.rb +21 -0
  81. data/lib/fit/action_fixture.rb +65 -0
  82. data/lib/fit/column_fixture.rb +104 -0
  83. data/lib/fit/file_runner.rb +80 -0
  84. data/lib/fit/fit_protocol.rb +62 -0
  85. data/lib/fit/fit_server.rb +173 -0
  86. data/lib/fit/fixture.rb +309 -0
  87. data/lib/fit/fixture_loader.rb +75 -0
  88. data/lib/fit/import_fixture.rb +9 -0
  89. data/lib/fit/parse.rb +206 -0
  90. data/lib/fit/primitive_fixture.rb +52 -0
  91. data/lib/fit/row_fixture.rb +188 -0
  92. data/lib/fit/scientific_double.rb +70 -0
  93. data/lib/fit/summary.rb +46 -0
  94. data/lib/fit/timed_action_fixture.rb +35 -0
  95. data/lib/fit/type_adapter.rb +95 -0
  96. data/lib/fit/wiki_runner.rb +15 -0
  97. data/lib/fittask.rb +184 -0
  98. data/test/all_tests.rb +13 -0
  99. data/test/file_runner_test.rb +52 -0
  100. data/test/fit_server_test.rb +214 -0
  101. data/test/fixture_loader_test.rb +71 -0
  102. data/test/fixture_test.rb +41 -0
  103. data/test/fixtures/fail_fixture.rb +9 -0
  104. data/test/fixtures/pass_fixture.rb +9 -0
  105. data/test/framework_test.rb +51 -0
  106. data/test/parse_test.rb +101 -0
  107. data/test/row_fixture_test.rb +44 -0
  108. data/test/scientific_double_test.rb +35 -0
  109. data/test/type_adapter_test.rb +120 -0
  110. metadata +165 -0
@@ -0,0 +1,188 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+ require 'fit/parse'
6
+ require 'fit/type_adapter'
7
+
8
+ module Fit
9
+
10
+ class RowFixture < ColumnFixture
11
+
12
+ attr_accessor :results
13
+ attr_accessor :missing, :surplus
14
+
15
+ def initialize
16
+ super
17
+ @missing = []
18
+ @surplus = []
19
+ end
20
+
21
+ def do_rows rows
22
+ begin
23
+ bind rows.parts
24
+ @results = query
25
+ match list(rows.more), @results, 0
26
+ last = rows.last
27
+ last.more = build_rows @surplus
28
+ mark_parse last.more, 'surplus'
29
+ mark_list @missing, 'missing'
30
+ rescue Exception => e
31
+ exception rows.leaf, e
32
+ end
33
+ end
34
+
35
+ # Gets rows to be compared
36
+ def query; end
37
+
38
+ protected
39
+
40
+ def match expected, computed, column_index
41
+ if column_index >= @column_bindings.size
42
+ check_list expected, computed
43
+ elsif @column_bindings[column_index].nil?
44
+ match(expected, computed, column_index + 1)
45
+ else
46
+ e_map = e_sort(expected, column_index)
47
+ c_map = c_sort(computed, column_index)
48
+ keys = e_map.keys | c_map.keys
49
+ keys.each do |key|
50
+ e_list = e_map[key]
51
+ c_list = c_map[key]
52
+ if e_list.nil?
53
+ @surplus += c_list
54
+ elsif c_list.nil?
55
+ @missing += e_list
56
+ elsif e_list.size == 1 and c_list.size == 1
57
+ check_list e_list, c_list
58
+ else
59
+ match(e_list, c_list, column_index + 1)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def list rows
66
+ result = []
67
+ until rows.nil?
68
+ result << rows
69
+ rows = rows.more
70
+ end
71
+ result
72
+ end
73
+
74
+ def e_sort list, column_index
75
+ adapter = @column_bindings[column_index]
76
+ result = {}
77
+ list.each do |row|
78
+ cell = row.parts.at(column_index)
79
+ begin
80
+ key = adapter.parse(cell.text)
81
+ bin(result, key, row)
82
+ rescue Exception => e
83
+ exception cell, e
84
+ rest = cell.more
85
+ until rest.nil?
86
+ ignore rest
87
+ rest = rest.more
88
+ end
89
+ end
90
+ end
91
+ result
92
+ end
93
+
94
+ def c_sort list, column_index
95
+ adapter = @column_bindings[column_index]
96
+ result = {}
97
+ list.each do |row|
98
+ begin
99
+ adapter.target = row
100
+ key = adapter.get
101
+ bin(result, key, row)
102
+ rescue Exception => e
103
+ @surplus << row # surplus anything with bad keys, including nil
104
+ end
105
+ end
106
+ result
107
+ end
108
+
109
+ def bin map, key, row
110
+ if map.include? key
111
+ map[key] <<= row
112
+ else
113
+ map[key] = [row]
114
+ end
115
+ end
116
+
117
+ def check_list e_list, c_list
118
+ if e_list.empty?
119
+ @surplus += c_list
120
+ return
121
+ end
122
+ if c_list.empty?
123
+ @missing += e_list
124
+ return
125
+ end
126
+ row = e_list.shift
127
+ cell = row.parts
128
+ obj = c_list.shift
129
+ @column_bindings.each do |adapter|
130
+ adapter.target = obj unless adapter.nil?
131
+ check cell, adapter
132
+ cell = cell.more
133
+ break if cell.nil?
134
+ end
135
+ check_list e_list, c_list
136
+ end
137
+
138
+ def mark_parse rows, message
139
+ annotation = Fixture.label message
140
+ until rows.nil?
141
+ wrong rows.parts
142
+ rows.parts.add_to_body annotation
143
+ rows = rows.more
144
+ end
145
+ end
146
+
147
+ def mark_list rows, message
148
+ annotation = Fixture.label message
149
+ rows.each do |row|
150
+ wrong row.parts
151
+ row.parts.add_to_body annotation
152
+ end
153
+ end
154
+
155
+ def build_rows rows
156
+ root_parse = ParseHolder.create nil, nil, nil, nil
157
+ next_parse = root_parse
158
+ rows.each {|row| next_parse = next_parse.more = ParseHolder.create('tr', nil, build_cells(row), nil)}
159
+ root_parse.more
160
+ end
161
+
162
+ def build_cells row
163
+ if row.nil?
164
+ nihil = ParseHolder.create 'td', 'nil', nil, nil
165
+ nihil.add_to_tag('colspan="' + @column_bindings.size.to_s + '"')
166
+ return nihil
167
+ end
168
+ root_parse = ParseHolder.create nil, nil, nil, nil
169
+ next_parse = root_parse
170
+ @column_bindings.each do |adapter|
171
+ next_parse = next_parse.more = ParseHolder.create('td', '&nbsp;', nil, nil)
172
+ if adapter.nil?
173
+ ignore next_parse
174
+ else
175
+ begin
176
+ adapter.target = row
177
+ next_parse.body = Fixture.gray(Fixture.escape(adapter.to_s(adapter.get)))
178
+ rescue Exception => e
179
+ exception next_parse, e
180
+ end
181
+ end
182
+ end
183
+ root_parse.more
184
+ end
185
+
186
+ end
187
+
188
+ end
@@ -0,0 +1,70 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ module Fit
5
+
6
+ # Warning: not (yet) a general number usable in all calculations
7
+ class ScientificDouble
8
+
9
+ attr_accessor :precision
10
+
11
+ def initialize value
12
+ @value = Float(value)
13
+ @precision = 0
14
+ end
15
+
16
+ def ScientificDouble.value_of s
17
+ if s.downcase.index('infinity')
18
+ new (1.0/0.0) # Infinity
19
+ else
20
+ result = new s.to_f
21
+ result.precision = precision s
22
+ result
23
+ end
24
+ end
25
+
26
+ def ScientificDouble.precision s
27
+ value = s.to_f
28
+ bound = tweak(s.strip).to_f
29
+ (bound - value).abs
30
+ end
31
+
32
+ def ScientificDouble.tweak s
33
+ pos = s.downcase.index('e')
34
+ unless pos.nil?
35
+ return tweak(s[0..(pos - 1)]) + s[pos..-1]
36
+ end
37
+ unless s.index('.').nil?
38
+ return s + "5"
39
+ end
40
+ return s + ".5"
41
+ end
42
+
43
+ def == obj
44
+ sd = ScientificDouble.value_of obj.to_s
45
+ self.<=>(sd) == 0
46
+ end
47
+
48
+ def <=> obj
49
+ other = obj.to_f
50
+ diff = @value - other
51
+
52
+ # workaround the much more precise way of Ruby doing floats than Java
53
+ return 0 if @precision.zero? and diff.abs < 1.0e-5
54
+
55
+ precision = @precision > obj.precision ? @precision : obj.precision
56
+ return -1 if diff < -precision
57
+ return 1 if diff > precision
58
+ return 0 if @value.nan? and other.nan?
59
+ return 1 if @value.nan?
60
+ return -1 if other.nan?
61
+ 0
62
+ end
63
+
64
+ def nan?; @value.nan?; end # unused?
65
+ def to_f; @value; end
66
+ def to_s; @value.to_s; end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ module Fit
5
+
6
+ class Summary < Fixture
7
+ @@counts_key = 'counts'
8
+
9
+ def do_table table
10
+ @summary[@@counts_key] = totals
11
+ table.parts.more = rows @summary.keys.sort
12
+ end
13
+
14
+ protected
15
+
16
+ def rows keys
17
+ return nil if keys.empty?
18
+ key = keys.shift
19
+ result = tr(td(key, td(summary[key].to_s, nil)), rows(keys))
20
+ mark(result) if key == @@counts_key
21
+ result
22
+ end
23
+
24
+ def tr parts, more
25
+ ParseHolder.create('tr', nil, parts, more)
26
+ end
27
+
28
+ def td body, more
29
+ ParseHolder.create('td', Fixture.gray(body), nil, more)
30
+ end
31
+
32
+ # Mark summary good or bad without counting
33
+ def mark row
34
+ official = @counts
35
+ @counts = Counts.new # use a fake results holder to avoid counting
36
+ cell = row.parts.more
37
+ if official.total_errors > 0
38
+ wrong cell
39
+ else
40
+ right cell
41
+ end
42
+ @counts = official
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/action_fixture'
5
+
6
+ module Fit
7
+
8
+ class TimedActionFixture < ActionFixture
9
+ attr_accessor :format
10
+ def initialize
11
+ super
12
+ @format = '%H:%M:%S'
13
+ end
14
+ def do_table table
15
+ super
16
+ table.parts.parts.last.more = td('time')
17
+ table.parts.parts.last.more = td('split')
18
+ end
19
+ def do_cells cells
20
+ start = time
21
+ super
22
+ split = time - start
23
+ cells.last.more = td(start.strftime(@format))
24
+ cells.last.more = td(split < 1 ? '&nbsp;' : sprintf("%1.1f", split))
25
+ end
26
+ # Utility
27
+ def td body
28
+ ParseHolder.create('td', Fixture.gray(body), nil, nil)
29
+ end
30
+ def time
31
+ Time.now
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,95 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/scientific_double'
5
+
6
+ module Fit
7
+
8
+ class TypeAdapter
9
+
10
+ attr_accessor :target, :type, :fixture
11
+
12
+ def initialize target, name = '', is_output = false
13
+ @is_output = is_output
14
+ @target = @fixture = target
15
+
16
+ @name=name
17
+ ends_in_qm = is_output && name=~/\?$/
18
+ if @name.index(/[A-Z]/)
19
+ @name = @name.split(/([A-Z][^A-Z]+)/).delete_if {|e| e.empty?}.collect {|e| e.downcase}.join('_')
20
+ end
21
+ @name = @name.gsub(/[^0-9a-zA-Z_]+$/,'').gsub(/[^0-9a-zA-Z_]+/,'_').gsub(/_+/,'_')
22
+ @name << '?' if ends_in_qm
23
+ end
24
+
25
+ # Factories
26
+
27
+ def TypeAdapter.for fixture, name, is_output=(name=~/(\(\))|(\?)$/)
28
+ GenericAdapter.new fixture, name, is_output
29
+ end
30
+
31
+ def TypeAdapter.on fixture, type
32
+ adapter = GenericAdapter.new fixture
33
+ adapter.type = type
34
+ adapter
35
+ end
36
+
37
+ def get
38
+ return nil if @name.nil?
39
+ getter = @name
40
+ getter.chop! if getter =~ /\?$/ && ! @target.respond_to?(getter.to_sym)
41
+ @target.send(getter)
42
+ end
43
+
44
+ def set value
45
+ raise 'Output fields cannot be set' if @is_output
46
+ @target.send("#{@name}=", value)
47
+ end
48
+
49
+ def is_output?
50
+ @is_output
51
+ end
52
+
53
+ def equals a, b
54
+ if ((a.kind_of? Float) and (b.kind_of? Numeric)) or ((a.kind_of? Numeric) and (b.kind_of? Float))
55
+ (a - b).abs < 1.0e-5 # use a delta to test equality between a float and a number
56
+ else
57
+ a == b
58
+ end
59
+ end
60
+
61
+ def to_s target
62
+ target.to_s
63
+ end
64
+
65
+ end
66
+
67
+ # A generic adapter uses the appartent type of its input to store
68
+ # appropriate values. For example, if a cell contains <td>1</td>,
69
+ # a Fixnum is generated; if a cell contains <td>0.5</td>, a Float
70
+ # is generated. Note that this process might not feasible for every
71
+ # type of primitive data.
72
+ class GenericAdapter < TypeAdapter
73
+ def parse value
74
+ return true if value.downcase == 'true'
75
+ return false if value.downcase == 'false'
76
+ unless @type.nil?
77
+ result = @fixture.parse value, @type
78
+ return result unless result.nil?
79
+ end
80
+ return Integer(value) if value =~ /^-?\d+$/
81
+ return Float(value) if (value =~ /^-?\d*\.\d*$/ || value =~ /^-?\d*\.\d*[e|E]\d+$/)
82
+ elements = value.split(',')
83
+ unless elements.size == 1
84
+ array = []
85
+ element_adapter = TypeAdapter.for @target, @name, @is_output
86
+ elements.each do |e|
87
+ array << element_adapter.parse(e.strip)
88
+ end
89
+ return array
90
+ end
91
+ return value
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/file_runner'
5
+
6
+ $stderr.puts 'WikiRunner is deprecated: use FileRunner'
7
+
8
+ if __FILE__ == $0
9
+ begin
10
+ Fit::FileRunner.new.run ARGV
11
+ rescue Exception => e
12
+ $stderr.puts e.message
13
+ exit -1
14
+ end
15
+ end
data/lib/fittask.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ require 'fit/file_runner'
5
+ require 'fit/parse'
6
+
7
+ module Rake
8
+
9
+ class FitReportRunner < Fit::FileRunner
10
+ def run args
11
+ process_args args
12
+ process
13
+ end
14
+ end
15
+
16
+ class FitRunner < Fit::FileRunner
17
+ def run args
18
+ process_args args
19
+ process
20
+ end
21
+ def process_args args
22
+ input_name = File.expand_path args[0]
23
+ input_file = File.open input_name
24
+ @input = input_file.read
25
+ input_file.close
26
+ @output = OutputStream.new
27
+ end
28
+ end
29
+
30
+ # A dummy output stream to avoid creating output files
31
+ class OutputStream < String
32
+ def print text; end
33
+ def close; end
34
+ end
35
+
36
+ # Create a task that runs a set of FIT tests.
37
+ #
38
+ # If rake is invoked with a ATEST command line option, then the list of
39
+ # test files will be overridden to include only the filename specified on
40
+ # the command line. This provides an easy way to run just one test.
41
+ # The exact syntax of the ATEST option is as follows:
42
+ # ATEST=/path/to/FileHtml:Right:Wrong:Ignores:Exceptions
43
+ # where you can include a path to the HTML file, which must be specified
44
+ # without the .html extension; and where Rights, Wrong, Ignores and
45
+ # Exceptions are the numbers of the expected results from the test run.
46
+ # Note that the report path will be the same as the test path.
47
+ #
48
+ class FitTask < TaskLib
49
+
50
+ attr_accessor :name, :libs, :pattern, :fail_on_failed_test
51
+
52
+ def test_suites=(list)
53
+ @test_suites = list
54
+ end
55
+
56
+ def test_suites
57
+ if ENV['ATEST']
58
+ atest = ENV['ATEST'].split ':'
59
+ filename = atest[0]
60
+ test_name = File.basename(filename)
61
+ test = { :name => test_name,
62
+ :right => atest[1].to_i, :wrong => atest[2].to_i,
63
+ :ignores => atest[3].to_i, :exceptions => atest[4].to_i }
64
+ suite = AcceptanceTestSuite.new
65
+ suite << test
66
+ suite.test_path = suite.report_path = File.dirname(filename) + File::SEPARATOR
67
+ [suite]
68
+ else
69
+ @test_suites
70
+ end
71
+ end
72
+
73
+ def initialize(name=:fittest)
74
+ @name = name
75
+ @libs = ["lib"]
76
+ @pattern = nil
77
+ @test_files = []
78
+ @test_suites = []
79
+ @fail_on_failed_test=false
80
+ @tests_failed=false
81
+ yield self if block_given?
82
+ define name
83
+ end
84
+
85
+ def define task_name
86
+ # describe the fit task
87
+ desc "Run FIT acceptance tests"
88
+ task task_name
89
+ # silence footnote creation since we don't want HTML reports
90
+ task task_name do
91
+ Fit::Parse.send(:define_method, 'footnote', lambda {''})
92
+ end
93
+ # define a fit task for each test suite
94
+ test_suites.each do |suite|
95
+ task task_name do
96
+ @tests_failed = true unless suite.run_tests
97
+ end
98
+ end
99
+
100
+ task task_name do
101
+ raise 'Tests failed.' if @fail_on_failed_test && @tests_failed
102
+ end
103
+
104
+ # describe the fit_report task
105
+ desc "Run FIT acceptance tests with HTML reports"
106
+ task_report_name = (task_name.to_s + '_report').to_sym
107
+ task task_report_name
108
+ # define a fit_report task for each test suite
109
+ test_suites.each do |suite|
110
+ task task_report_name do
111
+ # set footnote path to an appropriate location
112
+ Fit::Parse.footnote_path = suite.report_path
113
+ # run tests
114
+ @tests_failed = true unless suite.run_tests_with_reports
115
+ end
116
+ end
117
+
118
+ task task_report_name do
119
+ raise 'Tests failed.' if @fail_on_failed_test && @tests_failed
120
+ end
121
+
122
+ self
123
+ end
124
+
125
+ def create_test_suite &block
126
+ suite = AcceptanceTestSuite.new
127
+ block.call suite
128
+ @test_suites << suite
129
+ end
130
+
131
+ class AcceptanceTestSuite
132
+ attr_accessor :test_path, :report_path, :tests
133
+ def initialize
134
+ @tests = []
135
+ @test_path = @report_path = ''
136
+ end
137
+ def << test
138
+ @tests << test
139
+ end
140
+
141
+ def run_tests_with_reports; run_tests true; end;
142
+
143
+ def run_tests with_report=false
144
+ all_passed = true
145
+ @tests.each do |test|
146
+ begin
147
+ runner_args = [@test_path + "#{test[:name]}.html"]
148
+ puts "Running #{test[:name]}.html"
149
+
150
+ if with_report
151
+ report_file=@report_path + "Report_#{test[:name]}.html"
152
+ puts " (Writing report to #{report_file})"
153
+ runner_args << report_file
154
+ runner = Rake::FitReportRunner.new
155
+ else
156
+ runner = Rake::FitRunner.new
157
+ end
158
+
159
+ runner.run runner_args
160
+ result = runner.fixture.counts
161
+ verify test, result
162
+ rescue Exception => e
163
+ puts " #{test[:name]} failed: #{e}"
164
+ all_passed = false
165
+ end
166
+ end
167
+ all_passed
168
+ end
169
+
170
+ def verify test, result
171
+ [:exceptions,:wrong].each { |symbol| test[symbol] = 0 if test[symbol].nil? }
172
+ [:right, :wrong, :ignores, :exceptions].each do |symbol|
173
+ count = result.method(symbol).call
174
+ expected = test[symbol]
175
+ unless expected.nil? || count == expected
176
+ raise Exception.new("#{expected} #{symbol} expected, found #{count} instead.")
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ end
data/test/all_tests.rb ADDED
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'test/unit'
5
+
6
+ require 'test/file_runner_test'
7
+ require 'test/fit_server_test'
8
+ require 'test/fixture_test'
9
+ #require 'test/framework_test'
10
+ require 'test/parse_test'
11
+ require 'test/scientific_double_test'
12
+ require 'test/type_adapter_test'
13
+ require 'test/fixture_loader_test'
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'test/unit'
5
+ # Make the test run location independent
6
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
7
+ require 'fit/file_runner'
8
+
9
+ module Fit
10
+
11
+ class FileRunnerTest < Test::Unit::TestCase
12
+ def test_simple_html
13
+ simple_html = "<table>" +
14
+ " <tr><td>fit.Fixture</td></tr>" +
15
+ "</table>"
16
+ do_html simple_html
17
+ end
18
+ def test_wiki_html
19
+ wiki_html = "<table><tr><td>extra formatting" +
20
+ " <wiki>" +
21
+ " <table>" +
22
+ " <tr><td>fit.Fixture</td></tr>" +
23
+ " </table>" +
24
+ " </wiki>" +
25
+ "</td></tr></table>"
26
+ do_html wiki_html
27
+ end
28
+ def do_html text
29
+ runner = FileRunner.new
30
+ runner.fixture = TempFixture.new
31
+ runner.input = text
32
+ runner.output = OutputStream.new
33
+ runner.process
34
+
35
+ assert_equal 'fit.Fixture', $tempParse.leaf.text
36
+ end
37
+ end
38
+
39
+ # What's the Ruby equivalent of Java anonymous classes?
40
+ class TempFixture < Fixture
41
+ def do_tables tables
42
+ $tempParse = tables
43
+ end
44
+ end
45
+
46
+ # A dummy output stream
47
+ class OutputStream < String
48
+ def print text; end
49
+ def close; end
50
+ end
51
+
52
+ end