2 # Copyright (c) 2014, 2016 Intel Corporation
4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 # of this software and associated documentation files (the "Software"), to deal
6 # in the Software without restriction, including without limitation the rights
7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 # copies of the Software, and to permit persons to whom the Software is
9 # furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 """Tests for the Junit backend package."""
27 from lxml
import etree
29 import xml
.etree
.ElementTree
as etree
33 from unittest
import mock
37 from framework
import backends
38 from framework
import grouptools
39 from framework
import results
40 from framework
import status
44 # pylint: disable=no-self-use
46 JUNIT_SCHEMA
= os
.path
.join(os
.path
.dirname(__file__
), 'schema', 'junit-7.xsd')
49 <?xml version='1.0' encoding='utf-8'?>
51 <testsuite name="piglit" tests="1">
52 <testcase classname="piglit.foo.bar" name="a-test" status="pass" time="1.12345">
53 <system-out>this/is/a/command\nThis is stdout</system-out>
54 <system-err>this is stderr
66 @pytest.fixture(autouse
=True, scope
="module")
67 def mock_compression():
68 with mock
.patch('framework.backends.compression.get_mode',
69 mock
.Mock(return_value
='none')):
73 class TestProtectedLoad(object):
74 """Tests for the _load method."""
76 def test_default_name(self
, tmpdir
):
77 """backends.junit._load: uses 'junit result' for name as fallback."""
79 with
open('results.xml', 'w') as f
:
81 test
= backends
.junit
.REGISTRY
.load('results.xml', 'none')
83 assert test
.name
== 'junit result'
85 def test_file_name(self
, tmpdir
):
86 """backends.junit._load: uses the filename for name if filename !=
89 p
= tmpdir
.join('foobar.xml')
91 test
= backends
.junit
.REGISTRY
.load(str(p
), 'none')
92 assert test
.name
== 'foobar'
94 def test_folder_name(self
, tmpdir
):
95 """backends.junit._load: uses the folder name if the result is
99 p
= tmpdir
.join('foo', 'results.xml')
101 test
= backends
.junit
.REGISTRY
.load(str(p
), 'none')
103 assert test
.name
== 'foo'
105 class TestReturned(object):
106 """Test that the returned object is as expected."""
108 testname
= grouptools
.join('foo', 'bar', 'a-test')
111 def result(self
, tmpdir
):
112 p
= tmpdir
.join('test.xml')
114 return backends
.junit
._load
(str(p
))
116 def test_testrunresult(self
, result
):
117 """backends.junit._load: returns a TestrunResult instance."""
118 assert isinstance(result
, results
.TestrunResult
)
120 def test_replace_sep(self
, result
):
121 """backends.junit._load: replaces '.' with grouptools.SEPARATOR."""
122 assert self
.testname
in result
.tests
124 def test_testresult_instance(self
, result
):
125 """backends.junit._load: replaces result with TestResult instance.
127 assert isinstance(result
.tests
[self
.testname
], results
.TestResult
)
129 def test_status_instance(self
, result
):
130 """backends.junit._load: a status is found and loaded."""
131 assert isinstance(result
.tests
[self
.testname
].result
,
134 def test_time(self
, result
):
135 time
= result
.tests
[self
.testname
].time
136 assert isinstance(time
, results
.TimeAttribute
)
137 assert time
.start
== 1.0
138 assert time
.end
== 4.5
140 def test_command(self
, result
):
141 """backends.junit._load: command is loaded correctly."""
142 assert result
.tests
[self
.testname
].command
== 'this/is/a/command'
144 def test_out(self
, result
):
145 """backends.junit._load: stdout is loaded correctly."""
146 assert result
.tests
[self
.testname
].out
== 'This is stdout'
148 def test_err(self
, result
):
149 """backends.junit._load: stderr is loaded correctly."""
150 assert result
.tests
[self
.testname
].err
.strip() == 'this is stderr'
152 def test_totals(self
, result
):
153 """backends.junit._load: Totals are calculated."""
156 def test_pid(self
, result
):
157 """backends.junit._load: pid is loaded correctly."""
158 assert result
.tests
[self
.testname
].pid
== [1934]
161 class TestJUnitBackend(object):
162 """Tests for the JUnitBackend class."""
164 class TestFinalize(object):
165 """Tests for the finalize method."""
167 def test_skips_illformed_tests(self
, tmpdir
):
168 """backends.junit.JUnitBackend: skips illformed tests"""
169 result
= results
.TestResult()
170 result
.time
.end
= 1.2345
171 result
.result
= 'pass'
172 result
.out
= 'this is stdout'
173 result
.err
= 'this is stderr'
174 result
.command
= 'foo'
176 test
= backends
.junit
.JUnitBackend(str(tmpdir
))
177 test
.initialize(shared
.INITIAL_METADATA
)
178 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
180 tmpdir
.join('tests', '1.xml').write('bad data')
185 class TestJUnitWriter(object):
186 """Tests for the JUnitWriter class."""
188 def test_junit_replace(self
, tmpdir
):
189 """backends.junit.JUnitBackend.write_test: grouptools.SEPARATOR is
192 result
= results
.TestResult()
193 result
.time
.end
= 1.2345
194 result
.result
= 'pass'
195 result
.out
= 'this is stdout'
196 result
.err
= 'this is stderr'
197 result
.command
= 'foo'
199 test
= backends
.junit
.JUnitBackend(str(tmpdir
))
200 test
.initialize(shared
.INITIAL_METADATA
)
201 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
205 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
206 test_value
= test_value
.getroot()
208 assert test_value
.find('.//testcase').attrib
['classname'] == \
211 class TestValid(object):
213 def test_file(self
, tmpdir
):
215 p
= tmpdir
.join('foo')
217 result
= results
.TestResult()
218 result
.time
.end
= 1.2345
219 result
.result
= 'pass'
220 result
.out
= 'this is stdout'
221 result
.err
= 'this is stderr'
222 result
.command
= 'foo'
225 test
= backends
.junit
.JUnitBackend(str(p
))
226 test
.initialize(shared
.INITIAL_METADATA
)
227 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
230 result
.result
= 'fail'
231 with test
.write_test(grouptools
.join('a', 'test', 'test1')) as t
:
235 return str(p
.join('results.xml'))
237 def test_xml_well_formed(self
, test_file
):
238 """backends.junit.JUnitBackend.write_test: produces well formed xml."""
239 etree
.parse(test_file
)
241 @pytest.mark
.skipif(etree
.__name
__ != 'lxml.etree',
242 reason
="This test requires lxml")
243 def test_xml_valid(self
, test_file
):
244 """backends.junit.JUnitBackend.write_test: produces valid JUnit xml."""
245 # This XMLSchema class is unique to lxml
246 schema
= etree
.XMLSchema(file=JUNIT_SCHEMA
) # pylint: disable=no-member
247 with
open(test_file
, 'r') as f
:
248 assert schema
.validate(etree
.parse(f
))
251 class TestJUnitSubtestWriter(object):
252 """Tests for the JUnitWriter class."""
254 def test_junit_replace(self
, tmpdir
):
255 """backends.junit.JUnitBackend.write_test: grouptools.SEPARATOR is
258 result
= results
.TestResult()
259 result
.time
.end
= 1.2345
260 result
.out
= 'this is stdout'
261 result
.err
= 'this is stderr'
262 result
.command
= 'foo'
263 result
.subtests
['foo'] = 'pass'
264 result
.subtests
['bar'] = 'fail'
266 test
= backends
.junit
.JUnitBackend(str(tmpdir
),
268 test
.initialize(shared
.INITIAL_METADATA
)
269 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
273 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
274 test_value
= test_value
.getroot()
276 assert test_value
.find('.//testsuite/testsuite').attrib
['name'] == \
277 'piglit.a.group.test1'
279 def test_junit_replace_suffix(self
, tmpdir
):
280 """backends.junit.JUnitBackend.write_test: grouptools.SEPARATOR is
283 result
= results
.TestResult()
284 result
.time
.end
= 1.2345
285 result
.out
= 'this is stdout'
286 result
.err
= 'this is stderr'
287 result
.command
= 'foo'
288 result
.subtests
['foo'] = 'pass'
289 result
.subtests
['bar'] = 'fail'
291 test
= backends
.junit
.JUnitBackend(str(tmpdir
),
294 test
.initialize(shared
.INITIAL_METADATA
)
295 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
299 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
300 test_value
= test_value
.getroot()
302 suite
= test_value
.find('.//testsuite/testsuite')
303 assert suite
.attrib
['name'] == 'piglit.a.group.test1'
304 assert suite
.find('.//testcase[@name="{}"]'.format('foo.foo')) is not None
306 def test_subtest_skip(self
, tmpdir
):
307 result
= results
.TestResult()
308 result
.time
.end
= 1.2345
309 result
.out
= 'this is stdout'
310 result
.err
= 'this is stderr'
311 result
.command
= 'foo'
312 result
.subtests
['foo'] = 'pass'
313 result
.subtests
['bar'] = 'skip'
315 test
= backends
.junit
.JUnitBackend(str(tmpdir
),
317 test
.initialize(shared
.INITIAL_METADATA
)
318 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
322 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
323 test_value
= test_value
.getroot()
325 suite
= test_value
.find('.//testsuite/testsuite')
326 assert suite
.attrib
['name'] == 'piglit.a.group.test1'
327 assert suite
.find('.//testcase[@name="{}"]/skipped'.format('bar')) \
330 def test_result_skip(self
, tmpdir
):
331 result
= results
.TestResult()
332 result
.time
.end
= 1.2345
333 result
.out
= 'this is stdout'
334 result
.err
= 'this is stderr'
335 result
.command
= 'foo'
336 result
.result
= 'skip'
338 test
= backends
.junit
.JUnitBackend(str(tmpdir
),
340 test
.initialize(shared
.INITIAL_METADATA
)
341 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
345 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
346 test_value
= test_value
.getroot()
348 elem
= test_value
.find('.//testsuite/testcase[@name="test1"]/skipped')
349 assert elem
is not None
351 def test_classname(self
, tmpdir
):
352 result
= results
.TestResult()
353 result
.time
.end
= 1.2345
354 result
.out
= 'this is stdout'
355 result
.err
= 'this is stderr'
356 result
.command
= 'foo'
357 result
.subtests
['foo'] = 'pass'
358 result
.subtests
['bar'] = 'skip'
360 test
= backends
.junit
.JUnitBackend(str(tmpdir
),
362 test
.initialize(shared
.INITIAL_METADATA
)
363 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
367 test_value
= etree
.parse(str(tmpdir
.join('results.xml')))
368 test_value
= test_value
.getroot()
370 suite
= test_value
.find('.//testsuite/testsuite')
371 assert suite
.find('.//testcase[@classname="piglit.a.group.test1"]') \
374 class TestValid(object):
376 def test_file(self
, tmpdir
):
378 p
= tmpdir
.join('foo')
380 result
= results
.TestResult()
381 result
.time
.end
= 1.2345
382 result
.out
= 'this is stdout'
383 result
.err
= 'this is stderr'
384 result
.command
= 'foo'
386 result
.subtests
['foo'] = 'pass'
387 result
.subtests
['bar'] = 'fail'
389 test
= backends
.junit
.JUnitBackend(str(p
),
391 test
.initialize(shared
.INITIAL_METADATA
)
392 with test
.write_test(grouptools
.join('a', 'group', 'test1')) as t
:
395 result
.result
= 'fail'
396 with test
.write_test(grouptools
.join('a', 'test', 'test1')) as t
:
400 return str(p
.join('results.xml'))
402 def test_xml_well_formed(self
, test_file
):
403 """backends.junit.JUnitBackend.write_test: produces well formed xml."""
404 etree
.parse(test_file
)
406 @pytest.mark
.skipif(etree
.__name
__ != 'lxml.etree',
407 reason
="This test requires lxml")
408 def test_xml_valid(self
, test_file
):
409 """backends.junit.JUnitBackend.write_test: produces valid JUnit xml."""
410 # This XMLSchema class is unique to lxml
411 schema
= etree
.XMLSchema(file=JUNIT_SCHEMA
) # pylint: disable=no-member
412 with
open(test_file
, 'r') as f
:
413 assert schema
.validate(etree
.parse(f
))
416 class TestWriteResults(object):
417 """Tests for the write_results function."""
420 def setup_class(cls
):
421 """Setup values used by all tests."""
422 test
= results
.TestrunResult()
425 'uname': 'this is uname',
426 'glxinfo': 'glxinfo',
428 'wglinfo': 'wglinfo',
429 'lspci': 'this is lspci',
433 test
.options
= {'some': 'option'}
434 test
.time_elapsed
.end
= 1.23
435 another_test
= results
.TestResult()
436 another_test
.subtests
['foo'] = 'pass'
437 another_test
.subtests
['bar'] = 'skip'
438 test
.tests
= {'a test': results
.TestResult('pass'),
439 'another test': another_test
}
443 @pytest.mark
.parametrize('filepath', [
447 def test_write(self
, filepath
, tmpdir
):
448 """backends.json.write_results: writes a TestrunResult into a filepath.
450 p
= tmpdir
.join(filepath
)
451 assert not backends
.junit
.write_results(self
.test
, str(p
))
454 assert not backends
.junit
.write_results(self
.test
, str(p
),
458 def test_xml_well_formed(self
, tmpdir
):
459 """backends.json.write_results: writes a TestrunResult into a well
462 p
= tmpdir
.join('foo.xml')
463 assert not backends
.junit
.write_results(self
.test
, str(p
))
466 assert not backends
.junit
.write_results(self
.test
, str(p
),
470 @pytest.mark
.skipif(etree
.__name
__ != 'lxml.etree',
471 reason
="This test requires lxml")
472 def test_xml_valid(self
, tmpdir
):
473 """backends.json.write_results: writes a TestrunResult into a well
476 # This XMLSchema class is unique to lxml
477 schema
= etree
.XMLSchema(file=JUNIT_SCHEMA
) # pylint: disable=no-member
478 p
= tmpdir
.join('foo.xml')
479 assert not backends
.junit
.write_results(self
.test
, str(p
))
480 with p
.open('r') as f
:
481 assert schema
.validate(etree
.parse(f
))
483 assert not backends
.junit
.write_results(self
.test
, str(p
),
485 with p
.open('r') as f
:
486 assert schema
.validate(etree
.parse(f
))
488 def test_inst(self
, tmpdir
):
489 """backends.junit.write_results: test that the written JUnit loads
490 as a proper TestrunResult.
492 p
= tmpdir
.join('foo.xml')
493 assert not backends
.junit
.write_results(self
.test
, str(p
))
494 assert isinstance(backends
.junit
.load(str(p
), 'none'),
495 results
.TestrunResult
)
497 assert not backends
.junit
.write_results(self
.test
, str(p
),
499 assert isinstance(backends
.junit
.load(str(p
), 'none'),
500 results
.TestrunResult
)
502 @pytest.mark
.parametrize('filepath, exception', [
503 ('', FileNotFoundError
),
506 def test_bogus_filepath(self
, filepath
, exception
):
507 """backends.junit.write_results: raise with bogus filepaths
510 with pytest
.raises(exception
):
511 assert not backends
.junit
.write_results(self
.test
, filepath
)
513 with pytest
.raises(exception
):
514 assert not backends
.junit
.write_results(self
.test
, filepath
,