def testSetGet(self): st = Set.createNew("Test Set", 4) # these are in the set q = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) q2 = Question("Goodbye?", ["1", "2", "3", "4"], "d", st, 2) # this is *not* (included to be sure it doesn't accidentally get pulled) q3 = Question("Bye-bye?", ["1", "2", "3", "4"], "d", Set.createNew("t", 2), 2) # make sure gotten questions and originals are the same sets = getBySet(st) assert len(sets) == 2 assert sets[0].getQid() == q.getQid() assert sets[1].getQid() == q2.getQid()
def testDelete(self): st = Set.createNew("Test Set", 1) q1 = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) q2 = Question("What is the answer to this one?", ["foo", "bar", "42", "quux"], "c", st, 2) q3 = Question("What is the answer to another one?", ["foo", "bar", "42", "quux"], "c", st, 2) qm = QuestionManager(st) qs_from_qm = [i for i in qm] assert len(qs_from_qm) == 3 # bare delete outside of qm (not generally a good idea) q3.delete() # we haven't updated question manager yet qs_from_qm = [i for i in qm] assert len(qs_from_qm) == 3 # now... qm.update() qs_from_qm = [i for i in qm] assert len(qs_from_qm) == 2 # now delete one properly thru the qm qm.rmQuestion(q2) qs_from_qm = [i for i in qm] assert len(qs_from_qm) == 1
def testFindNextOrd(self): st = Set.createNew("Foo set", 1) q1 = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) q2 = Question("What is the answer to this one?", ["foo", "bar", "42", "quux"], "c", st, 2) q3 = Question("What is the answer to another one?", ["foo", "bar", "42", "quux"], "c", st, 3) # to make sure the where clause works throwOffSet = Set.createNew("Bar set", 2) q4 = Question("And how about this?", ["foo", "bar", "42", "quux"], "c", throwOffSet, 5) o = findNextOrd(st) assert o == 4, "Wrong next ord, expected 4, got %i" % o
def testRTFOutput(self): st = Set.createNew("Test Set", 3) q = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) q2 = Question("Goodbye?", ["1", "2", "3", "4"], "d", st, 2) questions = [q, q2] # answers q, a, ca = db.output._getRTFFormattedContent(questions[0], 1) for ans in a: self.failUnless(".\t" in ans) let = ans.split('.\t')[0] self.assertTrue(let in Question.qLetters), \ "Answer letter missing or incorrect on answer %r" % ans # correct answer q, a, ca = db.output._getRTFFormattedContent(questions[0], 2) self.assertTrue('\t' in ca), "Missing tab" ans, let = ca.split('\t') self.assertTrue(ans == 'ANS:') self.assertTrue(let in Question.qLetters) # question number q, a, ca = db.output._getRTFFormattedContent(questions[0], 3) self.assertTrue(".\t" in q), "Missing tab" num = q.split('.')[0] try: num = int(num) except TypeError: self.assertTrue(False), "Returned question number not an int"
def testGettersSetters(self): # compile a sample question q = "What is Maud's family name?" a = ["Bethamer", "Thorne", "Almzead", "Jallwei"] ca = "c" order = 1 st = Set.createNew("Maudiverse Set", 5) ques = Question(q, a, ca, st, order) # make sure getters work assert ques.getQuestion() == q assert ques.getAnswersList() == a assert ques.getCorrectAnswer() == ca assert ques.getSid() == st.getSid() assert ques.getSet().getSid() == st.getSid() assert ques.getOrder() == order assert ques.getQid() # try editing nq = "Which of these names belonged to Maud's mother?" ques.setQuestion(nq) na = ["Bethamer", "Thorne", "Ohlo", "Almzead"] ques.setAnswersList(na) nca = 'd' ques.setCorrectAnswer(nca) norder = 2 ques.setOrder(norder) # make sure values were updated assert ques.getQuestion() == nq assert ques.getAnswersList() == na assert ques.getCorrectAnswer() == nca assert ques.getOrder() == norder
def testQuestionManager(self): st = Set.createNew("Test Set", 1) q1 = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) q2 = Question("What is the answer to this one?", ["foo", "bar", "42", "quux"], "c", st, 2) qm = QuestionManager(st) # iter qs_from_qm = [i for i in qm] assert len(qs_from_qm) == 2 assert qs_from_qm[0] == q1 assert qs_from_qm[1] == q2 # byId qid = q1.getQid() qbyid = qm.byId(qid) assert qbyid == q1 # byName qname = q1.getQuestion() qbyname = qm.byName(qname) assert qbyname == q1 # byOrd qord = q1.getOrder() qbyord = qm.byOrd(qord) assert qbyord == q1
def testSwap(self): st = Set.createNew("Test Set", 1) q1 = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) q2 = Question("What is the answer to this one?", ["foo", "bar", "42", "quux"], "c", st, 2) swapRows(q1, q2) assert q1.getOrder() == 2 assert q2.getOrder() == 1
def testDupeQuestionNames(self): st = Set.createNew("Test Set", 1) st2 = Set.createNew("Test Set 2", 2) q = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) with self.assertRaises(DuplicateError): Question("What is the answer?", ["foo", "bar", "42", "quux"], "c", st, 2) try: # this one should be fine Question("What is the answer to another question?", ["foo", "bar", "42", "quux"], "c", st, 2) # and this one tests whether it correctly doesn't consider things # in different sets as dupes when they otherwise are Question("What is the answer?", ["foo", "bar", "42", "quux"], "c", st2, 3) except Exception as e: assert False, e
def testDbWriteRead(self): # create a question st = Set.createNew("Test Set", 3) q = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) qid = q.getQid() # read back in, make sure they're the same q2 = getById(qid) assert q == q2
def makeTestQuestions(): # create some questions to render st = Set.createNew("Test Set", 1) q1 = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) q2 = Question("'Goodbye' is a [...].", ["word", "tar", "taz", "tuux"], "a", st, 1) q3 = Question("Auf wiedersehen? // Goodbye?", ["me", "you", "they", "I"], "b", st, 1) qs = [q1, q2, q3] return qs
def testSaveRestore(self): cls = Class.createNew("TestClass") st = Set.createNew("TestSet", 1) st2 = Set.createNew("RevSet", 2) sl = [st, st2] q = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) #"new" q2 = Question("Goodbye?", ["1", "2", "3", "4"], "d", st, 2) # "new" q3 = Question("Sayonara.", ["1", "2", "3", "4"], "c", st2, 2) # "review" ql = [q, q2, q3] quizNum = 1 date = '2015-08-05' # use a datetime obj later on, format on display newNum = 2 #/ of course do this by checking list length in revNum = 1 #\ the Quiz object's lists later on newSet = st qPickle = pickle.dumps(ql) unPickledQl = pickle.loads(qPickle)
def testParseAndRead(self): cls = Class.createNew("MyClass") mama = Student.createNew("Bjornstad", "Jennifer", "1", "9A2DC6", "*****@*****.**", cls) soren = Student.createNew("Bjornstad", "Soren", "2", "9A2D9C", "*****@*****.**", cls) st = Set.createNew("fooset", 1) q1 = Question(u"das Buch", ['aa', 'bb', 'cc', 'dd'], 'b', st, 1) q2 = Question(u"die Lieblingsfarbe", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q3 = Question(u"die Tür", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q4 = Question(u"der Familienname", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q5 = Question(u"das Auto", ['aa', 'bb', 'cc', 'dd'], 'c', st, 1) q6 = Question(u"der Ball", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q7 = Question(u"der Stift", ['aa', 'bb', 'cc', 'dd'], 'b', st, 1) q8 = Question(u"die Tafel", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q9 = Question(u"der Deutschkurs", ['aa', 'bb', 'cc', 'dd'], 'c', st, 1) q10 = Question(u"der Fußball", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) ql = [q1, q2, q3, q4, q5, q6, q7, q8, q9, q10] qPickle = pickle.dumps(ql) # fake a quiz into the quizzes table, as it's quite complicated to do # otherwise q = '''INSERT INTO quizzes (zid, cid, qPickle, newNum, revNum, newSetNames, seq, resultsFlag, datestamp, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''' vals = (1, cls.getCid(), sqlite3.Binary(qPickle), 8, 2, "Foobar", 1, 0, '2015-08-01', '') d.inter.exQuery(q, vals) with open('tests/resources/tpStatsParse/mamasoren1.html') as f: data = f.read() responses = parseHtmlString(data) for resp in responses: writeResults(resp, cls, 1) for resp in responses: writeResults(resp, cls, 1, suppressCheck=True) # check the check :) c = d.inter.exQuery("SELECT * FROM results") answers = json.loads(c.fetchall()[0][3]) assert answers[0:2] == [[1, 'a'], [2, 'd']] # now try to read it back assert str(readResults(soren, 1)) == "[(1, u'a', 'b'), (2, u'b', 'd'),"\ " (3, u'c', 'd'), (4, u'd', 'a'), (5, u'b', 'c')," \ " (6, u'd', 'd'), (7, u'c', 'b'), (8, u'c', 'd')," \ " (9, u'd', 'c'), (10, u'b', 'a')]" # delete delResults(1) assert readResults(soren, 1) is None assert readResults(mama, 1) is None
def testRandomize(self): st = Set.createNew("Foo set", 1) q = Question("What is 2 + 2?", ["1", "2", "3", "4"], "d", st, 1) # check that order changes and correct answer stays the same. since it # could randomly not change the choice, run it a few times; for 0.25 # chance of not doing anything, chance of passing incorrectly < 1^-12. hasChangedOrder = False origOrder = q._a[:] for i in range(20): q.randomizeChoices() indices = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4} assert q._a.index("4") == indices[q.getCorrectAnswer()] if q._a != origOrder: hasChangedOrder = True assert hasChangedOrder
def testInvalidQuestions(self): st = Set.createNew("Test Set", 1) with self.assertRaises(QuestionFormatError): q = Question("What is the answer?", ["foo", "bar", "foo", "42"], "d", st, 1) with self.assertRaises(QuestionFormatError): q = Question("What is the answer?", ["foo"], "a", st, 1) with self.assertRaises(QuestionFormatError): q = Question("What is the answer?", ["foo", "bar", "baz", "42"], "e", st, 1) with self.assertRaises(QuestionFormatError): q = Question("What is the answer?", ["foo", "bar", "baz", "42"], "&", st, 1) with self.assertRaises(QuestionFormatError): q = Question("What is the answer?", ["foo", "bar", "", "42"], "d", st, 1)
def testRTFRender(self): fname = 'testfile.rtf' against_fname = 'tests/resources/test_format_against.rtf' st = Set.createNew("Test Set", 2) questions = [Question("Hello [...]?", ["foo", "bar", "baz", "quux"], "c", st, 1)] renderRTF(questions, fname) try: f = open(fname) except IOError: self.assertTrue(False), "File was not created successfully" else: self.assertTrue(f.readlines()), "No data in file" assert filecmp.cmp(fname, against_fname), \ "Output different from saved correct output file" finally: f.close() os.remove(fname)
def testInsertQuestion(self): st = Set.createNew("Test Set", 1) q1 = Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 0) q2 = Question("What is the answer to this one?", ["foo", "bar", "42", "quux"], "c", st, 1) q3 = Question("And how about this one?", ["foo", "bar", "42", "quux"], "c", st, 2) q4 = Question("And just one more.", ["foo", "bar", "42", "quux"], "c", st, 3) # we'll need to refetch because the ords have been changed in a # separate instance of the question; now the ords will be in order, # so sort by order and check the order of their qids q1id, q2id, q3id, q4id = \ q1.getQid(), q2.getQid(), q3.getQid(), q4.getQid() insertQuestion(q3, 1) newQs = getBySet(st) newQs.sort(key=lambda question: question.getOrder()) assert newQs[0].getQid() == q1id assert newQs[1].getQid() == q3id assert newQs[2].getQid() == q2id assert newQs[3].getQid() == q4id
def testWrongQuizError(self): # dupe of first part of above test, except with the wrong questions cls = Class.createNew("MyClass") mama = Student.createNew("Bjornstad", "Jennifer", "1", "9A2DC6", "*****@*****.**", cls) soren = Student.createNew("Bjornstad", "Soren", "2", "9A2D9C", "*****@*****.**", cls) st = Set.createNew("fooset", 1) q1 = Question(u"das Buch", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q2 = Question(u"die Lieblingsfarbe", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q3 = Question(u"die Tür", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q4 = Question(u"der Familienname", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q5 = Question(u"das Auto", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q6 = Question(u"der Ball", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q7 = Question(u"der Stift", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q8 = Question(u"die Tafel", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q9 = Question(u"this is stupid", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q10 = Question(u"something wrong", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) ql = [q1, q2, q3, q4, q5, q6, q7, q8, q9, q10] qPickle = pickle.dumps(ql) # fake a quiz into the quizzes table, as it's quite complicated to do # otherwise q = '''INSERT INTO quizzes (zid, cid, qPickle, newNum, revNum, newSetNames, seq, resultsFlag, datestamp, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''' vals = (1, cls.getCid(), sqlite3.Binary(qPickle), 8, 2, "Foobar", 1, 0, '2015-08-01', '') d.inter.exQuery(q, vals) with open('tests/resources/tpStatsParse/mamasoren1.html') as f: data = f.read() responses = parseHtmlString(data) with self.assertRaises(WrongQuizError) as garbage: for resp in responses: writeResults(resp, cls, 1)
def testFormatter(self): # set up a quiz with results cls = db.classes.Class.createNew("TestClass (no pun intended)") st = Set.createNew("fooset", 1) s = Student.createNew("Bjornstad", "Soren", "2", "c56al", "*****@*****.**", cls) s2 = Student.createNew("Almzead", "Maud,Her", "5", "55655", "*****@*****.**", cls) q1 = Question(u"das Buch", ['hourglass', 'book', 'Bach', 'cat'], 'b', st, 1) q2 = Question( u"die Lieblingsfarbe", ['favorite class', 'computer', 'color', 'favorite color'], 'd', st, 1) q3 = Question(u"die Tür", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q4 = Question(u"der Familienname", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) q5 = Question(u"das Auto", ['aa', 'bb', 'cc', 'dd'], 'c', st, 1) q6 = Question(u"der Ball", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q7 = Question(u"der Stift", ['aa', 'bb', 'cc', 'dd'], 'b', st, 1) q8 = Question(u"die Tafel", ['aa', 'bb', 'cc', 'dd'], 'd', st, 1) q9 = Question(u"der Deutschkurs", ['aa', 'bb', 'cc', 'dd'], 'c', st, 1) q10 = Question(u"der Fußball", ['aa', 'bb', 'cc', 'dd'], 'a', st, 1) ql = [q1, q2, q3, q4, q5, q6, q7, q8, q9, q10] qPickle = pickle.dumps(ql) # fake a quiz into the quizzes table, as it's quite complicated to do # otherwise q = '''INSERT INTO quizzes (zid, cid, qPickle, newNum, revNum, newSetNames, seq, resultsFlag, datestamp, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''' vals = (1, cls.getCid(), Binary(qPickle), 8, 2, "Foobar", 1, 0, '2015-08-01', '') d.inter.exQuery(q, vals) with open('tests/resources/tpStatsParse/mamasoren1.html') as f: data = f.read() responses = parseHtmlString(data) # we don't have a student with an ID of 1 in the db yet, so there's # nothing to match the one in the responses string with with self.assertRaises(MissingStudentError) as e: for resp in responses: writeResults(resp, cls, 1) # now fix that. s3 = Student.createNew("Bjornstad", "Jennifer", "1", "55655", "*****@*****.**", cls) for resp in responses: writeResults(resp, cls, 1) # now try some formatting things. optsDict = { 'fromName': 'Testy Tester', 'fromAddr': '*****@*****.**', 'subject': '[CQM $c] Quiz $n for $s: $r/$t ($p%)', 'body': 'Table of scores:\n$a\n\nAnnotated quiz:\n$Q\n\n' 'Original quiz:\n$q\n\nThe class average was ' '$R/$t ($P%). You won $$2 from your scores! ' 'To clarify, $$roll this.', 'hostname': 'mail.messagingengine.com', 'port': '465', 'ssl': 'SSL/TLS', 'username': '******', 'password': '******', #TODO: make sure this username/pass doesn't stay in here! } em = EmailManager(optsDict, cls, 1) assert em._expandFormatStr(optsDict['body'], s3, True).strip() == \ correctFormatStrTest.strip() assert em._expandFormatStr(optsDict['subject'], s3, False).strip() == \ correctFormatStrSubjTest.strip()
def testDeletions(self): c = Class.createNew("Greta and TI 101") st = Set.createNew("Test Set", 3) q = Question("Hello?", ["foo", "bar", "baz", "quux"], "c", st, 1) q2 = Question("Goodbye?", ["1", "2", "3", "4"], "d", st, 2) # test question-set cascade assert db.questions.getById(q.getQid()) is not None assert db.questions.getById(q2.getQid()) is not None st.delete() assert db.questions.getById(q.getQid()) is None assert db.questions.getById(q2.getQid()) is None # test student-class cascade s = db.students.Student.createNew("Almzead", "Maud", "1", "ff8836", "*****@*****.**", c) tpid = s.getTpid() assert db.students.findStudentByTpid(tpid, c) is not None db.classes.deleteClass(c.getName()) assert db.students.findStudentByTpid(tpid, c) is None # test history/quiz-class cascade # (much code, with checks removed, from test_genquiz) def do(): cls = db.classes.Class.createNew("Test Class") st = db.sets.Set.createNew("Test Set", 1) q = db.questions.Question("What is the answer?", ["foo", "bar", "baz", "42"], "d", st, 1) q4 = db.questions.Question("What is the answer ?", ["foo", "bar", "baz", "42"], "d", st, 4) st2 = db.sets.Set.createNew("Test Set", 1) q2 = db.questions.Question("What is the answer to this?", ["foo", "bar", "baz", "42"], "c", st2, 2) q3 = db.questions.Question("What is the answer to this question?", ["foo", "bar", "baz", "42"], "c", st2, 3) quiz = Quiz(cls) quiz.addNewSet(st) quiz.addNewSet(st2) quiz.setNewQuestions(1) quiz.setRevQuestions(2) quiz._fillNewItems() sr = SetRescheduler() quiz.newQ[0].reschedule(3, sr) quiz.newQ[1].reschedule(2, sr) sr.runResched() d.inter.exQuery('UPDATE classes SET setsUsed=? WHERE cid=?', (7, cls.getCid())) d.inter.forceSave() quiz.resetNewSets() quiz.addNewSet(st2) quiz.finishSetup() quiz._randNew() quiz._randRev() qPrev = quiz.generate() oldSetsUsed = getSetsUsed(cls) quiz.rewriteSchedule() return cls, st # We now have a history entry and a quizzes entry. cls, st = do() quizHistoryItem = db.history.historyForClass(cls)[0] c = d.inter.exQuery('SELECT * FROM history WHERE sid=? AND cid=?', (st.getSid(), cls.getCid())) assert quizHistoryItem assert c.fetchall() db.classes.deleteClass(cls.getName()) with self.assertRaises(IndexError): quizHistoryItem = db.history.historyForClass(cls)[0] c = d.inter.exQuery('SELECT * FROM history WHERE sid=? AND cid=?', (st.getSid(), cls.getCid())) assert not c.fetchall()