# Copyright 2008-2015 Nokia Networks
# Copyright 2016- Robot Framework Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from robot.model import SuiteVisitor
from robot.result import TestCase, TestSuite
from robot.utils import plural_or_not as s, secs_to_timestr
from .highlighting import HighlightingStream
from ..loggerapi import LoggerApi
[docs]
class DottedOutput(LoggerApi):
def __init__(self, width=78, colors='AUTO', stdout=None, stderr=None):
self.width = width
self.stdout = HighlightingStream(stdout or sys.__stdout__, colors)
self.stderr = HighlightingStream(stderr or sys.__stderr__, colors)
self.markers_on_row = 0
[docs]
def start_suite(self, data, result):
if not data.parent:
count = data.test_count
ts = ('test' if not data.rpa else 'task') + s(count)
self.stdout.write(f"Running suite '{result.name}' with {count} {ts}.\n")
self.stdout.write('=' * self.width + '\n')
[docs]
def end_test(self, data, result):
if self.markers_on_row == self.width:
self.stdout.write('\n')
self.markers_on_row = 0
self.markers_on_row += 1
if result.passed:
self.stdout.write('.')
elif result.skipped:
self.stdout.highlight('s', 'SKIP')
elif result.tags.robot('exit'):
self.stdout.write('x')
else:
self.stdout.highlight('F', 'FAIL')
[docs]
def end_suite(self, data, result):
if not data.parent:
self.stdout.write('\n')
StatusReporter(self.stdout, self.width).report(result)
self.stdout.write('\n')
[docs]
def message(self, msg):
if msg.level in ('WARN', 'ERROR'):
self.stderr.error(msg.message, msg.level)
[docs]
def result_file(self, kind, path):
self.stdout.write(f"{kind+':':8} {path}\n")
[docs]
class StatusReporter(SuiteVisitor):
def __init__(self, stream, width):
self.stream = stream
self.width = width
[docs]
def report(self, suite: TestSuite):
suite.visit(self)
stats = suite.statistics
ts = ('test' if not suite.rpa else 'task') + s(stats.total)
elapsed = secs_to_timestr(suite.elapsed_time)
self.stream.write(f"{'=' * self.width}\nRun suite '{suite.name}' with "
f"{stats.total} {ts} in {elapsed}.\n\n")
ed = 'ED' if suite.status != 'SKIP' else 'PED'
self.stream.highlight(suite.status + ed, suite.status)
self.stream.write(f'\n{stats.message}\n')
[docs]
def visit_test(self, test: TestCase):
if test.failed and not test.tags.robot('exit'):
self.stream.write('-' * self.width + '\n')
self.stream.highlight('FAIL')
self.stream.write(f': {test.full_name}\n{test.message.strip()}\n')