Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1 @@
#

View file

@ -0,0 +1,5 @@
[
"communications/facebook/test/unit/facebook_connector_test.js",
"ftu/test/unit/tutorial_test.js",
"keyboard/test/unit/imes/jspinyin/jspinyin_test.js"
]

View file

@ -0,0 +1,265 @@
import json
import logging
import mozlog
from mozprofile import Profile
from mozrunner import Runner
from optparse import OptionParser
import os
import shutil
import sys
import tempfile
import time
import tornado.websocket
import tornado.ioloop
import tornado.httpserver
import traceback
import reporters
class TestAgentServer(tornado.websocket.WebSocketHandler):
increment = 0
envs = {}
pending_envs = []
passes = 0
failures = 0
current_test = 'None'
timer = None
timeout = 120
def initialize(self, tests=None, runner=None, logger=None):
self.tests = tests
self.runner = runner
self.logger = logger
def emit(self, event, data):
command = (event, data)
self.write_message(json.dumps(command))
def open(self):
self.increment = self.increment + 1
self.run_tests(self.tests)
def timer_fn(self):
message = "Timed out after %d seconds" % self.timeout
self.logger.test_end(self.current_test, status='TIMEOUT', message=message)
self.runner.cleanup()
sys.exit(1)
def run_tests(self, tests):
self.tests = tests
self.run_next_test()
def run_next_test(self):
self.current_test = self.tests.pop()
self.emit('run tests', {'tests': ["/%s" % self.current_test] })
def on_envs_complete(self):
exitCode = 0
if self.failures or not self.passes:
# Magic non-zero value to match the expectations of the mozharness
# script.
exitCode = 10
for env in self.envs:
if len(self.envs[env].output):
self.logger.info('\ntest report: (' + env + ')')
self.logger.info('\n'.join(self.envs[env].output))
self.close()
self.logger.info('passed: %d' % self.passes)
self.logger.info('failed: %d' % self.failures)
self.logger.info('todo: 0')
self.logger.suite_end()
crashed = self.runner.cleanup()
sys.exit(1 if crashed else exitCode)
def handle_event(self, event, data):
if event == 'set test envs':
self.pending_envs = data[0]
if event == 'test data':
# the 'test data' event is a nested event
# inside of the main event body. It is a direct
# copy of the mocha reporter data with the addition
# of the 'testAgentEnvId' which is used to group
# the results of different test runs.
(test_event, test_data) = json.loads(data[0])
# gaia & test agent both use environment ids because
# they nest test runners. This is a very special case
# most test agent runners will not do this so add a
# fallback environment name to make this simpler.
if ('testAgentEnvId' in test_data):
test_env = test_data['testAgentEnvId']
else:
test_env = 'global'
# add to pending
if (test_event == 'start'):
self.envs[test_env] = reporters.StructuredLogReporter(stream=False,
logger=self.logger)
# don't process out of order commands
if not (test_env in self.envs):
return
self.envs[test_env].handle_event(test_event, test_data, self.current_test)
# remove from pending and trigger test complete check.
if (test_event == 'end'):
if test_env in self.pending_envs:
idx = self.pending_envs.index(test_env)
del self.pending_envs[idx]
self.passes += self.envs[test_env].passes
self.failures += self.envs[test_env].failures
if self.tests:
self.run_next_test()
# now that envs are totally complete show results.
elif (len(self.pending_envs) == 0):
self.on_envs_complete()
def on_close(self):
self.logger.warning("Build shut down unexpectedly")
self.runner.cleanup()
sys.exit(1)
def on_message(self, message):
# Instantiate a timer that will get called after self.timeout seconds;
# this timer is used to detect hangs/crashes and shut down the test
# run after checking for crashes.
loop = tornado.ioloop.IOLoop.instance()
if self.timer:
loop.remove_timeout(self.timer)
self.timer = loop.add_timeout(time.time() + self.timeout, self.timer_fn)
command = json.loads(message)
# test agent protocol always uses the [event, data] format.
self.handle_event(command[0], [command[1]])
class GaiaUnitTestRunner(object):
def __init__(self, binary=None, profile=None, symbols_path=None,
browser_arg=()):
self.binary = binary
self.profile = profile
self.symbols_path = symbols_path
self.browser_arg = browser_arg
def run(self):
self.profile_dir = os.path.join(tempfile.mkdtemp(suffix='.gaiaunittest'),
'profile')
shutil.copytree(self.profile, self.profile_dir)
cmdargs = ['--runapp', 'Test Agent']
if self.browser_arg:
cmdargs += list(self.browser_arg)
profile = Profile(profile=self.profile_dir)
self.runner = Runner(binary=self.binary,
profile=profile,
clean_profile=False,
cmdargs=cmdargs,
symbols_path=self.symbols_path)
self.runner.start()
def cleanup(self):
print 'checking for crashes'
crashed = self.runner.check_for_crashes()
self.runner.cleanup()
shutil.rmtree(os.path.dirname(self.profile_dir))
return crashed
__del__ = cleanup
def cli():
parser = OptionParser(usage='%prog [options] <test_file> <test_file> ...')
parser.add_option("--binary",
action="store", dest="binary",
default=None,
help="path to B2G desktop build binary")
parser.add_option("--profile",
action="store", dest="profile",
default=None,
help="path to gaia profile directory")
parser.add_option("--symbols-path",
action="store", dest="symbols_path",
default=None,
help="path or url to breakpad symbols")
parser.add_option("--browser-arg",
action="append", dest="browser_arg",
default=[],
help="optional command-line arg to pass to the browser")
mozlog.structured.commandline.add_logging_group(parser)
options, tests = parser.parse_args()
if not options.binary or not options.profile:
parser.print_usage()
parser.exit('--binary and --profile required')
if not tests:
# Read in a list of tests to skip from disabled.json, if it exists;
# disabled.json should contain filenames with paths relative to the
# apps directory, e.g., "wallpaper/test/unit/pick_test.js".
disabled = []
disabled_file = os.path.join(os.path.dirname(__file__), 'disabled.json')
if os.access(disabled_file, os.F_OK):
with open(disabled_file, 'r') as f:
disabled_contents = f.read()
try:
disabled = json.loads(disabled_contents)
except:
traceback.print_exc()
print "Error while decoding disabled.json; please make sure this file has valid JSON syntax."
sys.exit(1)
# build a list of tests
for path in ('apps', 'tv_apps'):
appsdir = os.path.join(os.path.dirname(os.path.abspath(options.profile)), path)
for root, dirs, files in os.walk(appsdir):
files.sort()
for f in files:
# only include tests in a 'unit' directory
roots = root.split(os.path.sep)
if 'unit' in roots:
full_path = os.path.relpath(os.path.join(root, f), appsdir)
if full_path.endswith('_test.js') and full_path not in disabled:
tests.append(full_path)
logger_defaults = { 'tbpl': sys.stdout }
upload_dir = os.environ.get('MOZ_UPLOAD_DIR')
if upload_dir:
logger_defaults['raw'] = open(os.path.join(upload_dir, "gu_structured_full.log"), "w")
logger = mozlog.structured.commandline.setup_logging('gaia-unit-tests',
options,
logger_defaults)
logger.suite_start(tests)
runner = GaiaUnitTestRunner(binary=options.binary,
profile=options.profile,
symbols_path=options.symbols_path,
browser_arg=options.browser_arg)
runner.run()
logger.info('starting WebSocket Server')
application = tornado.web.Application([
(r"/", TestAgentServer, {'tests': tests,
'runner': runner,
'logger': logger}),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8789)
tornado.ioloop.IOLoop.instance().start()
if __name__ == '__main__':
cli()

View file

@ -0,0 +1,4 @@
from base import Base
from spec import Spec
from tbpl import TBPLLogger
from structuredlog import StructuredLogReporter

View file

@ -0,0 +1,107 @@
""" Base class which reporters should all inherit from.
The design is based on the original Mocha (javascript)
reporter architecture.
"""
PASS_MARK = u"\u2713"
FAIL_MARK = u"\u2716"
class Base:
def __init__(self, stream=True):
# reporter output
self.output = []
self.stream_output = stream
# test details
self.passes = 0
self.failures = 0
self.pending = 0
self.duration = 0
self.failed_tests = []
# analytics
self.indent = 0
self.tests = 0
self.suites = 0
def formatError(self, data):
if not ('err' in data):
return ''
err = data['err']
out = data['fullTitle']
out += '\n ' + err['message'] + '\n'
def indent(item):
return ' ' + item
if ('stack' in err):
out += '\n'.join(map(indent, err['stack'].split('\n')))
return out
def epilogue(self):
self.report('\n')
if self.failed_tests:
for test in self.failed_tests:
self.report(self.formatError(test))
if self.failures:
self.report(FAIL_MARK + ' %d of %d test(s) failed' % (self.failures, self.tests))
else:
self.report(PASS_MARK + ' %d test(s) complete' % (self.tests))
self.report('took %d ms' % (self.duration))
def on_end(self, data):
self.epilogue()
def report(self, string, indent=False):
""" When self.stream_output is true will instantly
print results otherwise the results are added
to self.output.
"""
if indent:
string = (' ' * self.indent) + string
if self.stream_output:
print string
else:
self.output.append(string)
def handle_event(self, event, data, testname):
""" handles test events. The base class
is mostly responsible for incrementing the
reusable logic that the children then use.
"""
if event == 'pass':
self.passes += 1
if event == 'fail':
self.failures += 1
self.failed_tests.append(data)
if event == 'pending':
self.pending += 1
if event == 'suite':
self.indent += 1
if event == 'suite end':
self.indent -= 1
if event == 'end':
self.tests = data['tests']
self.duration = data['duration']
self.suites = data['suites']
methodName = 'on_' + event.replace(' ', '_')
if (hasattr(self, methodName)):
getattr(self, methodName)(data, testname)

View file

@ -0,0 +1,19 @@
from base import Base
from base import FAIL_MARK, PASS_MARK
class Spec(Base):
def on_test_end(self, data, testname):
mark = ' ';
if data['state'] == 'passed':
mark += PASS_MARK
else:
mark += FAIL_MARK
self.report(' ' + data['title'] + mark, True)
def on_suite(self, data, testname):
#print self.indent
self.report(data['title'], True)

View file

@ -0,0 +1,53 @@
from base import Base
import json
class StructuredLogReporter(Base):
def __init__(self, *args, **kwargs):
self.logger = kwargs.pop('logger')
Base.__init__(self, *args, **kwargs)
def log_message(self, log_type, data, testname):
message = []
for item in data.get('messages', []):
if isinstance(item, basestring):
message += [item]
else:
message += [json.dumps(item)]
self.logger.info('TEST-INFO | %s | %s: %s' % (testname, log_type, ' '.join(message)))
def on_log(self, data, testname):
self.log_message('log', data, testname)
def on_info(self, data, testname):
self.log_message('info', data, testname)
def on_warn(self, data, testname):
self.log_message('warn', data, testname)
def on_dir(self, data, testname):
self.log_message('dir', data, testname)
def on_error(self, data, testname):
self.log_message('error', data, testname)
def on_pass(self, data, testname):
self.logger.test_status(testname, data['fullTitle'], 'PASS')
def on_fail(self, data, testname):
subtest = data['fullTitle']
msg = None
stack = None
if 'err' in data:
if 'message' in data['err']:
msg = data['err']['message']
if 'stack' in data['err']:
stack = '\n'.join([' %s' % x for x in data['err']['stack'].split('\n')])
self.logger.test_status(testname, subtest, status='FAIL', message=msg, stack=stack)
def on_start(self, data, testname):
self.logger.test_start(testname)
def on_end(self, data, testname):
self.logger.test_end(testname, 'OK')
self.logger.info('suite results (pass/fail): %d/%d' %
(self.passes, self.failures))

View file

@ -0,0 +1,30 @@
from base import Base
class TBPLLogger(Base):
def __init__(self, *args, **kwargs):
self.logger = kwargs['logger']
del kwargs['logger']
Base.__init__(self, *args, **kwargs)
def on_pass(self, data, testname):
self.logger.testPass("%s | %s" % (testname, data['fullTitle']))
def on_fail(self, data, testname):
msg = data['fullTitle']
if 'err' in data:
if 'message' in data['err']:
msg += " | %s" % data['err']['message']
self.logger.testFail("%s | %s" % (testname, msg))
if 'err' in data and 'stack' in data['err']:
self.logger.info('stack trace:\n%s' % '\n'.join(' %s' % x for x in data['err']['stack'].split('\n')))
def on_suite(self, data, testname):
self.logger.testStart("%s | %s" % (testname, data['title']))
def on_suite_end(self, data, testname):
self.logger.testEnd("%s | %s" % (testname, data['title']))
def on_end(self, data, testname):
self.logger.info('suite results (pass/fail): %d/%d' %
(self.passes, self.failures))

View file

@ -0,0 +1,43 @@
["set test envs",["TA"]]
["test data","[\"start\",{\"total\":3,\"testAgentEnvId\":\"TA\"}]"]
start {u'total': 3, u'testAgentEnvId': u'TA'}
["test data","[\"suite\",{\"title\":\"\",\"fullTitle\":\"\",\"root\":true,\"indentation\":0,\"testAgentEnvId\":\"TA\"}]"]
suite {u'fullTitle': u'', u'root': True, u'testAgentEnvId': u'TA', u'indentation': 0, u'title': u''}
["test data","[\"suite\",{\"title\":\"test-agent/inspect\",\"fullTitle\":\"test-agent/inspect\",\"root\":false,\"indentation\":1,\"testAgentEnvId\":\"TA\"}]"]
suite {u'fullTitle': u'test-agent/inspect', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 1, u'title': u'test-agent/inspect'}
["test data","[\"suite\",{\"title\":\".inspect\",\"fullTitle\":\"test-agent/inspect .inspect\",\"root\":false,\"indentation\":2,\"testAgentEnvId\":\"TA\"}]"]
suite {u'fullTitle': u'test-agent/inspect .inspect', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 2, u'title': u'.inspect'}
["test data","[\"test\",{\"fn\":\"function () {\\n expect(0).to.be(1);\\n }\",\"title\":\"should fail\",\"fullTitle\":\"test-agent/inspect .inspect should fail\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test {u'fullTitle': u'test-agent/inspect .inspect should fail', u'type': u'test', u'testAgentEnvId': u'TA', u'fn': u'function () {\n expect(0).to.be(1);\n }', u'title': u'should fail'}
["test data","[\"fail\",{\"fn\":\"function () {\\n expect(0).to.be(1);\\n }\",\"title\":\"should fail\",\"fullTitle\":\"test-agent/inspect .inspect should fail\",\"state\":\"failed\",\"type\":\"test\",\"err\":{\"stack\":\"Error: expected 0 to equal 1\\n at assert (http://localhost:7771/vendor/expect.js:99)\\n at equal (http://localhost:7771/vendor/expect.js:203)\\n at (anonymous) (http://localhost:7771/vendor/expect.js:73)\\n at (anonymous) (http://localhost:7771/test/test-agent/inspect-test.js:20)\\n at run (http://localhost:7771/vendor/mocha/mocha.js:3001)\\n at runTest (http://localhost:7771/vendor/mocha/mocha.js:3305)\\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3349)\\n at next (http://localhost:7771/vendor/mocha/mocha.js:3233)\\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3242)\\n at next (http://localhost:7771/vendor/mocha/mocha.js:3192)\\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3210)\\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:4022)\\n\",\"message\":\"expected 0 to equal 1\",\"type\":\"Error\",\"constructorName\":\"Error\",\"expected\":null,\"actual\":null},\"testAgentEnvId\":\"TA\"}]"]
fail {u'err': {u'actual': None, u'constructorName': u'Error', u'expected': None, u'message': u'expected 0 to equal 1', u'type': u'Error', u'stack': u'Error: expected 0 to equal 1\n at assert (http://localhost:7771/vendor/expect.js:99)\n at equal (http://localhost:7771/vendor/expect.js:203)\n at (anonymous) (http://localhost:7771/vendor/expect.js:73)\n at (anonymous) (http://localhost:7771/test/test-agent/inspect-test.js:20)\n at run (http://localhost:7771/vendor/mocha/mocha.js:3001)\n at runTest (http://localhost:7771/vendor/mocha/mocha.js:3305)\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3349)\n at next (http://localhost:7771/vendor/mocha/mocha.js:3233)\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3242)\n at next (http://localhost:7771/vendor/mocha/mocha.js:3192)\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:3210)\n at (anonymous) (http://localhost:7771/vendor/mocha/mocha.js:4022)\n'}, u'title': u'should fail', u'state': u'failed', u'testAgentEnvId': u'TA', u'fullTitle': u'test-agent/inspect .inspect should fail', u'type': u'test', u'fn': u'function () {\n expect(0).to.be(1);\n }'}
["test data","[\"test end\",{\"fn\":\"function () {\\n expect(0).to.be(1);\\n }\",\"title\":\"should fail\",\"fullTitle\":\"test-agent/inspect .inspect should fail\",\"state\":\"failed\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test end {u'title': u'should fail', u'state': u'failed', u'testAgentEnvId': u'TA', u'fullTitle': u'test-agent/inspect .inspect should fail', u'type': u'test', u'fn': u'function () {\n expect(0).to.be(1);\n }'}
["test data","[\"suite\",{\"title\":\"without color\",\"fullTitle\":\"test-agent/inspect .inspect without color\",\"root\":false,\"indentation\":3,\"testAgentEnvId\":\"TA\"}]"]
suite {u'fullTitle': u'test-agent/inspect .inspect without color', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 3, u'title': u'without color'}
["test data","[\"test\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect without color should return formatted string\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test {u'fullTitle': u'test-agent/inspect .inspect without color should return formatted string', u'type': u'test', u'testAgentEnvId': u'TA', u'fn': u"function () {\n var result = TestAgent.inspect(object);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }", u'title': u'should return formatted string'}
["test data","[\"pass\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect without color should return formatted string\",\"duration\":13,\"state\":\"passed\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
pass {u'title': u'should return formatted string', u'state': u'passed', u'testAgentEnvId': u'TA', u'duration': 13, u'fullTitle': u'test-agent/inspect .inspect without color should return formatted string', u'type': u'test', u'fn': u"function () {\n var result = TestAgent.inspect(object);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }"}
["test data","[\"test end\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect without color should return formatted string\",\"duration\":13,\"state\":\"passed\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test end {u'title': u'should return formatted string', u'state': u'passed', u'testAgentEnvId': u'TA', u'duration': 13, u'fullTitle': u'test-agent/inspect .inspect without color should return formatted string', u'type': u'test', u'fn': u"function () {\n var result = TestAgent.inspect(object);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }"}
["test data","[\"suite end\",{\"title\":\"without color\",\"fullTitle\":\"test-agent/inspect .inspect without color\",\"root\":false,\"indentation\":3,\"testAgentEnvId\":\"TA\"}]"]
suite end {u'fullTitle': u'test-agent/inspect .inspect without color', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 3, u'title': u'without color'}
["test data","[\"suite\",{\"title\":\"with color\",\"fullTitle\":\"test-agent/inspect .inspect with color\",\"root\":false,\"indentation\":3,\"testAgentEnvId\":\"TA\"}]"]
suite {u'fullTitle': u'test-agent/inspect .inspect with color', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 3, u'title': u'with color'}
["test data","[\"test\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object, false, 2, true);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect with color should return formatted string\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test {u'fullTitle': u'test-agent/inspect .inspect with color should return formatted string', u'type': u'test', u'testAgentEnvId': u'TA', u'fn': u"function () {\n var result = TestAgent.inspect(object, false, 2, true);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }", u'title': u'should return formatted string'}
["test data","[\"pass\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object, false, 2, true);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect with color should return formatted string\",\"duration\":15,\"state\":\"passed\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
pass {u'title': u'should return formatted string', u'state': u'passed', u'testAgentEnvId': u'TA', u'duration': 15, u'fullTitle': u'test-agent/inspect .inspect with color should return formatted string', u'type': u'test', u'fn': u"function () {\n var result = TestAgent.inspect(object, false, 2, true);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }"}
["test data","[\"test end\",{\"fn\":\"function () {\\n var result = TestAgent.inspect(object, false, 2, true);\\n expect(result).to.contain('error');\\n expect(result).to.contain('details');\\n expect(result).to.contain('three');\\n }\",\"title\":\"should return formatted string\",\"fullTitle\":\"test-agent/inspect .inspect with color should return formatted string\",\"duration\":15,\"state\":\"passed\",\"type\":\"test\",\"testAgentEnvId\":\"TA\"}]"]
test end {u'title': u'should return formatted string', u'state': u'passed', u'testAgentEnvId': u'TA', u'duration': 15, u'fullTitle': u'test-agent/inspect .inspect with color should return formatted string', u'type': u'test', u'fn': u"function () {\n var result = TestAgent.inspect(object, false, 2, true);\n expect(result).to.contain('error');\n expect(result).to.contain('details');\n expect(result).to.contain('three');\n }"}
["test data","[\"suite end\",{\"title\":\"with color\",\"fullTitle\":\"test-agent/inspect .inspect with color\",\"root\":false,\"indentation\":3,\"testAgentEnvId\":\"TA\"}]"]
suite end {u'fullTitle': u'test-agent/inspect .inspect with color', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 3, u'title': u'with color'}
["test data","[\"suite end\",{\"title\":\".inspect\",\"fullTitle\":\"test-agent/inspect .inspect\",\"root\":false,\"indentation\":2,\"testAgentEnvId\":\"TA\"}]"]
suite end {u'fullTitle': u'test-agent/inspect .inspect', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 2, u'title': u'.inspect'}
["test data","[\"suite end\",{\"title\":\"test-agent/inspect\",\"fullTitle\":\"test-agent/inspect\",\"root\":false,\"indentation\":1,\"testAgentEnvId\":\"TA\"}]"]
suite end {u'fullTitle': u'test-agent/inspect', u'root': False, u'testAgentEnvId': u'TA', u'indentation': 1, u'title': u'test-agent/inspect'}
["test data","[\"suite end\",{\"title\":\"\",\"fullTitle\":\"\",\"root\":true,\"indentation\":0,\"testAgentEnvId\":\"TA\"}]"]
suite end {u'fullTitle': u'', u'root': True, u'testAgentEnvId': u'TA', u'indentation': 0, u'title': u''}
["test data","[\"end\",{\"suites\":4,\"tests\":3,\"passes\":2,\"pending\":0,\"failures\":1,\"start\":\"2012-10-13T03:02:43.824Z\",\"end\":\"2012-10-13T03:02:43.934Z\",\"duration\":110,\"testAgentEnvId\":\"TA\"}]"]
end {u'suites': 4, u'tests': 3, u'end': u'2012-10-13T03:02:43.934Z', u'passes': 2, u'start': u'2012-10-13T03:02:43.824Z', u'testAgentEnvId': u'TA', u'duration': 110, u'failures': 1, u'pending': 0}

View file

@ -0,0 +1,82 @@
import unittest
from gaia_unit_test.reporters.base import Base
import factory
class BaseExtended(Base):
def __init__(self, flag):
Base.__init__(self, flag)
self.calledWith = None
# whitespace case
def on_test_end(self, data):
self.calledWith = data
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.subject = Base(False)
def test_initailize(self):
self.assertEqual(self.subject.passes, 0)
self.assertEqual(self.subject.failures, 0)
self.assertEqual(self.subject.duration, 0)
self.assertEqual(self.subject.indent, 0)
def test_report(self):
subject = self.subject
subject.report('foo')
self.assertEqual(subject.output[0], 'foo')
subject.indent = 2
subject.report('xfoo', True)
self.assertEqual(subject.output[1], ' xfoo')
def test_handle_event(self):
subject = self.subject
# pass
subject.handle_event('pass', factory.passed())
self.assertEqual(subject.passes, 1)
# fail
expected_fail = factory.failed()
subject.handle_event('fail', expected_fail)
self.assertEqual(subject.failures, 1)
self.assertEqual(subject.failed_tests[0], expected_fail)
# indent
subject.handle_event('suite', factory.suite())
self.assertEqual(subject.indent, 1)
subject.handle_event('suite end', factory.suite())
self.assertEqual(subject.indent, 0)
# end
subject.handle_event('end', {
'tests': 10,
'duration': 123,
'suites': 10
})
self.assertEqual(subject.tests, 10)
self.assertEqual(subject.duration, 123)
self.assertEqual(subject.suites, 10)
def test_handle_event_extended(self):
subject = BaseExtended(False)
inputObj = {'foo': 'bar'}
subject.handle_event('test end', inputObj)
self.assertDictContainsSubset(inputObj, subject.calledWith)
self.calledWith = None
# should be silently ignored...
subject.handle_event('random thing', 'foo')
self.assertEqual(self.calledWith, None)
if __name__ == '__main__':
unittest.main(verbosity=2)

View file

@ -0,0 +1,17 @@
def passed():
return {};
def failed():
return {};
def suite():
return {};
def suite_end():
return {};
def test():
return {};
def test_end():
return {};