[IMP] core: reporting after tests

Currently there are a few issues with testing reporting (at the
command-line):

1. there is a global report after at_install tests, but it gets
   "scrolled off" by long post_install tests, and is thus easy to
   miss
2. with test tags, it's easy to fat finger a typo and run 0 tests,
   which look like everything's running fine (no failure)

To improve this, print a global report at shutdown (in
`--stop-after-init` mode if tests are enabled) which recapitulates the
test results *and prints a warning if no tests were run at all*.

Also update the reporting collection to make this more reliable:

* have `run_unit_tests` return `None` if it has run no tests, the
  assertion reporting machinery counts this as neither success nor
  failure which is exactly what we want
* have load_test only report a success *if files were actually
  loaded* (by having `load_data` return that information)

Task 2301268

closes odoo/odoo#54812

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Xavier Morel
2020-07-27 09:30:51 +00:00
parent 297c3d8378
commit 92903e22f8
3 changed files with 25 additions and 8 deletions
+6 -2
View File
@@ -33,6 +33,8 @@ def load_data(cr, idref, mode, kind, package, report):
noupdate is False, unless it is demo data or it is csv data in
init mode.
:returns: Whether a file was loaded
:rtype: bool
"""
def _get_files_of_kind(kind):
@@ -57,6 +59,7 @@ def load_data(cr, idref, mode, kind, package, report):
)
return files
filename = None
try:
if kind in ('demo', 'test'):
threading.currentThread().testing = True
@@ -70,6 +73,7 @@ def load_data(cr, idref, mode, kind, package, report):
if kind in ('demo', 'test'):
threading.currentThread().testing = False
return bool(filename)
def load_demo(cr, package, idref, mode, report=None):
"""
@@ -130,8 +134,8 @@ def load_module_graph(cr, graph, status=None, perform_checks=True,
def load_test(idref, mode):
cr.execute("SAVEPOINT load_test_data_file")
try:
load_data(cr, idref, mode, 'test', package, report)
return True
# return `None` if `load_data` didn't load any file
return load_data(cr, idref, mode, 'test', package, report) or None
except Exception:
_test_logger.exception(
'module %s: an exception occurred in a test', package.name)
+11 -6
View File
@@ -575,12 +575,11 @@ class OdooTestRunner(object):
return result
current_test = None
def run_unit_tests(module_name, position='at_install'):
"""
:returns: ``True`` if all of ``module_name``'s tests succeeded, ``False``
if any of them failed.
:rtype: bool
if any of them failed, ``None`` if no tests were ran.
:rtype: bool | None
"""
global current_test
# avoid dependency hell
@@ -590,7 +589,7 @@ def run_unit_tests(module_name, position='at_install'):
threading.currentThread().testing = True
config_tags = TagsSelector(tools.config['test_tags'])
position_tag = TagsSelector(position)
r = True
ran_tests = failures = False
for m in mods:
tests = unwrap_suite(unittest.TestLoader().loadTestsFromModule(m))
suite = OdooSuite(t for t in tests if position_tag.check(t) and config_tags.check(t))
@@ -604,13 +603,19 @@ def run_unit_tests(module_name, position='at_install'):
if time.time() - t0 > 5:
log_level = logging.RUNBOT
_logger.log(log_level, "%s ran %s tests in %.2fs, %s queries", m.__name__, result.testsRun, time.time() - t0, odoo.sql_db.sql_counter - t0_sql)
ran_tests = True
if not result.wasSuccessful():
r = False
failures = True
_logger.error("Module %s: %d failures, %d errors", module_name, len(result.failures), len(result.errors))
current_test = None
threading.currentThread().testing = False
return r
if failures:
return False
if ran_tests:
return True
return None
def unwrap_suite(test):
"""
+8
View File
@@ -510,6 +510,14 @@ class ThreadedServer(CommonServer):
rc = preload_registries(preload)
if stop:
if config['test_enable']:
with Registry.registries._lock:
for db, registry in Registry.registries.d.items():
report = registry._assertion_report
log = _logger.error if report.failures \
else _logger.warning if not report.successes \
else _logger.info
log("%d / %d tests failed when loading %s", report.failures, report.successes + report.failures, db)
self.stop()
return rc