qunited 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,186 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+ require 'stringio'
3
+
4
+ class TestResultsCollector < MiniTest::Unit::TestCase
5
+ def setup
6
+ @io = StringIO.new
7
+ @results_collector = QUnited::Driver::ResultsCollector.new(@io)
8
+ end
9
+
10
+ def test_must_be_initialized_with_io_object
11
+ assert_raises(ArgumentError) { QUnited::Driver::ResultsCollector.new }
12
+ QUnited::Driver::ResultsCollector.new(@io)
13
+ end
14
+
15
+ def test_on_test_result_must_be_given_a_block
16
+ assert_raises(ArgumentError) { @results_collector.on_test_result }
17
+ @results_collector.on_test_result { |result| }
18
+ end
19
+
20
+ def test_on_test_result_block_is_called_when_test_results_are_parsed
21
+ collected_results = []
22
+ @results_collector.on_test_result { |result| collected_results << result }
23
+
24
+ @io.puts two_tests_output
25
+ @io.rewind
26
+
27
+ @results_collector.collect_results
28
+
29
+ assert_equal 2, collected_results.size, 'The correct number of results have been collected'
30
+ assert collected_results.all? {|result| result.is_a? QUnited::QUnitTestResult }, 'Test results are the correct type'
31
+ end
32
+
33
+ def test_results_can_be_collected_with_other_lines_mixed_in
34
+ collected_results = []
35
+ @results_collector.on_test_result { |result| collected_results << result }
36
+
37
+ @io.puts two_tests_output_with_other_lines_mixed_in
38
+ @io.rewind
39
+
40
+ @results_collector.collect_results
41
+
42
+ assert_equal 2, collected_results.size, 'The correct number of results have been collected'
43
+ assert collected_results.all? {|result| result.is_a? QUnited::QUnitTestResult }, 'Test results are the correct type'
44
+ end
45
+
46
+ def test_one_line_test_results_are_ok
47
+ output = QUnited::Driver::ResultsCollector::TEST_RESULT_START_TOKEN +
48
+ %|{ "assertion_data": [{ "actual": 1, "expected": 1, "message": "This is fine", "result": true }], | +
49
+ %|"assertions": 1, "duration": 0.001, "failed": 0, "file": "", "module_name": "(no module)", | +
50
+ %|"name": "Just a test", "start": "2013-03-02T21:52:30.000Z", "total": 1 }| +
51
+ QUnited::Driver::ResultsCollector::TEST_RESULT_END_TOKEN
52
+
53
+ collected_results = []
54
+ @results_collector.on_test_result { |result| collected_results << result }
55
+
56
+ @io.puts output
57
+ @io.rewind
58
+
59
+ @results_collector.collect_results
60
+
61
+ assert_equal 1, collected_results.size, 'The correct number of results have been collected'
62
+ assert collected_results.all? {|result| result.is_a? QUnited::QUnitTestResult }, 'Test results are the correct type'
63
+ end
64
+
65
+ def test_on_non_test_result_line_must_be_given_a_block
66
+ assert_raises(ArgumentError) { @results_collector.on_non_test_result_line }
67
+ @results_collector.on_non_test_result_line { |line| }
68
+ end
69
+
70
+ def test_non_test_result_lines_can_be_captured
71
+ stray_lines = []
72
+ @results_collector.on_non_test_result_line { |line| stray_lines << line }
73
+
74
+ @io.puts two_tests_output_with_other_lines_mixed_in
75
+ @io.rewind
76
+
77
+ @results_collector.collect_results
78
+
79
+ assert_equal 4, stray_lines.size, 'The correct number of non test result lines have been collected'
80
+ assert stray_lines.all? {|line| line.is_a? String }, 'Other lines are all strings'
81
+ assert_equal "This is some other output\n", stray_lines[0], 'Line content is correct'
82
+ assert_equal "This is another with a blank line after it\n", stray_lines[1], 'Line content is correct'
83
+ assert_equal "\n", stray_lines[2], 'Can even get blank lines'
84
+ assert_equal "And another line at the end\n", stray_lines[3], 'Line content is correct'
85
+ end
86
+
87
+ private
88
+
89
+ def two_tests_output
90
+ output = <<RAW_OUTPUT
91
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_START_TOKEN}
92
+ {
93
+ "assertion_data": [
94
+ {
95
+ "actual": 1,
96
+ "expected": 1,
97
+ "message": "This is fine",
98
+ "result": true
99
+ }
100
+ ],
101
+ "assertions": 1,
102
+ "duration": 0.001,
103
+ "failed": 0,
104
+ "file": "",
105
+ "module_name": "(no module)",
106
+ "name": "Just a test",
107
+ "start": "2013-03-02T21:52:30.000Z",
108
+ "total": 1
109
+ }
110
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_END_TOKEN}
111
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_START_TOKEN}
112
+ {
113
+ "assertion_data": [
114
+ {
115
+ "actual": 1,
116
+ "expected": 1,
117
+ "message": "This is also fine",
118
+ "result": true
119
+ }
120
+ ],
121
+ "assertions": 1,
122
+ "duration": 0.003,
123
+ "failed": 0,
124
+ "file": "",
125
+ "module_name": "(no module)",
126
+ "name": "Just another test",
127
+ "start": "2013-03-02T21:52:33.000Z",
128
+ "total": 1
129
+ }
130
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_END_TOKEN}
131
+ RAW_OUTPUT
132
+
133
+ output
134
+ end
135
+
136
+ def two_tests_output_with_other_lines_mixed_in
137
+ output = <<RAW_OUTPUT
138
+ This is some other output
139
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_START_TOKEN}
140
+ {
141
+ "assertion_data": [
142
+ {
143
+ "actual": 1,
144
+ "expected": 1,
145
+ "message": "This is fine",
146
+ "result": true
147
+ }
148
+ ],
149
+ "assertions": 1,
150
+ "duration": 0.001,
151
+ "failed": 0,
152
+ "file": "",
153
+ "module_name": "(no module)",
154
+ "name": "Just a test",
155
+ "start": "2013-03-02T21:52:30.000Z",
156
+ "total": 1
157
+ }
158
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_END_TOKEN}
159
+ This is another with a blank line after it
160
+
161
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_START_TOKEN}
162
+ {
163
+ "assertion_data": [
164
+ {
165
+ "actual": 1,
166
+ "expected": 1,
167
+ "message": "This is also fine",
168
+ "result": true
169
+ }
170
+ ],
171
+ "assertions": 1,
172
+ "duration": 0.003,
173
+ "failed": 0,
174
+ "file": "",
175
+ "module_name": "(no module)",
176
+ "name": "Just another test",
177
+ "start": "2013-03-02T21:52:33.000Z",
178
+ "total": 1
179
+ }
180
+ #{QUnited::Driver::ResultsCollector::TEST_RESULT_END_TOKEN}
181
+ And another line at the end
182
+ RAW_OUTPUT
183
+
184
+ output
185
+ end
186
+ end
@@ -1,6 +1,16 @@
1
+ require 'stringio'
2
+
1
3
  # Common driver tests that should pass for any implementation of
