def post(self, fullname): conf = config.get_config() obj = logic.get_requested_object(fullname, conf) if isinstance(obj, logic.BadTest): if obj.exists: self.render_error('Error loading test object %s: \n%s' % (fullname, obj.load_errors[0][1]), 500) else: self.render_error('Test object %s does not exist.' % fullname, 404) return conf = config.get_config() try: batch = runner.start_batch(fullname, conf) except DeadlineExceededError: self.render_error('Tests took too long to run. Consider setting the ' '"storage" option in aeta.yaml to something other ' 'than "immediate", such as "memcache".', 500) return if conf.storage == 'immediate': tasks = batch.get_tasks(conf) data = {'batch_info': batch.get_json(), 'results': [task.get_json() for task in tasks] } else: data = {'batch_id': str(batch.key.id())} self.response.out.write(json.dumps(data))
def _run_test_unit(fullname, task_key, conf): """Runs a single test unit based on a RunTestUnitTask. The test identified by the task is run and the result is stored in the RunTestUnitTask. Args: fullname: The full name of the test unit to run. task_key: The key of the RunTestUnitTask to run. conf: The configuration to use. """ ctx_options = models.get_ctx_options(conf) task = models.RunTestUnitTask(key=task_key, fullname=fullname) load_errors = [] if _this_task_has_failed_before(): # This will appear to the user as a "load error" in the test. msg = 'Unknown error running test %s. See log for details.' % fullname load_errors.append((fullname, msg)) try: task.set_test_result(load_errors, unittest.TestResult(), '', conf) task.put(**ctx_options) # pylint: disable-msg=W0703 except: msg = 'Error writing message about the test %s that failed!' % fullname logging.exception(msg) return test = logic.get_requested_object(fullname, conf) suite = test.get_suite(conf, load_errors) # Since the test is a TestSuite, its run method will handle all the # administrative work involved in setUpModule, setUpClass, skipping, etc. result, output = _run_test_and_capture_output(suite) task.set_test_result(load_errors, result, output, conf) task.put(**ctx_options)
def get(self, fullname): conf = config.get_config() load_errors = [] test = logic.get_requested_object(fullname, conf) methods = test.get_methods(conf, load_errors) data = {'method_names': [method.fullname for method in methods], 'load_errors': load_errors} self.response.out.write(json.dumps(data))
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)
def get(self, fullname): """Default view.""" conf = config.get_config() obj = logic.get_requested_object(fullname, conf) if isinstance(obj, logic.BadTest): if obj.exists: self.render_error('Error loading test object %s: \n%s' % (fullname, obj.load_errors[0][1]), 500) else: self.render_error('Test object %s does not exist.' % fullname, 404) return # urllib.quote is necessary for things embedded in <script> tags to avoid # things like quotes and </script> in the string literals. values = {'root_name': urllib.quote(fullname), 'rest_path': urllib.quote(conf.url_path_rest), 'static_path': conf.url_path_static, } self.render_page(_get_template_path('index.html'), values)