def save_result(self, event_id, testcase_id, username, hwname, smolt, result, bugs, comment): """Saves the validated data to ResultsDB.""" if hwname is not None: hwname = hwname.encode('ascii', 'xmlcharrefreplace') if result is not None: result = result.encode('ascii', 'xmlcharrefreplace') filled = self.__update_profile_cookies(username, smolt, hwname) # This cookie is used for showing the "DONE" status message in the testcase # grid on the Event page if testcase_id not in filled: filled[testcase_id] = result response.set_cookie("filled", json.dumps(filled)) q = DBSession.query(db.Testcase) q = q.filter(db.Testcase.id == testcase_id) tc = q.one() # Prepares the data for ResultsDB storage q = DBSession.query(db.Event) q = q.filter(db.Event.id == event_id) event = q.one() job_id = event.resultsdb_job # normalize the empty smolt url to empty string if smolt is None or smolt.strip() == "": smolt = "" # Preparing the data for ResultsDB # Set "extra data" (from the ResultsDB's POW) # The result is stored here, so we can easily work with the result, without needing # to distinguish between the "tc" and "txt" type in the results view. keyval_pairs = dict(username=username, hwname=hwname, smolt=smolt, result=result, tctype = tc.type.name) # Some ResultsDB fields, reasonably used, so we don't need to create that much extra-data fields if comment is not None: summary = comment.encode('ascii', 'xmlcharrefreplace') else: summary = comment highlights = bugs # For the txt testcase, we set the ResultsDB result to PASSED # tc type testcase already has a subset of ResultsDB valid results. if tc.type.name == 'txt': result = "PASSED" # Store the data into ResultsDB tr_id = self.rdb.start_testrun(tc.url, job_id) retval = self.rdb.end_testrun(tr_id, result, tc.url, keyval_pairs, summary = summary, highlights = highlights) if retval == 0: flash("Result for '%s' sucessfully saved" % tc.name) else: flash("Result for '%s' could not be saved (ResultsDB error)" % tc.name, 'error') #FIXME: change model, so the event-category is one-to-many instead of many-to-many redirect(url('show_event', dict(event_id = event.id)))
def bootstrap(command, conf, vars): """Place any commands to setup testdays here""" # <websetup.bootstrap.before.auth # <websetup.bootstrap.after.auth> # event = db.Event('Power Management Testday', 'http://fedoraproject.org/wiki/Test_Day:2012-10-11_Power_Management') # c1 = db.Category('pm') # c2 = db.Category('tuned') # c3 = db.Category('other') t1 = db.Type('tc') t2 = db.Type('txt') # # DBSession.add(event) # DBSession.add(c1) # DBSession.add(c2) # DBSession.add(c3) DBSession.add(t1) DBSession.add(t2) # # event.categories = [c1, c2, c3] # # tc1 = db.Testcase('pm-suspendr', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_pm_suspend', t1, c1) # tc2 = db.Testcase('pm-hibernate', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_pm_hibernate', t1, c1) # tc3 = db.Testcase('pm-suspend-hybrid', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_pm_suspend_hybrid', t1, c1) # tc4 = db.Testcase('pm-bugreport', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_pm_bugreport', t1, c1) # tc5 = db.Testcase('pm-powersave', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_pm_powersave', t1, c1) # # tc6 = db.Testcase('Tuned', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_tuned_basic', t1, c2) # tc7 = db.Testcase('Tuned disabled idle', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_tuned_off_idle', t2, c2) # tc8 = db.Testcase('Tuned powersave idle', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_tuned_powersave_idle', t2, c2) # # tc9 = db.Testcase('Lid close', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_Lid_Close', t1, c3) # tc10 = db.Testcase('Backlight control', 'http://fedoraproject.org/wiki/QA:Testcase_Power_Management_Backlight_Control', t1, c3) # # DBSession.add(tc1) # DBSession.add(tc2) # DBSession.add(tc3) # DBSession.add(tc4) # DBSession.add(tc5) # DBSession.add(tc6) # DBSession.add(tc7) # DBSession.add(tc8) # DBSession.add(tc9) # DBSession.add(tc10) # transaction.commit()
def all_events(self): """Handle the front-page.""" q = DBSession.query(db.Event) #FIXME: change "created" to "takes-place" or something like that #FIXME: add some constraints (e.g. pagination) q = q.order_by(desc(db.Event.created)) events = q.all() return dict(events = events)
def fill_testcase(self, testcase_id, event_id, **kwargs): """Selects appropriate testcase from database and shows form for filling the results. If the 'type' is 'tc' (TestCase), then we want the user to select result from PASSED/FAILED/INFO. If the type is txt (TeXT), then the user should enter some arbitrary text as a result.""" q = DBSession.query(db.Testcase) q = q.filter(db.Testcase.id == testcase_id) tc = q.one() if tc.type.name == 'tc': tmpl_context.form = create_testcase_form elif tc.type.name == 'txt': tmpl_context.form = create_textinfo_form return dict(testcase = tc, event_id = event_id)
def setUp(self): """Prepare model test fixture.""" try: new_attrs = {} new_attrs.update(self.attrs) new_attrs.update(self.do_get_dependencies()) self.obj = self.klass(**new_attrs) DBSession.add(self.obj) DBSession.flush() return self.obj except: DBSession.rollback() raise
def show_event(self, event_id = None): if event_id is None: redirect(url('show_events')) q = DBSession.query(db.Event) q = q.filter(db.Event.id == event_id).order_by(db.Event.id) event = q.one() # As ResultsDB is probably the biggest bottle-neck loading/preparsing data # is cached. # The current caching implementation can not call methods with arguments # so we need to prepare a partial function, with the parameters pre-filled. cached_func = partial(rdb_preparse.show_event, self.rdb, event) mycache = cache.get_cache('show_event_resultsdb') cachedvalue = mycache.get_value( key="event_id_%s" % event_id, createfunc= cached_func, expiretime=10) #FIXME: make the expiretime configurable filled = json.loads(request.cookies.get("filled", "{}")) return dict(event=event, filled = filled, results = cachedvalue)
def test_query_obj(self): """Model objects can be queried""" obj = DBSession.query(self.klass).one() for key, value in self.attrs.iteritems(): assert_equals(getattr(obj, key), value)
def tearDown(self): """Finish model test fixture.""" DBSession.rollback()
def process_update_testday(self, **kwargs): result, data = self._parse_wiki(kwargs['wikipage']) if result == False: redirect('update_testday', dict(msg = data)) # load testcase types from DB tc_types = {} q = DBSession.query(db.Type) q = q.filter(db.Type.name == 'txt') tc_types['txt'] = q.one() q = DBSession.query(db.Type) q = q.filter(db.Type.name == 'tc') tc_types['tc'] = q.one() # check whether the event already exists based on the event url q = DBSession.query(db.Event) q = q.filter(db.Event.url == data['url']) try: event = q.one() event.name = data['name'] event.config = kwargs['wikipage'] e_action = "updated" # status just for the output message except sqlalchemy.orm.exc.NoResultFound: # event with such url does not exist job_id = self.rdb.start_job(name = data['name']) if job_id < 1: redirect('update_testday', dict(msg = "Error during ResultsDB start_job")) event = db.Event(data['name'], data['url']) event.resultsdb_job = job_id event.created = datetime.datetime.utcnow() event.config = kwargs['wikipage'] e_action = "created" DBSession.add(event) # clear the old categories/testcases in DB for c in event.categories: for t in c.testcases: DBSession.delete(t) DBSession.delete(c) # create new categories/testcases in DB categories = [] for cat in data['categories']: c = db.Category(cat['name']) categories.append(c) DBSession.add(c) for tc in cat['testcases']: t = db.Testcase(tc['name'], tc['url'], tc_types[tc['type']], c) DBSession.add(t) event.categories = categories transaction.commit() DBSession.add(event) eid = event.id transaction.commit() redirect('update_testday', dict( msg = 'Event with id %s %s correctly.' % (eid, e_action), event_link = url('/show_event', params = {"event_id": eid}), ) )
def process_export_testday(self, wikipage): result, w_data = self._parse_wiki(wikipage, "TestdayApp Metadata") if result == False: redirect('export_event', dict(msg = w_data)) q = DBSession.query(db.Event) q = q.filter(db.Event.url == w_data['url']) try: event = q.one() except sqlalchemy.orm.exc.NoResultFound: # event with such url does not exist redirect('export_event', dict(msg = "Event with url '%s' does not exist" % w_data['url'])) # creates list of testcase url's for each category # the list of url's specifies the 'order' of testcases for wiki matrix order = [] headers = [] for c in w_data['categories']: order.append([]) headers.append([c['name']]) for tc in c['testcases']: order[-1].append(tc['url']) headers[-1].append((tc['name'], tc['url'])) data = rdb_preparse._by_user(self.rdb, event) text_all = "" for grp_index, tc_group in enumerate(order): # Create table Header text_all += "=== %s ===\n\n" % headers[grp_index][0] text_all += "{|\n" text_all += "! User\n" text_all += "! Hardware\n" for name, url in headers[grp_index][1:]: text_all += "! [%s %s]\n" % (url, name) text_all += "! References\n" # Fill results for user in data: for smolt, hwname in data[user]: # if at least one result is set for user in group, set hit to true hit = False text = "|-\n" text += "| [[User:%s|%s]]\n" % (user, user) if smolt != "": text += "| [%s %s]\n" % (smolt, hwname) else: text += "| %s\n" % hwname for tc_url in tc_group: try: results = data[user][(smolt, hwname)][tc_url] hit = True except KeyError: text += "| \n" continue text += "| " dirty = False for result in results: if dirty: text += "<br />" dirty = False rtext = result['result'] if result['result'] in ['PASSED', 'FAILED']: rtext = "{{result|%s}} " % result['result'].lower()[:-2] elif result['result'] == 'INFO': rtext = "{{result|warn}} " else: # result is plaintext dirty = True text += "%s "% rtext for bug in result['bugs']: text += "<ref>{{bz|%s}}</ref>" % bug if result['comment']: text += "<ref>%s</ref>" % result['comment'] text += "\n" text += "| <references/>\n" # if at least one result was filled for the user+hw in the group, # add the text to the export if hit: text_all += text text_all += "|-\n" text_all += "|}\n" text_all += "\n\n" return dict(data = text_all)