2
4
  # QUnited::Driver::Base. There are also a few utility methods included.
3
5
  module QUnited::DriverCommonTests
6
+ def setup
7
+ start_capture_streams
8
+ end
9
+
10
+ def teardown
11
+ stop_capture_streams
12
+ end
13
+
4
14
  def test_driver_available
5
15
  assert driver_class.available?, 'Driver should be available - if it is not then ' +
6
16
  'either the available? method has a bug or you do not have the proper environment ' +
@@ -9,39 +19,58 @@ module QUnited::DriverCommonTests
9
19
  end
10
20
 
11
21
  def test_running_basic_tests
12
- results = run_for_project('basic_project')
13
- assert_equal 3, results.total_tests, 'Correct number of tests run'
14
- assert_equal 4, results.total_assertions, 'Correct number of assertions executed'
15
- assert_equal 0, results.total_failures, 'Correct number of failures given'
22
+ @results = run_tests_for_project('basic_project')
23
+ assert_equal 3, total_tests, 'Correct number of tests run'
24
+ assert_equal 4, total_assertions, 'Correct number of assertions executed'
25
+ assert_equal 0, total_failed_tests, 'Correct number of failures given'
16
26
  end
17
27
 
18
28
  # Make sure we can run tests with DOM operations
19
29
  def test_running_dom_tests
20
- results = run_for_project('dom_project')
21
- assert_equal 1, results.total_tests, 'Correct number of tests run'
22
- assert_equal 2, results.total_assertions, 'Correct number of assertions executed'
23
- assert_equal 0, results.total_failures, 'Correct number of failures given'
30
+ @results = run_tests_for_project('dom_project')
31
+ assert_equal 1, total_tests, 'Correct number of tests run'
32
+ assert_equal 2, total_assertions, 'Correct number of assertions executed'
33
+ assert_equal 0, total_failed_tests, 'Correct number of failures given'
24
34
  end
25
35
 
26
36
  def test_failures_are_recorded_correctly
