qunited 0.3.1 → 0.4.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.
@@ -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