Robot Framework
xunitwriter.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 from robot.result import ResultVisitor
17 from robot.utils import XmlWriter
18 
19 
21 
22  def __init__(self, execution_result):
23  self._execution_result_execution_result = execution_result
24 
25  def write(self, output):
26  xml_writer = XmlWriter(output, usage='xunit')
27  writer = XUnitFileWriter(xml_writer)
28  self._execution_result_execution_result.visit(writer)
29 
30 
31 
36 class XUnitFileWriter(ResultVisitor):
37 
38  def __init__(self, xml_writer):
39  self._writer_writer = xml_writer
40 
41  def start_suite(self, suite):
42  stats = suite.statistics # Accessing property only once.
43  attrs = {'name': suite.name,
44  'tests': f'{stats.total}',
45  'errors': '0',
46  'failures': f'{stats.failed}',
47  'skipped': f'{stats.skipped}',
48  'time': self._time_as_seconds_time_as_seconds(suite.elapsedtime),
49  'timestamp' : self._starttime_to_isoformat_starttime_to_isoformat(suite.starttime)}
50  self._writer_writer.start('testsuite', attrs)
51 
52  def end_suite(self, suite):
53  if suite.metadata or suite.doc:
54  self._writer_writer.start('properties')
55  if suite.doc:
56  self._writer_writer.element('property', attrs={'name': 'Documentation', 'value': suite.doc})
57  for meta_name, meta_value in suite.metadata.items():
58  self._writer_writer.element('property', attrs={'name': meta_name, 'value': meta_value})
59  self._writer_writer.end('properties')
60  self._writer_writer.end('testsuite')
61 
62  def visit_test(self, test):
63  self._writer_writer.start('testcase',
64  {'classname': test.parent.longname,
65  'name': test.name,
66  'time': self._time_as_seconds_time_as_seconds(test.elapsedtime)})
67  if test.failed:
68  self._writer_writer.element('failure', attrs={'message': test.message,
69  'type': 'AssertionError'})
70  if test.skipped:
71  self._writer_writer.element('skipped', attrs={'message': test.message,
72  'type': 'SkipExecution'})
73  self._writer_writer.end('testcase')
74 
75  def _time_as_seconds(self, millis):
76  return format(millis / 1000, '.3f')
77 
78  def visit_keyword(self, kw):
79  pass
80 
81  def visit_statistics(self, stats):
82  pass
83 
84  def visit_errors(self, errors):
85  pass
86 
87  def end_result(self, result):
88  self._writer.close()
89 
90  def _starttime_to_isoformat(self, stime):
91  if not stime:
92  return None
93  return f'{stime[:4]}-{stime[4:6]}-{stime[6:8]}T{stime[9:22]}000'
Provides an xUnit-compatible result file.
Definition: xunitwriter.py:36
def __init__(self, execution_result)
Definition: xunitwriter.py:22