27
- results = run_for_project('failures_project')
28
- assert_equal 4, results.total_tests, 'Correct number of tests run'
37
+ @results = run_tests_for_project('failures_project')
38
+ assert_equal 4, total_tests, 'Correct number of tests run'
29
39
  # QUnit calls the log callback (the same it calls for assertions) every time there
30
40
  # is a failed expect(num). So add one to this total.
31
- assert_equal 5 + 1, results.total_assertions, 'Correct number of assertions executed'
32
- assert_equal 4, results.total_failures, 'Correct number of failures given'
41
+ assert_equal 5 + 1, total_assertions, 'Correct number of assertions executed'
42
+ assert_equal 3, total_failed_tests, 'Correct number of failed tests given'
43
+ assert_equal 4, total_failed_assertions, 'Correct number of failed assertions given'
44
+
45
+ # JavaScript null values should be properly serialized as null by the driver. If they are
46
+ # they will be deserialized as Ruby nil in QUnitTestResult. Then they can be converted back
47
+ # into null when displayed by the formatter. Make sure the result has nil.
48
+ math_test = @results.find { |result| result.name == 'Addition is hard' }
49
+ null_assertion = math_test.assertions.find { |assertion| assertion.message == 'This expected null' }
50
+ assert_equal nil, null_assertion.expected
33
51
  end
34
52
 
35
53
  def test_syntax_error_in_test
