From 763f96559bd1827ce87a72708d72efc9361ef588 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Mon, 16 Jun 2014 17:04:40 +0530 Subject: Models modified. QuestionPaper model modified for generating random questions. Added language field to Question model. Removed tags from Quiz model. Template and javascript for Add and Edit questions modified. Added test cases for models. --- testapp/exam/forms.py | 23 +++- testapp/exam/models.py | 140 ++++++++++++++----- testapp/exam/tests.py | 222 ++++++++++++++++++++++++++++-- testapp/exam/views.py | 56 +------- testapp/static/exam/js/add_question.js | 29 +++- testapp/static/exam/js/edit_question.js | 51 +++++-- testapp/templates/exam/add_question.html | 6 +- testapp/templates/exam/add_quiz.html | 3 - testapp/templates/exam/edit_question.html | 12 +- testapp/templates/exam/edit_quiz.html | 4 - 10 files changed, 420 insertions(+), 126 deletions(-) diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index dc19783..e82ce3a 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -12,7 +12,8 @@ from taggit_autocomplete_modified import settings from string import letters, punctuation, digits import datetime -QUESTION_TYPE_CHOICES = ( +QUESTION_LANGUAGE_CHOICES = ( + ("select", "Select"), ("python", "Python"), ("bash", "Bash"), ("mcq", "MCQ"), @@ -20,7 +21,13 @@ QUESTION_TYPE_CHOICES = ( ("C++", "C++ Language"), ("java", "Java Language"), ("scilab", "Scilab"), - ) + ) + +QUESTION_TYPE_CHOICES = ( + ("select", "Select"), + ("mcq", "Multiple Choice"), + ("code", "Code"), + ) UNAME_CHARS = letters + "._" + digits PWD_CHARS = letters + punctuation + digits @@ -51,8 +58,8 @@ class UserRegisterForm(forms.Form): def clean_username(self): u_name = self.cleaned_data["username"] if u_name.strip(UNAME_CHARS): - msg = "Only letters, digits, period and underscore characters are "\ - "allowed in username" + msg = "Only letters, digits, period and underscore characters are"\ + " allowed in username" raise forms.ValidationError(msg) try: User.objects.get(username__exact=u_name) @@ -96,6 +103,7 @@ class UserRegisterForm(forms.Form): return u_name, pwd + class UserLoginForm(forms.Form): """Creates a form which will allow the user to log into the system.""" @@ -115,6 +123,7 @@ class UserLoginForm(forms.Form): raise forms.ValidationError("Invalid username/password") return user + class QuizForm(forms.Form): """Creates a form to add or edit a Quiz. It has the related fields and functions required.""" @@ -122,7 +131,6 @@ class QuizForm(forms.Form): start_date = forms.DateField(initial=datetime.date.today) duration = forms.IntegerField() active = forms.BooleanField(required=False) - tags = TagField(widget=TagAutocomplete()) description = forms.CharField(max_length=256, widget=forms.Textarea\ (attrs={'cols': 20, 'rows': 1})) @@ -139,6 +147,7 @@ class QuizForm(forms.Form): new_quiz.description = description new_quiz.save() + class QuestionForm(forms.Form): """Creates a form to add or edit a Question. It has the related fields and functions required.""" @@ -152,6 +161,8 @@ class QuestionForm(forms.Form): (attrs={'cols': 40, 'rows': 1})) options = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1}), required=False) + language = forms.CharField(max_length=20, widget=forms.Select\ + (choices=QUESTION_LANGUAGE_CHOICES)) type = forms.CharField(max_length=8, widget=forms.Select\ (choices=QUESTION_TYPE_CHOICES)) active = forms.BooleanField(required=False) @@ -165,6 +176,7 @@ class QuestionForm(forms.Form): points = self.cleaned_data['points'] test = self.cleaned_data["test"] options = self.cleaned_data['options'] + language = self.cleaned_data['language'] type = self.cleaned_data["type"] active = self.cleaned_data["active"] snippet = self.cleaned_data["snippet"] @@ -175,6 +187,7 @@ class QuestionForm(forms.Form): new_question.points = points new_question.test = test new_question.options = options + new_question.language = language new_question.type = type new_question.active = active new_question.snippet = snippet diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 758091f..ca53b2c 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -1,12 +1,12 @@ import datetime +from random import sample from django.db import models from django.contrib.auth.models import User from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete\ as TaggableManager -from django.http import HttpResponse -################################################################################ +############################################################################### class Profile(models.Model): """Profile for a user to store roll number and other details.""" user = models.OneToOneField(User) @@ -16,25 +16,30 @@ class Profile(models.Model): position = models.CharField(max_length=64) -QUESTION_TYPE_CHOICES = ( +QUESTION_LANGUAGE_CHOICES = ( ("python", "Python"), ("bash", "Bash"), - ("mcq", "MultipleChoice"), ("C", "C Language"), ("C++", "C++ Language"), ("java", "Java Language"), ("scilab", "Scilab"), + ) + + +QUESTION_TYPE_CHOICES = ( + ("mcq", "Multiple Choice"), + ("code", "Code"), ) -################################################################################ +############################################################################### class Question(models.Model): - """A question in the database.""" + """A question details in the database.""" # A one-line summary of the question. summary = models.CharField(max_length=256) - # The question text, should be valid HTML. + # The question text, should be a valid HTML. description = models.TextField() # Number of points for the question. @@ -43,31 +48,35 @@ class Question(models.Model): # Test cases for the question in the form of code that is run. test = models.TextField(blank=True) - # Any multiple choice options. Place one option per line. + # Any multiple choice options. Place one option per line. options = models.TextField(blank=True) + # The language for question. + language = models.CharField(max_length=24, + choices=QUESTION_LANGUAGE_CHOICES) + # The type of question. type = models.CharField(max_length=24, choices=QUESTION_TYPE_CHOICES) - # Is this question active or not. If it is inactive it will not be used + # Is this question active or not. If it is inactive it will not be used # when creating a QuestionPaper. active = models.BooleanField(default=True) - #Code Snippet + # Code Snippet snippet = models.CharField(max_length=256) - #Tags for the Question. + # Tags for the Question. tags = TaggableManager() def __unicode__(self): return self.summary -################################################################################ +############################################################################### class Answer(models.Model): - """Answers submitted by users. - """ - # The question for which we are an answer. + """Answers submitted by the users.""" + + # The question for which user answers. question = models.ForeignKey(Question) # The answer submitted by the user. @@ -76,7 +85,7 @@ class Answer(models.Model): # Error message when auto-checking the answer. error = models.TextField() - # Marks obtained for the answer. This can be changed by the teacher if the + # Marks obtained for the answer. This can be changed by the teacher if the # grading is manual. marks = models.FloatField(default=0.0) @@ -87,44 +96,103 @@ class Answer(models.Model): return self.answer -################################################################################ +############################################################################### class Quiz(models.Model): """A quiz that students will participate in. One can think of this as the "examination" event. """ - # The starting/ending date of the quiz. + # The start date of the quiz. start_date = models.DateField("Date of the quiz") # This is always in minutes. duration = models.IntegerField("Duration of quiz in minutes", default=20) - # Is the quiz active. The admin should deactivate the quiz once it is + # Is the quiz active. The admin should deactivate the quiz once it is # complete. active = models.BooleanField(default=True) # Description of quiz. description = models.CharField(max_length=256) - #Tags for the Quiz. - tags = TaggableManager() - class Meta: verbose_name_plural = "Quizzes" def __unicode__(self): desc = self.description or 'Quiz' - return '%s: on %s for %d minutes' % (desc, self.start_date, self.duration) + return '%s: on %s for %d minutes' % (desc, self.start_date, + self.duration) -################################################################################ +############################################################################### class QuestionPaper(models.Model): + """Question paper stores the detail of the questions.""" + + # Question paper belongs to a particular quiz. quiz = models.ForeignKey(Quiz) - questions = models.ManyToManyField(Question) + + # Questions that will be mandatory in the quiz. + fixed_questions = models.ManyToManyField(Question) + + # Questions that will be fetched randomly from the Question Set. + random_questions = models.ManyToManyField("QuestionSet") + + # Total marks for the question paper. total_marks = models.FloatField() + def get_total_marks(self): + """ Returns the total marks for the Question Paper""" + marks = 0.0 + questions = self.fixed_questions.all() + for question in questions: + marks += question.points + for question_set in self.random_questions.all(): + marks += question_set.marks * question_set.num_questions + return marks + + def _get_questions_for_answerpaper(self): + """ Returns fixed and random questions for the answer paper""" + questions = [] + questions = list(self.fixed_questions.all()) + for question_set in self.random_questions.all(): + questions += question_set.get_random_questions() + return questions + + def make_answerpaper(self, user, profile, ip): + """Creates an answer paper for the user to attempt the quiz""" + ans_paper = AnswerPaper(user=user, profile=profile, user_ip=ip) + ans_paper.start_time = datetime.datetime.now() + ans_paper.end_time = ans_paper.start_time \ + + datetime.timedelta(minutes=self.quiz.duration) + ans_paper.question_paper = self + questions = self._get_questions_for_answerpaper() + question_ids = [str(_.id) for _ in questions] + ans_paper.questions = "|".join(question_ids) + ans_paper.save() + return ans_paper + + +############################################################################### +class QuestionSet(models.Model): + """Question set contains set of questions from which random questions + will be selected for the quiz. + """ + + # Marks of each question of a particular Question Set + marks = models.FloatField() + + # Number of questions to be fetched for the quiz. + num_questions = models.IntegerField() + + # Set of questions for sampling randomly. + questions = models.ManyToManyField(Question) + + def get_random_questions(self): + """ Returns random questions from set of questions""" + return sample(self.questions.all(), self.num_questions) -################################################################################ + +############################################################################### class AnswerPaper(models.Model): """A answer paper for a student -- one per student typically. """ @@ -135,7 +203,8 @@ class AnswerPaper(models.Model): # data. profile = models.ForeignKey(Profile) - # All questions that remains to attempt to perticular Student + # All questions that are left to attempt for a particular Student + # (a list of ids separated by '|') questions = models.CharField(max_length=128) # The Quiz to which this question paper is attached to. @@ -176,8 +245,10 @@ class AnswerPaper(models.Model): return qs.count('|') + 1 def completed_question(self, question_id): - """Removes the question from the list of questions and returns -the next.""" + """ + Removes the completed question from the list of questions and + returns the next question. + """ qa = self.questions_answered if len(qa) > 0: self.questions_answered = '|'.join([qa, str(question_id)]) @@ -193,7 +264,9 @@ the next.""" return qs[0] def skip(self): - """Skip the current question and return the next available question.""" + """ + Skips the current question and returns the next available question. + """ qs = self.questions.split('|') if len(qs) == 0: return '' @@ -223,13 +296,14 @@ the next.""" answered = ', '.join(sorted(qa)) return answered if answered else 'None' - def get_total_marks(self): + def get_marks_obtained(self): """Returns the total marks earned by student for this paper.""" return sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) def get_question_answers(self): - """Return a dictionary with keys as questions and a list of the corresponding - answers. + """ + Return a dictionary with keys as questions and a list of the + corresponding answers. """ q_a = {} for answer in self.answers.all(): diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index 501deb7..ac63301 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -1,16 +1,214 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". +from django.utils import unittest +from exam.models import User, Profile, Question, Quiz, QuestionPaper,\ +QuestionSet, AnswerPaper -Replace this with more appropriate tests for your application. -""" -from django.test import TestCase +class ModelsTestCase(unittest.TestCase): + @classmethod + def setUpClass(self): + """ Initial fixtures for testing environment""" -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) + # create user profile + self.user = User.objects.create_user(username='demo_user', + password='demo', + email='demo@test.com') + self.profile = Profile.objects.create(user=self.user, roll_number=1, + institute='IIT', + department='Chemical', + position='Student') + + # create 20 questions + for i in range(1, 21): + Question.objects.create(summary='Q%d' % (i)) + + # All active questions + self.questions = Question.objects.filter(active=True) + + # Single question details + self.question = self.questions[0] + self.question.summary = 'Demo question' + self.question.language = 'Python' + self.question.type = 'Code' + self.question.options = None + self.question.description = 'Write a function' + self.question.points = 1.0 + self.question.active = True + self.question.test = 'Test Cases' + self.question.snippet = 'def myfunc()' + self.question.tags.add('python', 'function') + + # create a quiz + self.quiz = Quiz.objects.create(start_date='2014-06-16', + duration=30, active=False, + description='demo quiz') + + # create question paper + self.quest_paper = QuestionPaper.objects.create(quiz=self.quiz, + total_marks=0.0) + + # add fixed set of questions to the question paper + self.quest_paper.fixed_questions.add(self.questions[3], + self.questions[5]) + + # create two QuestionSet for random questions + # QuestionSet 1 + self.quest_set_1 = QuestionSet.objects.create(marks=2, num_questions=2) + + # add pool of questions for random sampling + self.quest_set_1.questions.add(self.questions[6], self.questions[7], + self.questions[8], self.questions[9]) + + # add question set 1 to random questions in Question Paper + self.quest_paper.random_questions.add(self.quest_set_1) + + # QuestionSet 2 + self.quest_set_2 = QuestionSet.objects.create(marks=3, num_questions=3) + + # add pool of questions + self.quest_set_2.questions.add(self.questions[11], self.questions[12], + self.questions[13], self.questions[14]) + + # add question set 2 + self.quest_paper.random_questions.add(self.quest_set_2) + + # ip address for AnswerPaper + self.ip = '127.0.0.1' + + # create answerpaper + self.answerpaper = AnswerPaper(user=self.user, profile=self.profile, + questions='1|2|3', + question_paper=self.quest_paper, + start_time='2014-06-13 12:20:19.791297', + end_time='2014-06-13 12:50:19.791297', + user_ip=self.ip) + +############################################################################### + def test_user_profile(self): + """ Test user profile""" + self.assertIs(type(self.profile), type(Profile())) + self.assertEqual(self.user.username, 'demo_user') + self.assertEqual(self.profile.user.username, 'demo_user') + self.assertEqual(self.profile.roll_number, 1) + self.assertEqual(self.profile.institute, 'IIT') + self.assertEqual(self.profile.department, 'Chemical') + self.assertEqual(self.profile.position, 'Student') + + def test_question(self): + """ Test question """ + self.assertIs(type(self.question), type(Question())) + self.assertEqual(self.question.summary, 'Demo question') + self.assertEqual(self.question.language, 'Python') + self.assertEqual(self.question.type, 'Code') + self.assertTrue(self.question.options is None) + self.assertEqual(self.question.description, 'Write a function') + self.assertEqual(self.question.points, 1.0) + self.assertTrue(self.question.active) + self.assertEqual(self.question.test, 'Test Cases') + self.assertEqual(self.question.snippet, 'def myfunc()') + tag_list = [] + for tag in self.question.tags.all(): + tag_list.append(tag.name) + self.assertEqual(tag_list, ['python', 'function']) + self.assertEqual(len(self.questions), 20) + + def test_quiz(self): + """ Test Quiz""" + self.assertIs(type(self.quiz), type(Quiz())) + self.assertEqual(self.quiz.start_date, '2014-06-16') + self.assertEqual(self.quiz.duration, 30) + self.assertTrue(self.quiz.active is False) + self.assertEqual(self.quiz.description, 'demo quiz') + + def test_questionpaper(self): + """ Test question paper""" + self.assertIs(type(self.quest_paper), type(QuestionPaper())) + self.assertEqual(self.quest_paper.quiz.description, 'demo quiz') + self.assertEqual(list(self.quest_paper.fixed_questions.all()), + [self.questions[3], self.questions[5]]) + + def test_get_random_questions(self): + """ Test get_random_questions() method of Question Paper """ + random_questions_set_1 = set(self.quest_set_1.get_random_questions()) + random_questions_set_2 = set(self.quest_set_2.get_random_questions()) + + # To check whether random questions are from random_question_set + boolean = set(self.quest_set_1.questions.all()).\ + intersection(random_questions_set_1)\ + == random_questions_set_1 + self.assertTrue(boolean) + self.assertEqual(len(random_questions_set_1), 2) + self.assertFalse(random_questions_set_1 == random_questions_set_2) + + def test_get_questions_for_answerpaper(self): + """ Test get_questions_for_answerpaper() method of Question Paper""" + questions = self.quest_paper._get_questions_for_answerpaper() + fixed = list(self.quest_paper.fixed_questions.all()) + quest_set = self.quest_paper.random_questions.all() + total_random_questions = 0 + available_questions = [] + for qs in quest_set: + total_random_questions += qs.num_questions + available_questions += qs.questions.all() + self.assertEqual(total_random_questions, 5) + self.assertEqual(len(available_questions), 8) + self.assertEqual(len(questions), 7) + + def test_make_answerpaper(self): + """ Test make_answerpaper() method of Question Paper""" + answerpaper = self.quest_paper.make_answerpaper(self.user, + self.profile, self.ip) + self.assertIs(type(answerpaper), type(AnswerPaper())) + paper_questions = set((answerpaper.questions).split('|')) + self.assertEqual(len(paper_questions), 7) + fixed = {'4', '6'} + boolean = fixed.intersection(paper_questions) == fixed + self.assertTrue(boolean) + + def test_answerpaper(self): + """ Test Answer Paper""" + self.assertIs(type(self.answerpaper), type(AnswerPaper())) + self.assertEqual(self.answerpaper.user.username, 'demo_user') + self.assertEqual(self.answerpaper.profile_id, 1) + self.assertEqual(self.answerpaper.user_ip, self.ip) + questions = self.answerpaper.questions + num_questions = len(questions.split('|')) + self.assertEqual(questions, '1|2|3') + self.assertEqual(num_questions, 3) + self.assertEqual(self.answerpaper.question_paper, self.quest_paper) + self.assertEqual(self.answerpaper.question_paper, self.quest_paper) + self.assertEqual(self.answerpaper.start_time, + '2014-06-13 12:20:19.791297') + self.assertEqual(self.answerpaper.end_time, + '2014-06-13 12:50:19.791297') + + def test_current_question(self): + """ Test current_question() method of Answer Paper""" + current_question = self.answerpaper.current_question() + self.assertTrue(current_question is not None) + + def test_completed_question(self): + """ Test completed_question() method of Answer Paper""" + question = self.answerpaper.completed_question(3) + self.assertTrue(question is not None) + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_questions_left(self): + """ Test questions_left() method of Answer Paper""" + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_skip(self): + """ Test skip() method of Answer Paper""" + self.assertTrue(self.answerpaper.skip() is not None) + + def test_answered_str(self): + """ Test answered_str() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_answered_str(), 'None') + + def test_get_marks_obtained(self): + """ Test get_marks_obtained() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_marks_obtained(), 0) + + def test_get_question_answer(self): + """ Test get_question_answer() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_question_answers(), {}) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 92dd029..76773cb 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -166,7 +166,7 @@ def results_user(request): papers = AnswerPaper.objects.filter(user=user) quiz_marks = [] for paper in papers: - marks_obtained = paper.get_total_marks() + marks_obtained = paper.get_marks_obtained() max_marks = paper.question_paper.total_marks percentage = round((marks_obtained/max_marks)*100, 2) temp = paper.question_paper.quiz.description, marks_obtained,\ @@ -187,7 +187,6 @@ def edit_quiz(request): duration = request.POST.getlist('duration') active = request.POST.getlist('active') description = request.POST.getlist('description') - tags = request.POST.getlist('tags') for j, quiz_id in enumerate(quiz_list): quiz = Quiz.objects.get(id=quiz_id) @@ -196,14 +195,6 @@ def edit_quiz(request): quiz.active = active[j] quiz.description = description[j] quiz.save() - edit_tags = tags[j] - quiz.save() - for tag in quiz.tags.all(): - quiz.tags.remove(tag) - tags_split = edit_tags.split(', ') - for i in range(0, len(tags_split)-1): - tag = tags_split[i].strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/showquiz/") @@ -222,7 +213,6 @@ def edit_question(request): type = request.POST.getlist('type') active = request.POST.getlist('active') snippet = request.POST.getlist('snippet') - tags = request.POST.getlist('tags') for j, question_id in enumerate(question_list): question = Question.objects.get(id=question_id) question.summary = summary[j] @@ -233,14 +223,7 @@ def edit_question(request): question.active = active[j] question.snippet = snippet[j] question.type = type[j] - edit_tags = tags[j] question.save() - for tag in question.tags.all(): - question.tags.remove(tag) - tags_split = edit_tags.split(',') - for i in range(0, len(tags_split)-1): - tag = tags_split[i].strip() - question.tags.add(tag) return my_redirect("/exam/manage/questions") @@ -331,10 +314,6 @@ def add_quiz(request, quiz_id=None): if quiz_id is None: form.save() quiz = Quiz.objects.order_by("-id")[0] - tags = form['tags'].data.split(',') - for tag in tags: - tag = tag.strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/designquestionpaper") else: d = Quiz.objects.get(id=quiz_id) @@ -344,12 +323,6 @@ def add_quiz(request, quiz_id=None): d.description = form['description'].data d.save() quiz = Quiz.objects.get(id=quiz_id) - for tag in quiz.tags.all(): - quiz.tags.remove(tag) - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/showquiz") else: return my_render_to_response('exam/add_quiz.html', @@ -368,14 +341,6 @@ def add_quiz(request, quiz_id=None): form.initial['duration'] = d.duration form.initial['description'] = d.description form.initial['active'] = d.active - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags return my_render_to_response('exam/add_quiz.html', {'form': form}, context_instance=ci) @@ -398,7 +363,7 @@ def show_all_questionpapers(request, questionpaper_id=None): if request.method == "POST" and request.POST.get('add') == "add": return my_redirect("/exam/manage/designquestionpaper/" + - questionpaper_id) + questionpaper_id) if request.method == "POST" and request.POST.get('delete') == "delete": data = request.POST.getlist('papers') @@ -545,7 +510,7 @@ def manual_questionpaper(request, questionpaper_id=None): msg = 'No matching Question found...' tags = Tag.objects.all() context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} + 'tags': tags, 'msg': msg}} return my_render_to_response('exam/manual_questionpaper.html', context, context_instance=ci) @@ -578,7 +543,7 @@ def manual_questionpaper(request, questionpaper_id=None): msg = 'No matching Question found...' tags = Tag.objects.all() context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} + 'tags': tags, 'msg': msg}} return my_render_to_response('exam/manual_questionpaper.html', context, context_instance=ci) @@ -665,7 +630,8 @@ def start(request, questionpaper_id=None): # Make user directory. user_dir = get_user_dir(user) - questions = [str(_.id) for _ in questionpaper.questions.all()] + questions = [str(_.id) for _ in\ + questionpaper._get_questions_for_answerpaper()] random.shuffle(questions) new_paper.questions = "|".join(questions) @@ -822,7 +788,7 @@ def complete(request, reason=None, questionpaper_id=None): else: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get(user=user, question_paper=q_paper) - obt_marks = paper.get_total_marks() + obt_marks = paper.get_marks_obtained() tot_marks = paper.question_paper.total_marks if obt_marks == paper.question_paper.total_marks: context = {'message': "Hurray ! You did an excellent job.\ @@ -953,14 +919,6 @@ def show_all_quiz(request): form.initial['duration'] = d.duration form.initial['active'] = d.active form.initial['description'] = d.description - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags forms.append(form) return my_render_to_response('exam/edit_quiz.html', {'forms': forms, 'data': data}, diff --git a/testapp/static/exam/js/add_question.js b/testapp/static/exam/js/add_question.js index ba17492..56fdd1f 100644 --- a/testapp/static/exam/js/add_question.js +++ b/testapp/static/exam/js/add_question.js @@ -135,7 +135,19 @@ function textareaformat() $('#id_snippet').bind('blur', function( event ){ document.getElementById("id_snippet").rows=1; document.getElementById("id_snippet").cols=40; - }); + }); + + + $('#id_type').bind('focus', function(event){ + var type = document.getElementById('id_type'); + type.style.border = '1px solid #ccc'; + }); + + $('#id_language').bind('focus', function(event){ + var language = document.getElementById('id_language'); + language.style.border = '1px solid #ccc'; + }); + $('#id_type').bind('change',function(event){ var value = document.getElementById('id_type').value; if(value == 'mcq') @@ -167,7 +179,20 @@ function textareaformat() function autosubmit() { - if (document.getElementById('id_type').value == 'mcq') + var language = document.getElementById('id_language'); + if(language.value == 'select') + { + language.style.border="solid red"; + return false; + } + var type = document.getElementById('id_type'); + if(type.value == 'select') + { + type.style.border = 'solid red'; + return false; + } + + if (type.value == 'mcq') { var value = document.getElementById('id_options').value; if(value.split('\n').length < 4) diff --git a/testapp/static/exam/js/edit_question.js b/testapp/static/exam/js/edit_question.js index 28d95f9..c5df631 100644 --- a/testapp/static/exam/js/edit_question.js +++ b/testapp/static/exam/js/edit_question.js @@ -120,6 +120,7 @@ function textareaformat() var option = document.getElementsByName('options'); var descriptions = document.getElementsByName('description'); var snippets = document.getElementsByName('snippet'); + var language = document.getElementsByName('language') var type = document.getElementsByName('type'); var tags = document.getElementsByName('tags'); for (var i=0;i diff --git a/testapp/templates/exam/add_quiz.html b/testapp/templates/exam/add_quiz.html index 9851584..c2533de 100644 --- a/testapp/templates/exam/add_quiz.html +++ b/testapp/templates/exam/add_quiz.html @@ -5,11 +5,8 @@ {% block css %} - {% endblock %} {% block script %} - - {% endblock %} {% block onload %} onload="javascript:test();" {% endblock %} diff --git a/testapp/templates/exam/edit_question.html b/testapp/templates/exam/edit_question.html index 73e61d7..b28cc3e 100644 --- a/testapp/templates/exam/edit_question.html +++ b/testapp/templates/exam/edit_question.html @@ -30,15 +30,15 @@
Summary: {{ form.summary }}{{ form.summary.errors }} -
Points:{{ form.points }}{{ form.points.errors }}   Active:   {{ form.active }}{{form.active.errors}}   Type:  {{ form.type }}{{form.type.errors}} -
Rendered:

+
Language: {{form.language}}{{form.language.errors}} +
Active: {{ form.active }}{{form.active.errors}}   Type:  {{ form.type }}{{form.type.errors}} +
Points:{{ form.points }}{{ form.points.errors }} +
Rendered:

Description: {{ form.description}} {{form.description.errors}}
Test: {{ form.test }}{{form.test.errors}}
Snippet: {{ form.snippet }}{{ form.snippet.errors }}
-
Summary: {{ form.summary }}{{ form.summary.errors }} - -
Points:{{ form.points }}{{ form.points.errors }}   Active:   {{ form.active }}{{form.active.errors}}   Type:  {{ form.type }}{{form.type.errors}} - +
Language: {{form.language}}{{form.language.errors}} +
Active:   {{ form.active }}{{form.active.errors}}   Type:  {{ form.type }}{{form.type.errors}} +
Points:{{ form.points }}{{ form.points.errors }}
Rendered:

Description: {{ form.description }} {{form.description.errors}} -
Test: {{ form.test }}{{form.test.errors}} +
Test: {{ form.test }}{{form.test.errors}}
Snippet: {{ form.snippet }}{{ form.snippet.errors }}
Tags: {{ form.tags }} -
Options: {{ form.options }} {{form.options.errors}} {{form.options.helptext}} +
Tags: {{ form.tags }} +
Options:{{ form.options }} {{form.options.errors}} {{form.options.helptext}}
diff --git a/testapp/templates/exam/edit_quiz.html b/testapp/templates/exam/edit_quiz.html index 0ea4aae..cf80df1 100644 --- a/testapp/templates/exam/edit_quiz.html +++ b/testapp/templates/exam/edit_quiz.html @@ -5,13 +5,10 @@ {% block css %} - {% endblock %} {% block script %} - - {% endblock %} {% block onload %} onload = 'javascript:form_load();' {% endblock %} @@ -25,7 +22,6 @@ Start Date: {{ form.start_date}} Duration: {{ form.duration }} Active: {{ form.active }} - Tags: {{ form.tags }} Description: {{ form.description }}
{% endfor %} -- cgit From 11307537a5ceae54722116cf699016e1e887edf6 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Fri, 20 Jun 2014 04:21:04 +0530 Subject: Changes made as per the suggestions. --- testapp/exam/forms.py | 9 ++++----- testapp/exam/models.py | 29 +++++++++++++++-------------- testapp/exam/views.py | 15 +++------------ 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index e82ce3a..7c66944 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -12,18 +12,17 @@ from taggit_autocomplete_modified import settings from string import letters, punctuation, digits import datetime -QUESTION_LANGUAGE_CHOICES = ( +LANGUAGES = ( ("select", "Select"), ("python", "Python"), ("bash", "Bash"), - ("mcq", "MCQ"), ("C", "C Language"), ("C++", "C++ Language"), ("java", "Java Language"), ("scilab", "Scilab"), ) -QUESTION_TYPE_CHOICES = ( +QUESTION_TYPES = ( ("select", "Select"), ("mcq", "Multiple Choice"), ("code", "Code"), @@ -162,9 +161,9 @@ class QuestionForm(forms.Form): options = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1}), required=False) language = forms.CharField(max_length=20, widget=forms.Select\ - (choices=QUESTION_LANGUAGE_CHOICES)) + (choices=LANGUAGES)) type = forms.CharField(max_length=8, widget=forms.Select\ - (choices=QUESTION_TYPE_CHOICES)) + (choices=QUESTION_TYPES)) active = forms.BooleanField(required=False) tags = TagField(widget=TagAutocomplete(), required=False) snippet = forms.CharField(widget=forms.Textarea\ diff --git a/testapp/exam/models.py b/testapp/exam/models.py index ca53b2c..22c7913 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -1,5 +1,5 @@ import datetime -from random import sample +from random import sample, shuffle from django.db import models from django.contrib.auth.models import User from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete\ @@ -16,7 +16,7 @@ class Profile(models.Model): position = models.CharField(max_length=64) -QUESTION_LANGUAGE_CHOICES = ( +LANGUAGES = ( ("python", "Python"), ("bash", "Bash"), ("C", "C Language"), @@ -26,7 +26,7 @@ QUESTION_LANGUAGE_CHOICES = ( ) -QUESTION_TYPE_CHOICES = ( +QUESTION_TYPES = ( ("mcq", "Multiple Choice"), ("code", "Code"), ) @@ -34,12 +34,12 @@ QUESTION_TYPE_CHOICES = ( ############################################################################### class Question(models.Model): - """A question details in the database.""" + """Question for a quiz.""" # A one-line summary of the question. summary = models.CharField(max_length=256) - # The question text, should be a valid HTML. + # The question text, should be valid HTML. description = models.TextField() # Number of points for the question. @@ -53,16 +53,16 @@ class Question(models.Model): # The language for question. language = models.CharField(max_length=24, - choices=QUESTION_LANGUAGE_CHOICES) + choices=LANGUAGES) # The type of question. - type = models.CharField(max_length=24, choices=QUESTION_TYPE_CHOICES) + type = models.CharField(max_length=24, choices=QUESTION_TYPES) # Is this question active or not. If it is inactive it will not be used # when creating a QuestionPaper. active = models.BooleanField(default=True) - # Code Snippet + # Snippet of code provided to the user. snippet = models.CharField(max_length=256) # Tags for the Question. @@ -140,7 +140,7 @@ class QuestionPaper(models.Model): # Total marks for the question paper. total_marks = models.FloatField() - def get_total_marks(self): + def update_total_marks(self): """ Returns the total marks for the Question Paper""" marks = 0.0 questions = self.fixed_questions.all() @@ -158,15 +158,16 @@ class QuestionPaper(models.Model): questions += question_set.get_random_questions() return questions - def make_answerpaper(self, user, profile, ip): + def make_answerpaper(self, user, ip): """Creates an answer paper for the user to attempt the quiz""" - ans_paper = AnswerPaper(user=user, profile=profile, user_ip=ip) + ans_paper = AnswerPaper(user=user, profile=user.profile, user_ip=ip) ans_paper.start_time = datetime.datetime.now() ans_paper.end_time = ans_paper.start_time \ + datetime.timedelta(minutes=self.quiz.duration) ans_paper.question_paper = self questions = self._get_questions_for_answerpaper() - question_ids = [str(_.id) for _ in questions] + question_ids = [str(x.id) for x in questions] + shuffle(questions) ans_paper.questions = "|".join(question_ids) ans_paper.save() return ans_paper @@ -174,7 +175,7 @@ class QuestionPaper(models.Model): ############################################################################### class QuestionSet(models.Model): - """Question set contains set of questions from which random questions + """Question set contains a set of questions from which random questions will be selected for the quiz. """ @@ -203,7 +204,7 @@ class AnswerPaper(models.Model): # data. profile = models.ForeignKey(Profile) - # All questions that are left to attempt for a particular Student + # All questions that remain to be attempted for a particular Student # (a list of ids separated by '|') questions = models.CharField(max_length=128) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 76773cb..7353d82 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -127,7 +127,8 @@ def user_register(request): context_instance=ci) else: form = UserRegisterForm() - return my_render_to_response('exam/register.html', {'form': form}) + return my_render_to_response('exam/register.html', {'form': form}, + context_instance=ci) def quizlist_user(request): @@ -623,19 +624,9 @@ def start(request, questionpaper_id=None): msg = 'You do not have a profile and cannot take the quiz!' raise Http404(msg) - new_paper = AnswerPaper(user=user, user_ip=ip, - question_paper=questionpaper, profile=profile) - new_paper.start_time = datetime.datetime.now() - new_paper.end_time = datetime.datetime.now() + new_paper = questionpaper.make_answerpaper(user, ip,) # Make user directory. user_dir = get_user_dir(user) - - questions = [str(_.id) for _ in\ - questionpaper._get_questions_for_answerpaper()] - random.shuffle(questions) - - new_paper.questions = "|".join(questions) - new_paper.save() return start(request, questionpaper_id) -- cgit From 75943b5561f2849ee4efc59c6ba4b8468caae88f Mon Sep 17 00:00:00 2001 From: prathamesh Date: Sat, 21 Jun 2014 14:57:33 +0530 Subject: TestCases Separated --- testapp/exam/tests.py | 264 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 157 insertions(+), 107 deletions(-) diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index ac63301..29c22ac 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -1,106 +1,68 @@ from django.utils import unittest from exam.models import User, Profile, Question, Quiz, QuestionPaper,\ -QuestionSet, AnswerPaper + QuestionSet, AnswerPaper, Answer +import datetime -class ModelsTestCase(unittest.TestCase): +def setUpModule(): + # create user profile + user = User.objects.create_user(username='demo_user', + password='demo', + email='demo@test.com') + User.objects.create_user(username='demo_user2', + password='demo', + email='demo@test.com') + Profile.objects.create(user=user, roll_number=1, institute='IIT', + department='Chemical', position='Student') - @classmethod - def setUpClass(self): - """ Initial fixtures for testing environment""" - - # create user profile - self.user = User.objects.create_user(username='demo_user', - password='demo', - email='demo@test.com') - self.profile = Profile.objects.create(user=self.user, roll_number=1, - institute='IIT', - department='Chemical', - position='Student') - - # create 20 questions - for i in range(1, 21): - Question.objects.create(summary='Q%d' % (i)) - - # All active questions - self.questions = Question.objects.filter(active=True) - - # Single question details - self.question = self.questions[0] - self.question.summary = 'Demo question' - self.question.language = 'Python' - self.question.type = 'Code' - self.question.options = None - self.question.description = 'Write a function' - self.question.points = 1.0 - self.question.active = True - self.question.test = 'Test Cases' - self.question.snippet = 'def myfunc()' - self.question.tags.add('python', 'function') - - # create a quiz - self.quiz = Quiz.objects.create(start_date='2014-06-16', - duration=30, active=False, - description='demo quiz') - - # create question paper - self.quest_paper = QuestionPaper.objects.create(quiz=self.quiz, - total_marks=0.0) - - # add fixed set of questions to the question paper - self.quest_paper.fixed_questions.add(self.questions[3], - self.questions[5]) - - # create two QuestionSet for random questions - # QuestionSet 1 - self.quest_set_1 = QuestionSet.objects.create(marks=2, num_questions=2) - - # add pool of questions for random sampling - self.quest_set_1.questions.add(self.questions[6], self.questions[7], - self.questions[8], self.questions[9]) + # create 20 questions + for i in range(1, 21): + Question.objects.create(summary='Q%d' % (i), points=1) - # add question set 1 to random questions in Question Paper - self.quest_paper.random_questions.add(self.quest_set_1) - - # QuestionSet 2 - self.quest_set_2 = QuestionSet.objects.create(marks=3, num_questions=3) - - # add pool of questions - self.quest_set_2.questions.add(self.questions[11], self.questions[12], - self.questions[13], self.questions[14]) + # create a quiz + Quiz.objects.create(start_date='2014-06-16', duration=30, active=False, + description='demo quiz') - # add question set 2 - self.quest_paper.random_questions.add(self.quest_set_2) - # ip address for AnswerPaper - self.ip = '127.0.0.1' +def tearDownModule(): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() - # create answerpaper - self.answerpaper = AnswerPaper(user=self.user, profile=self.profile, - questions='1|2|3', - question_paper=self.quest_paper, - start_time='2014-06-13 12:20:19.791297', - end_time='2014-06-13 12:50:19.791297', - user_ip=self.ip) ############################################################################### +class ProfileTestCases(unittest.TestCase): + def setUp(self): + self.user = User.objects.get(pk=1) + self.profile = Profile.objects.get(pk=1) + def test_user_profile(self): """ Test user profile""" - self.assertIs(type(self.profile), type(Profile())) self.assertEqual(self.user.username, 'demo_user') self.assertEqual(self.profile.user.username, 'demo_user') - self.assertEqual(self.profile.roll_number, 1) + self.assertEqual(int(self.profile.roll_number), 1) self.assertEqual(self.profile.institute, 'IIT') self.assertEqual(self.profile.department, 'Chemical') self.assertEqual(self.profile.position, 'Student') + +############################################################################### +class QuestionTestCases(unittest.TestCase): + def setUp(self): + # Single question details + self.question = Question(summary='Demo question', language='Python', + type='Code', active=True, + description='Write a function', points=1.0, + test='Test Cases', snippet='def myfunc()') + self.question.save() + self.question.tags.add('python', 'function') + def test_question(self): """ Test question """ - self.assertIs(type(self.question), type(Question())) self.assertEqual(self.question.summary, 'Demo question') self.assertEqual(self.question.language, 'Python') self.assertEqual(self.question.type, 'Code') - self.assertTrue(self.question.options is None) + self.assertFalse(self.question.options) self.assertEqual(self.question.description, 'Write a function') self.assertEqual(self.question.points, 1.0) self.assertTrue(self.question.active) @@ -108,32 +70,85 @@ class ModelsTestCase(unittest.TestCase): self.assertEqual(self.question.snippet, 'def myfunc()') tag_list = [] for tag in self.question.tags.all(): - tag_list.append(tag.name) + tag_list.append(tag.name) self.assertEqual(tag_list, ['python', 'function']) - self.assertEqual(len(self.questions), 20) + + +############################################################################### +class QuizTestCases(unittest.TestCase): + def setUp(self): + self.quiz = Quiz.objects.get(pk=1) def test_quiz(self): """ Test Quiz""" - self.assertIs(type(self.quiz), type(Quiz())) - self.assertEqual(self.quiz.start_date, '2014-06-16') + self.assertEqual((self.quiz.start_date).strftime('%Y-%m-%d'), + '2014-06-16') self.assertEqual(self.quiz.duration, 30) self.assertTrue(self.quiz.active is False) self.assertEqual(self.quiz.description, 'demo quiz') + +############################################################################### +class QuestionPaperTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + # All active questions + self.questions = Question.objects.filter(active=True) + self.quiz = Quiz.objects.get(id=1) + + # create question paper + self.question_paper = QuestionPaper.objects.create(quiz=self.quiz, + total_marks=0.0) + # add fixed set of questions to the question paper + self.question_paper.fixed_questions.add(self.questions[3], + self.questions[5]) + # create two QuestionSet for random questions + # QuestionSet 1 + self.question_set_1 = QuestionSet.objects.create(marks=2, + num_questions=2) + + # add pool of questions for random sampling + self.question_set_1.questions.add(self.questions[6], self.questions[7], + self.questions[8], self.questions[9]) + # add question set 1 to random questions in Question Paper + self.question_paper.random_questions.add(self.question_set_1) + + # QuestionSet 2 + self.question_set_2 = QuestionSet.objects.create(marks=3, + num_questions=3) + + # add pool of questions + self.question_set_2.questions.add(self.questions[11], + self.questions[12], + self.questions[13], + self.questions[14]) + # add question set 2 + self.question_paper.random_questions.add(self.question_set_2) + + # ip address for AnswerPaper + self.ip = '127.0.0.1' + + self.user = User.objects.get(pk=1) + def test_questionpaper(self): """ Test question paper""" - self.assertIs(type(self.quest_paper), type(QuestionPaper())) - self.assertEqual(self.quest_paper.quiz.description, 'demo quiz') - self.assertEqual(list(self.quest_paper.fixed_questions.all()), + self.assertEqual(self.question_paper.quiz.description, 'demo quiz') + self.assertEqual(list(self.question_paper.fixed_questions.all()), [self.questions[3], self.questions[5]]) + def test_update_total_marks(self): + """ Test update_total_marks() method of Question Paper""" + self.assertEqual(self.question_paper.update_total_marks(), 15) + def test_get_random_questions(self): - """ Test get_random_questions() method of Question Paper """ - random_questions_set_1 = set(self.quest_set_1.get_random_questions()) - random_questions_set_2 = set(self.quest_set_2.get_random_questions()) + """ Test get_random_questions() method of Question Paper""" + random_questions_set_1 = set(self.question_set_1. + get_random_questions()) + random_questions_set_2 = set(self.question_set_2. + get_random_questions()) # To check whether random questions are from random_question_set - boolean = set(self.quest_set_1.questions.all()).\ + boolean = set(self.question_set_1.questions.all()).\ intersection(random_questions_set_1)\ == random_questions_set_1 self.assertTrue(boolean) @@ -142,12 +157,12 @@ class ModelsTestCase(unittest.TestCase): def test_get_questions_for_answerpaper(self): """ Test get_questions_for_answerpaper() method of Question Paper""" - questions = self.quest_paper._get_questions_for_answerpaper() - fixed = list(self.quest_paper.fixed_questions.all()) - quest_set = self.quest_paper.random_questions.all() + questions = self.question_paper._get_questions_for_answerpaper() + fixed = list(self.question_paper.fixed_questions.all()) + question_set = self.question_paper.random_questions.all() total_random_questions = 0 available_questions = [] - for qs in quest_set: + for qs in question_set: total_random_questions += qs.num_questions available_questions += qs.questions.all() self.assertEqual(total_random_questions, 5) @@ -156,18 +171,48 @@ class ModelsTestCase(unittest.TestCase): def test_make_answerpaper(self): """ Test make_answerpaper() method of Question Paper""" - answerpaper = self.quest_paper.make_answerpaper(self.user, - self.profile, self.ip) - self.assertIs(type(answerpaper), type(AnswerPaper())) + answerpaper = self.question_paper.make_answerpaper(self.user, self.ip) + self.assertIsInstance(answerpaper, AnswerPaper) paper_questions = set((answerpaper.questions).split('|')) self.assertEqual(len(paper_questions), 7) fixed = {'4', '6'} boolean = fixed.intersection(paper_questions) == fixed self.assertTrue(boolean) + +############################################################################### +class AnswerPaperTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + self.ip = '101.0.0.1' + self.user = User.objects.get(id=1) + self.profile = self.user.profile + self.quiz = Quiz.objects.get(pk=1) + self.question_paper = QuestionPaper(quiz=self.quiz, total_marks=3) + self.question_paper.save() + + # create answerpaper + self.answerpaper = AnswerPaper(user=self.user, profile=self.profile, + questions='1|2|3', + question_paper=self.question_paper, + start_time='2014-06-13 12:20:19.791297', + end_time='2014-06-13 12:50:19.791297', + user_ip=self.ip) + self.answerpaper.questions_answered = '1' + self.answerpaper.save() + + # answers for the Answer Paper + self.answer_right = Answer(question=Question.objects.get(id=1), + answer="Demo answer", correct=True, marks=1) + self.answer_wrong = Answer(question=Question.objects.get(id=2), + answer="My answer", correct=False, marks=0) + self.answer_right.save() + self.answer_wrong.save() + self.answerpaper.answers.add(self.answer_right) + self.answerpaper.answers.add(self.answer_wrong) + def test_answerpaper(self): """ Test Answer Paper""" - self.assertIs(type(self.answerpaper), type(AnswerPaper())) self.assertEqual(self.answerpaper.user.username, 'demo_user') self.assertEqual(self.answerpaper.profile_id, 1) self.assertEqual(self.answerpaper.user_ip, self.ip) @@ -175,8 +220,7 @@ class ModelsTestCase(unittest.TestCase): num_questions = len(questions.split('|')) self.assertEqual(questions, '1|2|3') self.assertEqual(num_questions, 3) - self.assertEqual(self.answerpaper.question_paper, self.quest_paper) - self.assertEqual(self.answerpaper.question_paper, self.quest_paper) + self.assertEqual(self.answerpaper.question_paper, self.question_paper) self.assertEqual(self.answerpaper.start_time, '2014-06-13 12:20:19.791297') self.assertEqual(self.answerpaper.end_time, @@ -185,12 +229,11 @@ class ModelsTestCase(unittest.TestCase): def test_current_question(self): """ Test current_question() method of Answer Paper""" current_question = self.answerpaper.current_question() - self.assertTrue(current_question is not None) + self.assertEqual(current_question, '2') def test_completed_question(self): """ Test completed_question() method of Answer Paper""" - question = self.answerpaper.completed_question(3) - self.assertTrue(question is not None) + question = self.answerpaper.completed_question(1) self.assertEqual(self.answerpaper.questions_left(), 2) def test_questions_left(self): @@ -199,16 +242,23 @@ class ModelsTestCase(unittest.TestCase): def test_skip(self): """ Test skip() method of Answer Paper""" - self.assertTrue(self.answerpaper.skip() is not None) + next_question_id = self.answerpaper.skip() + self.assertTrue(next_question_id is not None) + self.assertEqual(next_question_id, '3') def test_answered_str(self): """ Test answered_str() method of Answer Paper""" - self.assertEqual(self.answerpaper.get_answered_str(), 'None') + answered_question = self.answerpaper.get_answered_str() + self.assertEqual(answered_question, '1') def test_get_marks_obtained(self): """ Test get_marks_obtained() method of Answer Paper""" - self.assertEqual(self.answerpaper.get_marks_obtained(), 0) + self.assertEqual(self.answerpaper.get_marks_obtained(), 1.0) def test_get_question_answer(self): """ Test get_question_answer() method of Answer Paper""" - self.assertEqual(self.answerpaper.get_question_answers(), {}) + answered = self.answerpaper.get_question_answers() + first_answer = answered.values()[0][0] + self.assertEqual(first_answer.answer, 'Demo answer') + self.assertTrue(first_answer.correct) + self.assertEqual(len(answered), 2) -- cgit From a31b44d170a26a51587d3c1c1080d5d90f1db356 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Sat, 21 Jun 2014 16:01:34 +0530 Subject: Added assertion in test_get_random_questions, to check the order of questions. --- testapp/exam/tests.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index 29c22ac..2a5f1e7 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -142,18 +142,22 @@ class QuestionPaperTestCases(unittest.TestCase): def test_get_random_questions(self): """ Test get_random_questions() method of Question Paper""" - random_questions_set_1 = set(self.question_set_1. - get_random_questions()) - random_questions_set_2 = set(self.question_set_2. - get_random_questions()) + random_questions_set_1 = self.question_set_1.get_random_questions() + random_questions_set_2 = self.question_set_2.get_random_questions() # To check whether random questions are from random_question_set - boolean = set(self.question_set_1.questions.all()).\ - intersection(random_questions_set_1)\ - == random_questions_set_1 + questions_set_1 = set(self.question_set_1.questions.all()) + random_set_1 = set(random_questions_set_1) + random_set_2 = set(random_questions_set_2) + boolean = questions_set_1.intersection(random_set_1) == random_set_1 self.assertTrue(boolean) - self.assertEqual(len(random_questions_set_1), 2) - self.assertFalse(random_questions_set_1 == random_questions_set_2) + self.assertEqual(len(random_set_1), 2) + # To check that the questions are random. + # If incase not random then check that the order is diferent + try: + self.assertFalse(random_set_1 == random_set_2) + except AssertionError: + self.assertTrue(random_questions_set_1 != random_questions_set_2) def test_get_questions_for_answerpaper(self): """ Test get_questions_for_answerpaper() method of Question Paper""" -- cgit From c525c8f26b8e926733d5e4e3d415e19250e54e72 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Sun, 22 Jun 2014 09:42:38 +0530 Subject: Made changes to update_total_marks method --- testapp/exam/models.py | 3 ++- testapp/exam/tests.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 22c7913..42c5d5a 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -148,7 +148,8 @@ class QuestionPaper(models.Model): marks += question.points for question_set in self.random_questions.all(): marks += question_set.marks * question_set.num_questions - return marks + self.total_marks = marks + return None def _get_questions_for_answerpaper(self): """ Returns fixed and random questions for the answer paper""" diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index 2a5f1e7..b2ba36f 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -138,7 +138,9 @@ class QuestionPaperTestCases(unittest.TestCase): def test_update_total_marks(self): """ Test update_total_marks() method of Question Paper""" - self.assertEqual(self.question_paper.update_total_marks(), 15) + self.assertEqual(self.question_paper.total_marks, 0) + self.question_paper.update_total_marks() + self.assertEqual(self.question_paper.total_marks, 15) def test_get_random_questions(self): """ Test get_random_questions() method of Question Paper""" -- cgit