Exemple #1
0
def start_batch(fullname, conf):
  """Creates a TestBatch for all the given tests and returns it.

  Eventually, all tests will automatically run in the background.

  Args:
    fullname: The full name of the group of tests to run.  This should be the
        period-separated name of a test package, module, class, or method, or
        the empty string to run all tests.
    conf: The configuration to use.
    run_immediately: If set to True, tests will be run immediately rather than
        in the task queue.  They will be finished before this function returns.

  Returns:
    The TestBatch created for the run.

  Raises:
    TypeError: Wrong input arguments.
  """
  utils.check_type(fullname, 'fullname', str)
  utils.check_type(conf, 'conf', config.Config)
  ctx_options = models.get_ctx_options(conf)
  # It's necessary to set the key because if ctx_options['use_datastore'] ==
  # False, the key will not be set to something reasonable automatically.
  batch_key = ndb.Key(models.TestBatch, utils.rand_unique_id())
  batch = models.TestBatch(fullname=fullname, key=batch_key)
  batch.put(**ctx_options)
  call = deferred.DeferredCall(_initialize_batch, fullname, batch_key, conf)
  if conf.storage == 'immediate':
    call.run()
    # _initialize_batch() should have updated batch data
    return batch.key.get(**ctx_options)
  else:
    deferred.defer_multi([call], queue=conf.test_queue)
    return batch
Exemple #2
0
def _initialize_batch(fullname, batch_key, conf):
  """Initializes a TestBatch to start the tests running.

  This function creates a RunTestUnitTask for every test unit in the batch and
  starts running them in the background.

  Args:
    batch_key: The ndb.Key of the batch to initialize.
    conf: The configuration to use.
    run_immediately: If set to True, tests will be run immediately rather than
        in the task queue.  They will be finished before this function returns.
  """
  ctx_options = models.get_ctx_options(conf)
  errors_out = []
  batch = models.TestBatch(key=batch_key, fullname=fullname)
  if _this_task_has_failed_before():
    # This will appear to the user as a "load error" in the batch.
    msg = ('Unknown error initializing batch %s.  See log for details.' %
           fullname)
    errors_out.append((fullname, msg))
    try:
      batch.set_info(errors_out, {}, conf)
      batch.put(**ctx_options)
    # pylint: disable-msg=W0703
    except:
      msg = 'Error writing message about the batch %s that failed!' % fullname
      logging.exception(msg)
    return
  test = logic.get_requested_object(fullname, conf)
  test_units = test.get_units(conf, errors_out)
  test_unit_methods = {}
  tasks = []
  defer_calls = []
  for (i, unit) in enumerate(test_units):
    # Ignore loading errors for now.  _run_test_unit will detect loading errors
    # when its task is executed.
    method_names = [method.fullname for method in unit.get_methods(conf)]
    test_unit_methods[unit.fullname] = method_names
    task_key = models.RunTestUnitTask.get_key(batch_key, i)
    tasks.append(models.RunTestUnitTask(key=task_key, fullname=unit.fullname))
  batch.set_info(errors_out, test_unit_methods, conf)
  # Put batch after tasks, so that we don't see that the batch has tasks before
  # they exist.
  ndb.put_multi(tasks + [batch], **ctx_options)
  for task in tasks:
    call = deferred.DeferredCall(_run_test_unit, str(task.fullname), task.key,
                                 conf)
    if conf.storage == 'immediate':
      call.run()
    else:
      defer_calls.append(call)
  if ctx_options.get('use_datastore', True):
    defer_calls.append(deferred.DeferredCall(_delete_batch, batch.key, 0, conf,
                                             _countdown=_DELETE_TIME_SECS))
  deferred.defer_multi(defer_calls, queue=conf.test_queue)