def test_get_surveys_today(app, MonkeyEmail): with app.app_context(): timestamp_today = str(int(time.mktime(date.today().timetuple()))) fields_pre = { 'name': 'test_pre', 'program_id': '1', 'course_type_id': '1', 'focus_id': '1', 'traditional_id': '1', 'equipment_id': '1', 'experience_id': '1', 'university_type_id': '1', 'university_id': '1', 'number_students': '20', 'students_per_instructor': '4', 'lab_per_lecture': '2', 'hours_per_lab': '2.5', 'number_labs': '10', 'number_experiments': '5', 'number_projects': '1', 'week_guided': '1', 'start_date_pre': timestamp_today, 'start_date_post': '1934064000', 'frequency_phys_principle': '3', 'frequency_known_principle': '2', 'frequency_unknown_principle': '0', 'students_questions': '0', 'students_plan': '0', 'students_design': '0', 'students_apparatus': '0', 'students_analysis': '0', 'students_troubleshoot': '0', 'students_groups': '0', 'modeling_mathematics': '0', 'modeling_model': '0', 'modeling_tools': '0', 'modeling_measurement': '0', 'modeling_predictions': '0', 'modeling_uncertainty': '0', 'modeling_calibrate': '0', 'analysis_uncertainty': '0', 'analysis_calculate': '0', 'analysis_computer': '0', 'analysis_control': '0', 'communication_oral': '0', 'communication_written': '0', 'communication_lab': '0', 'communication_journal': '0', 'communication_test': '0' } fields_post_1 = fields_pre.copy() fields_post_1['name'] = 'test_post_1' fields_post_1['start_date_pre'] = 1 fields_post_1['start_date_post'] = timestamp_today fields_post_2 = fields_post_1.copy() fields_post_2['name'] = 'test_post_2' course_db = CourseDB() course_db.generate_identifier = lambda: '12345' course_db.add_course(user_id=1, fields=fields_pre) course_db.add_course(user_id=1, fields=fields_post_1) course_db.add_course(user_id=2, fields=fields_post_2) pre, post = course_db.get_surveys_today() pre_list = [] for row in pre: pre_list.append(list(row)) post_list = [] for row in post: post_list.append(list(row)) assert [1, 'test_pre', '12345'] in pre_list assert [1, 'test_post_1', '12345'] in post_list assert [2, 'test_post_2', '12345'] in post_list
class HandleCourseQuestions: """Handler for the questions about a new course. The member self.question contains all CourseQuestion objects. """ def __init__(self): self.db = CourseDB() self.values = {} self.questions = [ StartTab(), QuestionText( 'name', 'Name', 'Wählen Sie einen beliebigen Namen für den Kurs aus.'), QuestionDate( 'start_date_pre', 'Start Prä-Befragung', 'Start der Befragung vor dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDate( 'start_date_post', 'Start Post-Befragung', 'Start der Befragung nach dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDropdown( 'university_type', 'Art der Hochschule', 'An welcher Art von Hochschule findet der Kurs statt?', self.db.select_all_entries('university_type')), QuestionDropdownWithText( 'university', 'Hochschule', 'An welcher Hochschule findet der Kurs statt?', self.db.select_all_entries('university'), 'Andere'), QuestionDropdown('program', 'Studiengang', 'Zu welchen Studiengang gehört der Kurs?', self.db.select_all_entries('program')), QuestionDropdown('experience', 'Jahrgang', 'In welchem Jahrgang sind die Studenten?', self.db.select_all_entries('experience')), QuestionDropdown('course_type', 'Art des Kurses', 'Was für eine Art von Kurs ist es?', self.db.select_all_entries('course_type')), QuestionDropdown('traditional', 'Didaktische Methoden', 'Welche didaktischen Methoden benutzt der Kurs?', self.db.select_all_entries('traditional')), QuestionDropdown('focus', 'Schwerpunkt', 'Worauf liegt der Schwerpunkt des Kurses?', self.db.select_all_entries('focus')), QuestionNumber( 'number_students', 'Anzahl an Studenten', ('Wieviele Studenten werden voraussichtlich an dem Kurs ' + 'teilnehmen?'), default=0, value_range=(0, 1000)), QuestionNumber( 'students_per_instructor', 'Verhältnis Studenten/Betreuer', 'Wieviele Studenten kommen in etwa auf einen Betreuer?', default=0, value_range=(0, 100)), QuestionNumber( 'number_experiments', 'Nummer von Experimenten', 'Wieviele Experimente muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber('number_projects', 'Nummer von Projekten', 'Wieviele Projekte muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber( 'lab_per_lecture', 'Verhältnis Praktikum/Vorlesung', 'Wie ist das Verhältnis von Praktikum zu Vorlesung? (Angabe als z.B. 0.5)', default=0, value_range=(0, 100), step=0.1), QuestionNumber('hours_per_lab', 'Länge eines Termins', 'Wieviele Stunden dauert ein Termin?', default=0, value_range=(0, 24), step=0.01), QuestionNumber('number_labs', 'Anzahl Termine', 'Wieviele Termine gibt es?', default=0, value_range=(0, 1000)), QuestionNumber('week_guided', 'Geführte Wochen', 'Wieviel Wochen sind die Experiment geführt?', default=0, value_range=(0, 1000)), QuestionDropdownWithText( 'equipment', 'Geräte', 'Was für eine Art von Geräten wird hauptsächlich verwendet?', self.db.select_all_entries('equipment'), 'Andere'), EndTab(), StartTab(), QuestionFrequency( { 'frequency_phys_principle': 'bekannte physikalische Prinzipien verifizieren?', 'frequency_known_principle': 'bekannte physikalische Prinzipien durch selbstständiges Experimentieren wiederentdecken?', 'frequency_unknown_principle': 'offene Fragen untersuchen, deren Antwort unbekannt ist?' }, 'Wie oft werden Studenten in dem Praktikum ...'), QuestionFrequency( { 'students_questions': 'der eigenen Fragestellung?', 'students_plan': 'der Planung der Messmethode?', 'students_design': 'dem Design des Messaubaus?', 'students_apparatus': 'dem Aufbau der Messapparate?', 'students_analysis': 'der selbstständigen Ausarbeitung der Auswertung?', 'students_troubleshoot': 'dem Troubleshooting des Messapparates?', 'students_groups': 'der Gruppenarbeit?' }, 'Wie oft arbeiten Studenten an ...'), QuestionFrequency( { 'modeling_mathematics': 'die mathematische Modellierung des physikalischen Systems', 'modeling_model': 'die konzeptuelle Modellierung des physikalischen Systems', 'modeling_tools': 'Modellierung des physikalischen Aufbau', 'modeling_measurement': 'Modellierung der Messgeräte', 'modeling_predictions': 'Angabe von Vorhersagen, die durch mathematische oder physikalische Modelle entstehen', 'modeling_uncertainty': 'um das Messsystem order die Messprozedur zu verbessern und die Messunsicherheiten zu reduzieren', 'modeling_calibrate': 'Kalibrierung der Messgeräte' }, 'Studenten modellieren selbstständig durch ...'), QuestionFrequency( { 'analysis_uncertainty': 'der direkten Bestimmung der Messunsicherheiten', 'analysis_calculate': 'Bestimmung der Messunsicherheiten durch Fehlerfortpflanzung', 'analysis_computer': 'Berechnung/Visualisierung am Computer', 'analysis_control': 'Computersteuerung der Messgeräte' }, 'Studenten führen die Auswertung und die Visualisierung der Daten durch mit ...' ), QuestionFrequency( { 'communication_oral': 'die Ergebnisse in einer mündlichen Präsentation', 'communication_written': 'die Ergebnisse in einer schriftlichen Präsentation/Bericht', 'communication_journal': 'die Ergebnisse in Form eines Journalartikels', 'communication_lab': 'den Versuchsablauf in einem Laborbuch', 'communication_test': 'die Vorbereitung mit einem Testat' }, 'Studenten kommunizieren ...'), QuestionNote('notes', 'Notizen', ('Gibt es noch etwas, dass Sie uns sagen wollen? ' + 'Max. 255 Zeichen.')), EndTab() ] def __iter__(self): for question in self.questions: yield question def parse(self, form): """Parse a given form for the values for the new course. Args: form (dict(str: str)): The form returned from the webpage. Returns: A list of all the errors it encountered while parsing. >>> parse({"name": ""}) ["Name is required."] """ errors = [] for question in self.questions: try: parsed_data = question.parse(form) if parsed_data: if len(parsed_data) >= 2 and len(parsed_data[0]) == 2: for data in parsed_data: self.values[data[0]] = data[1] else: self.values[parsed_data[0]] = parsed_data[1] except Exception as e: errors.append(e) try: errors.extend(self._sanity_check()) except KeyError as e: pass return errors def _sanity_check(self): """Check the sanity of the data. 1. Check if both start-dates are in the future. 2. Post is after Pre Date 3. All frequency questions have int values between 0 and 3 """ errors = [] # all dates in future if not ((date.fromtimestamp(int(self.values['start_date_pre'])) > date.today()) & (date.fromtimestamp( int(self.values['start_date_post'])) > date.today())): errors.append('Das Anfangsdatum muss in der Zukunft liegen.') # post is after pre if not self.values['start_date_pre'] < self.values['start_date_post']: errors.append( 'Start Post-Befragung muss nach der Pre-Befragung sein.') frequency_questions = [ 'frequency_*', 'students_*^(?!_)', 'modeling_*', 'analysis_*', 'communication_*' ] for key in self.values: if any(re.match(expr, key) for expr in frequency_questions): if not (int(self.values[key]) in [0, 1, 2, 3]): errors.append('Flascher Wert im Feld {}'.format(key)) return errors def write(self, user_id): """Write the parsed values to the database. Args: user_id (str): The id of the owner of the new course. """ self.db.add_course(user_id, self.values)
def test_add_course(app, MonkeyEmail): with app.app_context(): course_db = CourseDB() courses = course_db.get_courses(user_id=2) assert len(courses) == 2 course_name = 'New Course' fields = { 'name': course_name, 'program_id': '1', 'course_type_id': '1', 'focus_id': '1', 'traditional_id': '1', 'equipment_id': '1', 'experience_id': '1', 'university_type_id': '1', 'university_id': '1', 'number_students': '20', 'students_per_instructor': '4', 'lab_per_lecture': '2', 'hours_per_lab': '2.5', 'number_labs': '10', 'number_experiments': '5', 'number_projects': '1', 'week_guided': '1', 'start_date_pre': '1899849600', 'start_date_post': '1934064000', 'frequency_phys_principle': '3', 'frequency_known_principle': '2', 'frequency_unknown_principle': '0', 'students_questions': '0', 'students_plan': '0', 'students_design': '0', 'students_apparatus': '0', 'students_analysis': '0', 'students_troubleshoot': '0', 'students_groups': '0', 'modeling_mathematics': '0', 'modeling_model': '0', 'modeling_tools': '0', 'modeling_measurement': '0', 'modeling_predictions': '0', 'modeling_uncertainty': '0', 'modeling_calibrate': '0', 'analysis_uncertainty': '0', 'analysis_calculate': '0', 'analysis_computer': '0', 'analysis_control': '0', 'communication_oral': '0', 'communication_written': '0', 'communication_lab': '0', 'communication_journal': '0', 'communication_test': '0' } course_db.add_course(user_id=2, fields=fields) courses = course_db.get_courses(user_id=2) assert len(courses) == 3 assert courses[-1]['name'] == course_name assert MonkeyEmail.called assert MonkeyEmail.recipient == '*****@*****.**' assert MonkeyEmail.subject == 'Kurs Registrierung GEclass' assert course_name in MonkeyEmail.content