def test_figures(): ass = Assignment() with ass.add_figure() as f: f.caption = "A" f.caption += " figure" f.filename = "image.png" assert len(ass._figures) == 1 assert ass._figures[0].filename == os.path.abspath("image.png") assert ass._figures[0].caption == "A figure" assert ass._figures[0].formatted_caption == "A figure" ass.NS.id = "1234" with ass.add_figure() as f: f.caption = "figure for question {id}" f.filename = "image.png" assert len(ass._figures) == 2 assert ass._figures[0].filename == os.path.abspath("image.png") assert ass._figures[0].caption == "A figure" assert ass._figures[0].formatted_caption == "A figure" assert ass._figures[1].filename == os.path.abspath("image.png") assert ass._figures[1].caption == "figure for question {id}" assert ass._figures[1].formatted_caption == "figure for question 1234"
def test_simple_writer(tmpdir): with utils.TempDir(tmpdir): ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_part() as p: p.text = "q1p1" with q.add_part() as p: p.text = "q1p2" with ass.add_question() as q: q.text = "q2" with q.add_part() as p: p.text = "q2p1" with q.add_part() as p: p.text = "q2p2" with pytest.raises(RuntimeError): w = Writers.Simple() w.dump(ass) fh = io.StringIO() writer = Writers.Simple(fh) writer.dump(ass)
def test_problem_set_builder(tmpdir): with utils.TempDir(tmpdir): ass = Assignment() with ass.add_question() as q: q.text += "Question 1" with q.add_question() as qq: qq.text += "What is the answer to Q1?" with qq.add_answer(Answer.Numerical) as a: a.quantity = 1.23 with ass.add_question() as q: q.text += "Question 2" with q.add_part() as p: p.text += "Question 2, Part 1" with p.add_question() as qq: qq.text += "What is the answer to Q2P1?" with qq.add_answer(Answer.Numerical) as a: a.quantity = 2.34 if os.path.exists("_test"): shutil.rmtree("_test") os.mkdir("_test") Actions.BuildProblemSetAndBlackboardQuiz(ass, "test") shutil.rmtree("_test") Actions.BuildProblemSetAndBlackboardQuiz(ass, "test", remove=True) assert os.path.isdir("_test") assert os.path.isfile("_test/test.tex") assert os.path.isfile("_test/test.pdf") assert os.path.isfile("_test/test.aux") assert os.path.isfile("_test/test-quiz.txt")
def test_blackboard_quiz_writer_output(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = "q1.1" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" a.correct += "a4" with ass.add_question() as q: q.text = "q1.2" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" a.incorrect += "a4" with ass.add_question() as q: q.text = "q2.1" with q.add_answer(Answer.Numerical) as a: a.quantity = 1.23 with ass.add_question() as q: q.text = "q2.2" with q.add_answer(Answer.Numerical) as a: a.quantity = u.Quantity(987654321, 'm/s') with ass.add_question() as q: q.text = "q2.3" with q.add_answer(Answer.Numerical) as a: a.quantity = u.Quantity(5432, '') with ass.add_question() as q: q.text = "q2.4" with q.add_answer(Answer.Numerical) as a: a.quantity = UQ_(Q_(10.234, 'm'), Q_(321, 'cm')) with ass.add_question() as q: q.text = "q3.1" with q.add_answer(Answer.Text) as a: a.text = "correct answer" with ass.add_question() as q: q.text = "q3.2" with q.add_answer(Answer.Text) as a: a.text = "first correct answer;second correct answer" writer.dump(ass) quiz_text = """\ MC\tq1.1\ta1\tincorrect\ta2\tincorrect\ta3\tincorrect\ta4\tcorrect\tNone of the above.\tincorrect MC\tq1.2\ta1\tincorrect\ta2\tincorrect\ta3\tincorrect\ta4\tincorrect\tNone of the above.\tcorrect NUM\tq2.1\t1.23E+00\t1.23E-02 NUM\tq2.2 Give your answer in meter / second.\t9.88E+08\t9.88E+06 NUM\tq2.3\t5.43E+03\t5.43E+01 NUM\tq2.4 Give your answer in meter.\t1.02E+01\t3.21E+00 FIB\tq3.1\tcorrect answer FIB\tq3.2\tfirst correct answer\tsecond correct answer """ assert fh.getvalue() == quiz_text
def test_blackboard_quiz_writer_raises_on_no_answers(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = "q1" with pytest.raises(RuntimeError): writer.dump(ass)
def test_question_tagging(): ass = Assignment() with ass.add_question() as q: q.tags = "topic 1" q.tags += "topic 2" q.text = "q1" with q.add_answer(Answer.Text) as a: a.text = 'the answer' with ass.add_question() as q: q.tags = "topic 3" q.text = "q2" with q.add_part() as p: p.text = "q2p1" with p.add_answer(Answer.Text) as a: a.quantity = 2.34 with ass.add_question() as q: q.text = "q3" q.tags = "topic 2" with q.add_part() as p: p.text = "q3p1" with p.add_answer(Answer.Text) as a: a.quantity = 3.10 with q.add_part() as p: p.text = "q3p2" with p.add_answer(Answer.Text) as a: a.quantity = 3.2 fass = Filters.filter( Filters.has_tag('topic 2'), ass ) assert len(fass._questions) == 2 assert fass._questions[0]._text == "q1" assert fass._questions[1]._text == "q3" fass = Filters.filter( Filters.has_tag('topic 3'), ass ) assert len(fass._questions) == 1 assert fass._questions[0]._text == "q2" fass = Filters.filter( Filters.has_tag("topic 2"), ass ) assert len(fass._questions) == 2 assert fass._questions[0]._text == "q1" assert fass._questions[1]._text == "q3" fass = Filters.filter( Filters.has_tag("topic 3"), ass ) assert len(fass._questions) == 1 assert fass._questions[0]._text == "q2" fass = Filters.filter( Filters.has_matching_tag("topic ."), ass ) assert len(fass._questions) == 3 assert fass._questions[0]._text == "q1" assert fass._questions[1]._text == "q2" assert fass._questions[2]._text == "q3"
def test_blackboard_quiz_writer_raises_on_unrecognized_answer_type(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.AnswerBase) as a: pass with pytest.raises(RuntimeError): writer.dump(ass)
def test_blackboard_quiz_writer_removed_newlines_in_question_text(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = '''A question with line breaks.''' with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.correct += "a2" writer.dump(ass) assert fh.getvalue( ) == "MC\tA question with line breaks.\ta1\tincorrect\ta2\tcorrect\tNone of the above.\tincorrect\n"
def test_information(): ass = Assignment() with ass.add_information() as info: info.text = "For each of the problems below..." with ass.add_question() as q: q.text = "Question 1" with ass.add_question() as q: q.text = "Question 2" with ass.add_information() as info: info.text = "For the next problem, assume..." with ass.add_question() as q: q.text = "Question 3" assert len(ass._questions) == 3 assert len(ass._information) == 2 assert 0 in ass._information assert 2 in ass._information assert ass._information[0].text == "For each of the problems below..." assert ass._information[2].text == "For the next problem, assume..."
def test_latex_writer_header_and_footers(): ass = Assignment() ass.meta.title = "The Title" ass.meta.header = { 'R': "right header", 'L': "left header", 'C': "center header" } ass.meta.footer = { 'R': "right footer", 'L': "left footer", 'C': "center footer" } ass.meta.config = { 'answers': { 'numerical/spacing': '2in', 'multiple_choice/symbol': r'\alph*)', 'text/spacing': r'3in' } } with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.correct += "a2" fh = io.StringIO() writer = Writers.Latex(fh) writer.make_key = True writer.dump(ass) print(fh.getvalue()) assert re.search("header", fh.getvalue()) assert re.search("footer", fh.getvalue()) assert re.search("left header", fh.getvalue()) assert re.search("center header", fh.getvalue()) assert re.search("right header", fh.getvalue()) assert re.search("left footer", fh.getvalue()) assert re.search("center footer", fh.getvalue()) assert re.search("right footer", fh.getvalue()) assert re.search(r"\\title\{The Title\}", fh.getvalue())
def test_blackboard_quiz_writer_output_with_macros(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = r"q1.1 \shell[strip]{pwd}" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" a.correct += "a4" writer.dump(ass) quiz_text = """\ MC\tq1.1 {CWD}\ta1\tincorrect\ta2\tincorrect\ta3\tincorrect\ta4\tcorrect\tNone of the above.\tincorrect """.format(CWD=os.path.abspath(os.getcwd())) assert fh.getvalue() == quiz_text
def test_demo(): ass = Assignment() with ass.add_question() as q: q.text = ''' Compute the gravitational force exerted on a {Mass1} object by: ''' q.NS.Mass1 = 1.2 with q.add_part() as p: p.text = ''' Earth. ''' with q.add_part() as p: p.text = ''' A {Mass2} object placed {Distance} away. ''' p.NS.Mass2 = 2.3
def test_latex_writer_raises_with_no_fh(): ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_part() as p: p.text = "q1p1" with q.add_part() as p: p.text = "q1p2" with ass.add_question() as q: q.text = "q2" with q.add_part() as p: p.text = "q2p1" with q.add_part() as p: p.text = "q2p2" with pytest.raises(RuntimeError): w = Writers.Latex() w.dump(ass)
def test_latex_writer(tmpdir): with utils.TempDir(tmpdir): fh = io.StringIO() writer = Writers.Latex(fh) writer.make_key = True ass = Assignment() ass.meta.title = "Homework Assignment" ass.meta.header = {'R': r"powered by \LaTeX"} ass.meta.config = { 'answers': { 'numerical/spacing': '2in', 'multiple_choice/symbol': r'\alph*)', 'text/spacing': r'3in' } } with ass.add_information() as info: info.text = "This is some information for the assignment." with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" a.correct += "a4" with ass.add_information() as info: info.text = "This information should appear between the first and second question." with ass.add_question() as q: q.text = "q2" with q.add_answer(Answer.Numerical) as a: a.quantity = 1.23 with ass.add_question() as q: q.text = "q3" with q.add_part() as p: p.text = "q3p1" with q.add_part() as p: p.text = "q3p2" with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.MultipleChoice) as a: a.correct += "a1" a.incorrect += "a2" a.incorrect += "a3" a.correct += "a4" writer.dump(ass) with open('test.tex', 'w') as f: f.write(fh.getvalue())
def test_extract_quiz(): ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_question() as qq: qq.text = "q1:qq" with qq.add_answer(Answer.Text) as a: a.text = 'the answer' with ass.add_question() as q: q.text = "q2" with q.add_part() as p: p.text = "q2p1" with q.add_question() as qq: qq.text = "q2p1:qq" with ass.add_question() as q: q.text = "q3" with q.add_part() as p: p.text = "q3p1" with q.add_question() as qq: qq.text = "q3p1:qq" with q.add_part() as p: p.text = "q3p2" filt = Filters.QuizExtractor() quiz = filt.filter(ass) fh = io.StringIO() writer = Writers.Simple(fh) writer.dump(quiz)
def test_blackboard_quiz_writer_raises_on_multiple_choice_with_no_correct_answer( ): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) writer.config.add_none_of_the_above_choice = False ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" with pytest.raises(RuntimeError): writer.dump(ass) writer.config.add_none_of_the_above_choice = True writer.dump(ass) ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.MultipleChoice) as a: a.meta.add_none_of_the_above_choice = False a.incorrect += "a1" a.incorrect += "a2" a.incorrect += "a3" with pytest.raises(RuntimeError): writer.dump(ass)
def test_question_text(): ass = Assignment() with ass.add_question() as q: q.text = "question 1 text" q.NS.x = 10 # with q.add_answer( Numerical ) as a: # def calc(x): # return 2*x # a.NS.calc = calc with q.add_part() as p: p.text = "question 1, part 1 text" with q.add_part() as p: p.text = "question 1, part 2 text" with ass.add_question() as q: q.text = "question 2 text" with q.add_part() as p: p.text = "question 2, part 1 text" with q.add_part() as p: p.text = "question 2, part 2 text" # with q.add_answer( MultipleChoice ) as a: # a.choices = ''' # incorrect # ^correct" # also not correct # incorrect 4 # ''' assert ass._questions[0]._text == "question 1 text" assert ass._questions[0]._parts[0]._text == "question 1, part 1 text" assert ass._questions[0]._parts[1]._text == "question 1, part 2 text" assert ass._questions[1]._text == "question 2 text" assert ass._questions[1]._parts[0]._text == "question 2, part 1 text" assert ass._questions[1]._parts[1]._text == "question 2, part 2 text"
def test_blackboard_writer_figures(tmpdir): with utils.TempDir(tmpdir): image_text = r"""<?xml version="1.0" encoding="UTF-8" ?> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <circle cx="125" cy="125" r="75" fill="orange" /> </svg> """ with open("file.svg", "w") as f: f.write(image_text) fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = "See image above." with q.add_figure() as f: f.filename = "file.svg" with q.add_answer(Answer.MultipleChoice) as a: a.incorrect += "a" a.correct += "b" with ass.add_question() as q: q.text = "no image here." with q.add_answer(Answer.MultipleChoice) as a: a.correct += "a" a.incorrect += "b" writer.dump(ass) quiz_text = """\ MC\t{IMAGE_TEXT}</br>Consider the figure above. See image above.\ta\tincorrect\tb\tcorrect\tNone of the above.\tincorrect MC\tno image here.\ta\tcorrect\tb\tincorrect\tNone of the above.\tincorrect """.format(IMAGE_TEXT=image_text.replace("\n", " ")) assert fh.getvalue() == quiz_text with open("Bb-quiz-with-figure.txt", "w") as f: writer.dump(ass, f)
def test_blackboard_quiz_writer_with_numerical_answer_tolerance(): fh = io.StringIO() writer = Writers.BlackboardQuiz(fh) ass = Assignment() with ass.add_question() as q: q.text = "q1" with q.add_answer(Answer.Numerical) as a: a.quantity = UQ_(Q_(10, 'm'), Q_(1, 'm')) with ass.add_question() as q: q.text = "q2" with q.add_answer(Answer.Numerical) as a: a.quantity = UQ_(Q_('10', 'm'), Q_('1', 'cm')) with ass.add_question() as q: q.text = "q3" with q.add_answer(Answer.Numerical) as a: a.quantity = Q_(10, 'm') with ass.add_question() as q: q.text = "q4" with q.add_answer(Answer.Numerical) as a: a.quantity = Q_('10', 'm') writer.dump(ass)
def test_test_question_bank(): bank = Assignment() def CalcAnswer(Mass): return (Mass * Q_(9.8, 'm/s^2')).to("N") with bank.add_question() as q: q.text = r'''How much does a {Mass:} weigh?''' q.tags += "M1" q.tags += "L1" q.NS.Mass = Q_(10, 'kg') with q.add_answer(Answer.Numerical) as a: a.quantity = CalcAnswer with bank.add_question(copy.deepcopy(q)) as q: q.NS.Mass = Q_(20, 'kg') q.answer.NS.__dict__.update(q.NS.__dict__) with bank.add_question(copy.deepcopy(q)) as q: q.NS.Mass = Q_(30, 'kg') q.answer.NS.__dict__.update(q.NS.__dict__) def CalcAnswer(Mass1, Mass2, Distance): # a_r = v^2 / r = G m1 / r^2 # v^2 = G m1 / r # v = sqrt( G m1 / r ) G = Q_(6.674e-11, 'N kg^-2 m^2') return ((G * Mass1 / Distance)**0.5).to('m/s') with bank.add_question() as q: q.text = r'''How fast will a {Mass1} mass in a {Distance} orbit around a {Mass2} mass be traveling?''' q.tags += "M1" q.tags += "L2" q.NS.Mass1 = Q_(10, 'kg') q.NS.Mass2 = Q_(300, 'kg') q.NS.Distance = Q_(10, 'm') with q.add_answer(Answer.Numerical) as a: a.quantity = CalcAnswer with bank.add_question(copy.deepcopy(q)) as q: q.NS.Mass1 = Q_(35, 'kg') q.answer.NS.__dict__.update(q.NS.__dict__) with bank.add_question(copy.deepcopy(q)) as q: q.NS.Mass1 = Q_(500, 'kg') q.answer.NS.__dict__.update(q.NS.__dict__) test1 = Assignment() test2 = Assignment() test3 = Assignment() test4 = Assignment() for q in PullRandomQuestions(bank, predicate=(has_tag("M1") & has_tag("L1"))): with test1.add_question(q): pass for q in PullRandomQuestions(bank, predicate=(has_tag("M1") | has_tag("L1"))): with test2.add_question(q): pass for q in PullRandomQuestions(bank, num=2, predicate=(has_tag("M1") & has_tag("L1"))): with test3.add_question(q): pass for q in PullRandomQuestions(bank, num=2, predicate=(has_tag("M1") | has_tag("L1"))): with test4.add_question(q): pass assert len(test1._questions) == 3 assert len(test2._questions) == 6 assert len(test3._questions) == 2 assert len(test4._questions) == 2 with pytest.raises(RuntimeError): PullRandomQuestions(bank, num=2, predicate=has_tag("Missing")) assert CheckQuestionBank(bank, Checks.has_a_tag) assert CheckQuestionBank(bank, has_tag("M1")) assert not CheckQuestionBank(bank, has_tag("M2")) assert CheckQuestionBank(bank, Checks.has_answer) with bank.add_question() as q: q.text = "None" assert not CheckQuestionBank(bank, Checks.has_answer) del bank._questions[-1] assert CheckQuestionBank(bank, Checks.has_answer) with bank.add_question() as q: q.text = "None" with q.add_answer(Answer.MultipleChoice) as a: pass assert not CheckQuestionBank(bank, Checks.has_answer) del bank._questions[-1] assert CheckQuestionBank(bank, Checks.has_answer) with bank.add_question() as q: q.text = "None" with q.add_answer(Answer.MultipleChoice) as a: a.correct += "A" assert CheckQuestionBank(bank, Checks.has_answer)
def test_update(): ass1 = Assignment() ass2 = Assignment() with ass1.add_question() as q: q.text = "A1Q1" with ass1.add_question() as q: q.text = "A1Q2" with ass2.add_question() as q: q.text = "A2Q1" assert len(ass1._questions) == 2 assert len(ass2._questions) == 1 assert ass1._questions[0]._text == "A1Q1" assert ass1._questions[1]._text == "A1Q2" assert ass2._questions[0]._text == "A2Q1" ass1.update(ass2) assert len(ass1._questions) == 3 assert len(ass2._questions) == 1 assert ass1._questions[0]._text == "A1Q1" assert ass1._questions[1]._text == "A1Q2" assert ass1._questions[2]._text == "A2Q1" assert ass2._questions[0]._text == "A2Q1" ass2.update(ass1) assert len(ass1._questions) == 3 assert len(ass2._questions) == 4 assert ass1._questions[0]._text == "A1Q1" assert ass1._questions[1]._text == "A1Q2" assert ass1._questions[2]._text == "A2Q1" assert ass2._questions[0]._text == "A2Q1" assert ass2._questions[1]._text == "A1Q1" assert ass2._questions[2]._text == "A1Q2" assert ass2._questions[3]._text == "A2Q1"
import os, sys from pyAssignment.Assignment import Assignment import pyAssignment.Assignment.Answers as Answer from pyAssignment.Actions import BuildProblemSetAndBlackboardQuiz import pint units = pint.UnitRegistry() Q_ = units.Quantity ass = Assignment() ass.meta.title = r'Simple Assignment' with ass.add_question() as q: q.text = r'''Calculate the weight of a 20 kg mass.''' with q.add_question() as qq: qq.text = r'''What is the mass?''' with qq.add_answer(Answer.Numerical) as a: a.quantity = (Q_(20, 'kg') * Q_(9.8, 'm/s^2')).to('N') basename = os.path.basename(__file__).replace(".py", "") BuildProblemSetAndBlackboardQuiz(ass, basename)