提交 d60991ff 编写于 作者: C Cleber Rosa

Result: port JSON result plugin

This moves all JSON result code to the plugin file.  With that, the
core avocado has no knowledge about this plugin, as it should be.
Still, the `results.json` is going to be generated by default, unless
the command line option `--json-job-result` is set to `off`.
Signed-off-by: NCleber Rosa <crosa@redhat.com>
上级 43349c11
......@@ -42,7 +42,6 @@ from . import output
from . import multiplexer
from . import tree
from . import test
from . import jsonresult
from . import replay
from .output import STD_OUTPUT
from .settings import settings
......@@ -280,11 +279,6 @@ class Job(object):
# If there are any active output plugins, let's use them
self._set_output_plugins()
# Setup the json plugin to output to the debug directory
json_file = os.path.join(self.logdir, 'results.json')
json_plugin = jsonresult.JSONResult(self, json_file)
self.result_proxy.add_output_plugin(json_plugin)
# Setup the html output to the results directory
if HTML_REPORT_SUPPORT:
html_file = os.path.join(self.logdir, 'html', 'results.html')
......
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat Inc. 2014
# Author: Ruda Moura <rmoura@redhat.com>
"""
JSON output module.
"""
import json
import logging
from .result import Result
class JSONResult(Result):
"""
JSON Test Result class.
"""
command_line_arg_name = '--json'
def __init__(self, job, force_json_file=None):
"""
:param job: Job which defines this result
:param force_json_file: Override the json output file location
"""
Result.__init__(self, job)
if force_json_file:
self.output = force_json_file
else:
self.output = getattr(self.args, 'json_output', '-')
self.json = None
self.log = logging.getLogger("avocado.app")
def start_tests(self):
"""
Called once before any tests are executed.
"""
Result.start_tests(self)
self.json = {'debuglog': self.logfile,
'tests': []}
def end_test(self, state):
"""
Called when the given test has been run.
:param state: result of :class:`avocado.core.test.Test.get_state`.
:type state: dict
"""
Result.end_test(self, state)
if 'job_id' not in self.json:
self.json['job_id'] = state.get('job_unique_id', "<unknown>")
t = {'test': str(state.get('name', "<unknown>")),
'url': str(state.get('name', "<unknown>")),
'start': state.get('time_start', -1),
'end': state.get('time_end', -1),
'time': state.get('time_elapsed', -1),
'status': state.get('status', {}),
'whiteboard': state.get('whiteboard', "<unknown>"),
'logdir': state.get('logdir', "<unknown>"),
'logfile': state.get('logfile', "<unknown>"),
'fail_reason': str(state.get('fail_reason', "<unknown>"))
}
self.json['tests'].append(t)
def _save_json(self):
with open(self.output, 'w') as j:
j.write(self.json)
def end_tests(self):
"""
Called once after all tests are executed.
"""
Result.end_tests(self)
self.json.update({
'total': self.tests_total,
'pass': self.passed,
'errors': self.errors,
'failures': self.failed,
'skip': self.skipped,
'time': self.tests_total_time
})
self.json = json.dumps(self.json)
if self.output == '-':
self.log.debug(self.json)
else:
self._save_json()
......@@ -10,20 +10,72 @@
# See LICENSE for more details.
#
# Copyright: Red Hat Inc. 2014
# Author: Ruda Moura <rmoura@redhat.com>
# Authors: Ruda Moura <rmoura@redhat.com>
# Cleber Rosa <crosa@redhat.com>
"""
JSON output module.
"""
import json
import logging
import os
from avocado.core.plugin_interfaces import CLI
from avocado.core.jsonresult import JSONResult
from avocado.core.result import register_test_result_class
from avocado.core.parser import FileOrStdoutAction
from avocado.core.plugin_interfaces import CLI, Result
class JSON(CLI):
UNKNOWN = '<unknown>'
class JSONResult(Result):
def _render(self, result):
tests = []
for test in result.tests:
tests.append({'test': str(test.get('name', UNKNOWN)),
'url': str(test.get('name', UNKNOWN)),
'start': test.get('time_start', -1),
'end': test.get('time_end', -1),
'time': test.get('time_elapsed', -1),
'status': test.get('status', {}),
'whiteboard': test.get('whiteboard', UNKNOWN),
'logdir': test.get('logdir', UNKNOWN),
'logfile': test.get('logfile', UNKNOWN),
'fail_reason': str(test.get('fail_reason', UNKNOWN))})
content = {'job_id': result.job_unique_id,
'debuglog': result.logfile,
'tests': tests,
'total': result.tests_total,
'pass': result.passed,
'errors': result.errors,
'failures': result.failed,
'skip': result.skipped,
'time': result.tests_total_time}
return json.dumps(content)
def render(self, result, job):
if not (hasattr(job.args, 'json_job_result') or
hasattr(job.args, 'json_output')):
return
content = self._render(result)
if getattr(job.args, 'json_job_result', 'off') == 'on':
json_path = os.path.join(job.logdir, 'results.json')
with open(json_path, 'w') as json_file:
json_file.write(content)
json_path = getattr(job.args, 'json_output', 'None')
if json_path is not None:
if json_path == '-':
log = logging.getLogger("avocado.app")
log.debug(content)
else:
with open(json_path, 'w') as json_file:
json_file.write(content)
class JSONCLI(CLI):
"""
JSON output
......@@ -43,6 +95,11 @@ class JSON(CLI):
help='Enable JSON result format and write it to FILE. '
"Use '-' to redirect to the standard output.")
run_subcommand_parser.output.add_argument(
'--json-job-result', dest='json_job_result',
choices=('on', 'off'), default='on',
help=('Enables default JSON result in the job results directory. '
'File will be named "results.json".'))
def run(self, args):
if 'json_output' in args and args.json_output is not None:
register_test_result_class(args, JSONResult)
pass
......@@ -6,8 +6,9 @@ import tempfile
import shutil
from avocado import Test
from avocado.core import jsonresult
from avocado.core import job
from avocado.core.result import Result
from avocado.plugins import jsonresult
class FakeJob(object):
......@@ -28,10 +29,11 @@ class JSONResultTest(unittest.TestCase):
self.tmpfile = tempfile.mkstemp()
self.tmpdir = tempfile.mkdtemp(prefix='avocado_' + __name__)
args = argparse.Namespace(json_output=self.tmpfile[1])
self.test_result = jsonresult.JSONResult(FakeJob(args))
self.job = job.Job(args)
self.test_result = Result(FakeJob(args))
self.test_result.filename = self.tmpfile[1]
self.test_result.start_tests()
self.test1 = SimpleTest(job=job.Job(), base_logdir=self.tmpdir)
self.test1 = SimpleTest(job=self.job, base_logdir=self.tmpdir)
self.test1.status = 'PASS'
self.test1.time_elapsed = 1.23
......@@ -44,8 +46,9 @@ class JSONResultTest(unittest.TestCase):
self.test_result.start_test(self.test1)
self.test_result.end_test(self.test1.get_state())
self.test_result.end_tests()
self.assertTrue(self.test_result.json)
with open(self.test_result.filename) as fp:
json_result = jsonresult.JSONResult()
json_result.render(self.test_result, self.job)
with open(self.job.args.json_output) as fp:
j = fp.read()
obj = json.loads(j)
self.assertTrue(obj)
......@@ -78,7 +81,9 @@ class JSONResultTest(unittest.TestCase):
run_fake_status({"status": ""})
# Postprocess
self.test_result.end_tests()
res = json.loads(self.test_result.json)
json_result = jsonresult.JSONResult()
json_result.render(self.test_result, self.job)
res = json.loads(open(self.job.args.json_output).read())
check_item("[pass]", res["pass"], 2)
check_item("[errors]", res["errors"], 4)
check_item("[failures]", res["failures"], 1)
......@@ -94,7 +99,9 @@ class JSONResultTest(unittest.TestCase):
self.test_result.start_test(self.test1)
self.test_result.check_test(self.test1.get_state())
self.test_result.end_tests()
res = json.loads(self.test_result.json)
json_result = jsonresult.JSONResult()
json_result.render(self.test_result, self.job)
res = json.loads(open(self.job.args.json_output).read())
check_item("[total]", res["total"], 1)
check_item("[skip]", res["skip"], 0)
check_item("[pass]", res["pass"], 1)
......
......@@ -132,7 +132,7 @@ if __name__ == '__main__':
'gdb = avocado.plugins.gdb:GDB',
'wrapper = avocado.plugins.wrapper:Wrapper',
'xunit = avocado.plugins.xunit:XUnitCLI',
'json = avocado.plugins.json:JSON',
'json = avocado.plugins.jsonresult:JSONCLI',
'journal = avocado.plugins.journal:Journal',
'html = avocado.plugins.html:HTML',
'remote = avocado.plugins.remote:Remote',
......@@ -156,6 +156,7 @@ if __name__ == '__main__':
],
'avocado.plugins.result': [
'xunit = avocado.plugins.xunit:XUnitResult',
'json = avocado.plugins.jsonresult:JSONResult',
],
},
zip_safe=False,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册