36
- runner = driver_class.new(
54
+ driver = driver_class.new(
37
55
  [File.join(FIXTURES_DIR, 'errors_project/app/assets/javascripts/no_error.js')],
38
56
  [File.join(FIXTURES_DIR, 'errors_project/test/javascripts/this_test_has_syntax_error.js'),
39
57
  File.join(FIXTURES_DIR, 'errors_project/test/javascripts/this_test_has_no_errors_in_it.js')])
40
58
 
41
- stderr = capture_stderr { runner.run }
59
+ driver.run
60
+ stderr = captured_stderr
42
61
  assert stderr.size > 10, 'Got some stderr output to describe the crash'
43
- results = runner.results
44
- assert runner.results.failed?, 'Should fail if syntax error in test'
62
+ @results = driver.results
63
+ assert total_failed_tests.size > 0, 'Should fail if syntax error in test'
64
+ end
65
+
66
+ def test_proper_formatter_methods_are_called_when_tests_pass
67
+ mock_formatter = mock
68
+ mock_formatter.expects(:start)
69
+ mock_formatter.expects(:test_passed).times(3)
70
+ mock_formatter.expects(:stop)
71
+ mock_formatter.expects(:summarize)
72
+
73
+ run_tests_for_project 'basic_project', :formatter => mock_formatter
45
74
  end
46
75
 
47
76
  protected
@@ -50,21 +79,53 @@ module QUnited::DriverCommonTests
50
79
  raise 'Must implement driver_class and return the driver class being tested'
51
80
  end
52
81
 
53
- def run_for_project(project_name)
54
- runner = runner_for_project(project_name)
55
- runner.run
82
+ def run_tests_for_project(project_name, driver_opts={})
83
+ driver = driver_for_project(project_name, driver_opts)
84
+ driver.run
56
85
  end
57
86
 
58
- def runner_for_project(project_name)
87
+ def driver_for_project(project_name, opts={})
59
88
  Dir.chdir File.join(FIXTURES_DIR, project_name)
60
- driver_class.new("app/assets/javascripts/*.js", "test/javascripts/*.js")
89
+ driver = driver_class.new("app/assets/javascripts/*.js", "test/javascripts/*.js")
90
+ driver.formatter = opts[:formatter] if opts[:formatter]
91
+ driver
92
+ end
93
+
94
+ def start_capture_streams
95
+ @original_stdout, $stdout = $stdout, StringIO.new
96
+ @original_stderr, $stderr = $stderr, StringIO.new
97
+ end
98
+
99
+ def stop_capture_streams
100
+ $stdout, $stderr = @original_stdout, @original_stderr
61
101
  end
62
102
 
63
- def capture_stderr
64
- previous_stderr, $stderr = $stderr, StringIO.new
65
- yield
103
+ def captured_stdout
104
+ $stdout.string
105
+ end
106
+
107
+ def captured_stderr
66
108
  $stderr.string
67
- ensure
68
- $stderr = previous_stderr
109
+ end
110
+
111
+
112
+ def total_tests
113
+ @results.size
114
+ end
115
+
116
+ def total_failed_tests
117
+ @results.select { |tr| tr.failed? }.size
118
+ end
119
+
120
+ def total_error_tests
121
+ @results.select { |tr| tr.error? }.size
122
+ end
123
+
124
+ def total_assertions
125
+ @results.inject(0) { |total, result| total += result.assertions.size}
126
+ end
127
+
128
+ def total_failed_assertions
129
+ @results.inject(0) { |total, result| total += result.assertions.select { |a| a.failed? }.size }
69
130
  end
70
131
  end
@@ -0,0 +1,250 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+ require 'date'
3
+ require 'stringio'
4
+
5
+ # Test running tests with the Rhino driver.
6
+ class TestDots < MiniTest::Unit::TestCase
7
+ def setup
8
+ @output = StringIO.new
9
+ @formatter = ::QUnited::Formatter::Dots.new({:driver_name => 'FakeDriver', :output => @output})
10
+ end
11
+
12
+ def test_basic_output
13
+ @formatter.start
14
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
15
+
16
+ @formatter.test_passed create_result([
17
+ create_assertion(:message => 'good assertion 1'),
18
+ create_assertion(:message => 'good assertion 2')
19
+ ])
20
+ assert_output_equals '.'
21
+
22
+ @formatter.test_passed create_result([
23
+ create_assertion({ :result => true, :message => "doesn't matter" })
24
+ ])
25
+ assert_output_equals '.'
26
+
27
+ @formatter.stop
28
+ @formatter.summarize
29
+
30
+ seconds = 0.02
31
+
32
+ expected = <<EXPECTED_OUTPUT
33
+
34
+
35
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (2 / seconds)} tests/s, #{'%.6g' % (3 / seconds)} assertions/s.
36
+
37
+ 2 tests, 3 assertions, 0 failures, 0 errors
38
+ EXPECTED_OUTPUT
39
+
40
+ assert_output_equals expected
41
+ end
42
+
43
+ def test_ok_failure_output
44
+ @formatter.start
45
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
46
+
47
+ msg = "This should be true"
48
+ @formatter.test_failed create_result([
49
+ create_assertion({ :result => false, :message => msg })
50
+ ])
51
+ assert_output_equals 'F'
52
+
53
+ @formatter.stop
54
+ @formatter.summarize
55
+
56
+ seconds = 0.01
57
+
58
+ expected = <<EXPECTED_OUTPUT
59
+
60
+
61
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (1 / seconds)} tests/s, #{'%.6g' % (1 / seconds)} assertions/s.
62
+
63
+ 1) Failure:
64
+ This stuff should work (My Tests) [something_test.js]
65
+ #{msg}
66
+
67
+ 1 tests, 1 assertions, 1 failures, 0 errors
68
+ EXPECTED_OUTPUT
69
+
70
+ assert_output_equals expected
71
+ end
72
+
73
+ def test_equal_failure_output
74
+ @formatter.start
75
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
76
+
77
+ msg = "These strings match"
78
+ expected, actual = "String here", "Other string here"
79
+ @formatter.test_failed create_result([
80
+ create_assertion({ :result => false, :message => msg,
81
+ :expected => expected, :actual => actual })
82
+ ])
83
+ assert_output_equals 'F'
84
+
85
+ @formatter.stop
86
+ @formatter.summarize
87
+
88
+ seconds = 0.01
89
+
90
+ expected = <<EXPECTED_OUTPUT
91
+
92
+
93
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (1 / seconds)} tests/s, #{'%.6g' % (1 / seconds)} assertions/s.
94
+
95
+ 1) Failure:
96
+ This stuff should work (My Tests) [something_test.js]
97
+ #{msg}
98
+ Expected: "#{expected}"
99
+ Actual: "#{actual}"
100
+
101
+ 1 tests, 1 assertions, 1 failures, 0 errors
102
+ EXPECTED_OUTPUT
103
+
104
+ assert_output_equals expected
105
+ end
106
+
107
+ def test_equal_with_null_failure_output
108
+ @formatter.start
109
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
110
+
111
+ msg = "These strings match"
112
+ expected, actual = 1, nil
113
+ @formatter.test_failed create_result([
114
+ create_assertion({ :result => false, :message => msg,
115
+ :expected => expected, :actual => actual })
116
+ ])
117
+ assert_output_equals 'F'
118
+
119
+ @formatter.stop
120
+ @formatter.summarize
121
+
122
+ seconds = 0.01
123
+
124
+ expected = <<EXPECTED_OUTPUT
125
+
126
+
127
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (1 / seconds)} tests/s, #{'%.6g' % (1 / seconds)} assertions/s.
128
+
129
+ 1) Failure:
130
+ This stuff should work (My Tests) [something_test.js]
131
+ #{msg}
132
+ Expected: 1
133
+ Actual: null
134
+
135
+ 1 tests, 1 assertions, 1 failures, 0 errors
136
+ EXPECTED_OUTPUT
137
+
138
+ assert_output_equals expected
139
+ end
140
+
141
+ def test_failure_output_with_no_file
142
+ @formatter.start
143
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
144
+
145
+ msg = "This should be true"
146
+ @formatter.test_failed create_result([
147
+ create_assertion({ :result => false, :message => msg })
148
+ ], {:file => nil})
149
+ assert_output_equals 'F'
150
+
151
+ @formatter.stop
152
+ @formatter.summarize
153
+
154
+ seconds = 0.01
155
+
156
+ expected = <<EXPECTED_OUTPUT
157
+
158
+
159
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (1 / seconds)} tests/s, #{'%.6g' % (1 / seconds)} assertions/s.
160
+
161
+ 1) Failure:
162
+ This stuff should work (My Tests)
163
+ #{msg}
164
+
165
+ 1 tests, 1 assertions, 1 failures, 0 errors
166
+ EXPECTED_OUTPUT
167
+
168
+ assert_output_equals expected
169
+ end
170
+
171
+ def test_multiple_failure_output
172
+ @formatter.start
173
+ assert_output_equals "\n# Running JavaScript tests with FakeDriver:\n\n"
174
+
175
+ msg1 = "This should be true"
176
+ @formatter.test_failed create_result([
177
+ create_assertion({ :result => false, :message => msg1 })
178
+ ])
179
+ assert_output_equals 'F'
180
+
181
+ msg2 = "These strings match"
182
+ msg3 = "Another thing that should be true"
183
+ expected, actual = "String here", "Other string here"
184
+ @formatter.test_failed create_result([
185
+ create_assertion({ :result => false, :message => msg2,
186
+ :expected => expected, :actual => actual }),
187
+ create_assertion({ :result => false, :message => msg3 })
188
+ ])
189
+ assert_output_equals 'F'
190
+
191
+ @formatter.stop
192
+ @formatter.summarize
193
+
194
+ seconds = 0.01 * 2
195
+
196
+ expected = <<EXPECTED_OUTPUT
197
+
198
+
199
+ Finished in #{'%.6g' % seconds} seconds, #{'%.6g' % (2 / seconds)} tests/s, #{'%.6g' % (3 / seconds)} assertions/s.
200
+
201
+ 1) Failure:
202
+ This stuff should work (My Tests) [something_test.js]
203
+ #{msg1}
204
+
205
+ 2) Failure:
206
+ This stuff should work (My Tests) [something_test.js]
207
+ #{msg2}
208
+ Expected: "#{expected}"
209
+ Actual: "#{actual}"
210
+
211
+ 3) Failure:
212
+ This stuff should work (My Tests) [something_test.js]
213
+ #{msg3}
214
+
215
+ 2 tests, 3 assertions, 2 failures, 0 errors
216
+ EXPECTED_OUTPUT
217
+
218
+ assert_output_equals expected
219
+ end
220
+
221
+ private
222
+
223
+ def assert_output_equals(string)
224
+ assert_equal string, @output.string
225
+ clear_output
226
+ end
227
+
228
+ def clear_output
229
+ @output.truncate(@output.rewind)
230
+ end
231
+
232
+ def create_result(assertions=nil, data={})
233
+ assertions ||= [create_assertion]
234
+ QUnited::QUnitTestResult.new({
235
+ :assertion_data => assertions,
236
+ :assertions => assertions.size,
237
+ :duration => 0.010,
238
+ :failed => assertions.select {|a| !a[:result]}.size,
239
+ :file => "something_test.js",
240
+ :module_name => "My Tests",
241
+ :name => "This stuff should work",
242
+ :start => DateTime.now,
243
+ :total => assertions.size
244
+ }.merge(data))
245
+ end
246
+
247
+ def create_assertion(data={})
248
+ { :message => 'This is the message', :result => true }.merge(data)
249
+ end
250
+ end
@@ -1,6 +1,5 @@
1
1
  require File.expand_path('../../test_helper', __FILE__)
2
2
  require File.expand_path('../driver_common_tests', __FILE__)
3
- require 'stringio'
4
3
 
5
4
  # Test running tests with the PhantomJs driver.
6
5
  class TestPhantomJsDriver < MiniTest::Unit::TestCase
@@ -9,7 +8,7 @@ class TestPhantomJsDriver < MiniTest::Unit::TestCase
9
8
  private
10
9
 
11
10
  def driver_class
12
- QUnited::Driver::PhantomJs
11
+ ::QUnited::Driver::PhantomJs
13
12
  end
14
13
 
15
14
  end