From 2a0909ef9d1107ec09a870947946cb336f0373c3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 25 Aug 2016 16:23:43 +0530 Subject: added upload and download questions with files --- yaksh/models.py | 46 +++++++++++++++++++++++++++++++++++++++------- yaksh/views.py | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 18 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 73d4b27..d626b26 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -10,9 +10,13 @@ from django.forms.models import model_to_dict from django.contrib.contenttypes.models import ContentType from taggit.managers import TaggableManager from django.utils import timezone +from django.core.files import File +from StringIO import StringIO import pytz import os import shutil +import zipfile + languages = ( ("python", "Python"), @@ -231,27 +235,32 @@ class Question(models.Model): def dump_into_json(self, question_ids, user): questions = Question.objects.filter(id__in=question_ids, user_id=user.id) questions_dict = [] + zip_file_name = StringIO() + zip_file = zipfile.ZipFile(zip_file_name, "a") for question in questions: test_case = question.get_test_cases() + files = question._add_and_get_files(zip_file) q_dict = {'summary': question.summary, 'description': question.description, - 'points': question.points, - 'language': question.language, - 'type': question.type, - 'active': question.active, + 'points': question.points, 'language': question.language, + 'type': question.type, 'active': question.active, 'test_case_type': question.test_case_type, 'snippet': question.snippet, - 'testcase': [case.get_field_value() for case in test_case]} + 'testcase': [case.get_field_value() for case in test_case], + 'files': files} questions_dict.append(q_dict) - - return json.dumps(questions_dict, indent=2) + question._add_json_to_zip(zip_file, questions_dict) + return zip_file_name def load_from_json(self, questions_list, user): questions = json.loads(questions_list) + ques = Question() for question in questions: question['user'] = user + files = question.pop('files') test_cases = question.pop('testcase') que, result = Question.objects.get_or_create(**question) + que._add_files_to_db(files) model_class = get_model_class(que.test_case_type) for test_case in test_cases: model_class.objects.get_or_create(question=que, **test_case) @@ -278,6 +287,29 @@ class Question(models.Model): return test_case + def _add_and_get_files(self, zip_file): + files = FileUpload.objects.filter(question=self) + for file in files: + zip_file.write(file.file.path, (os.path.basename(file.file.path))) + files_list = [os.path.basename(file.file.name) for file in files] + return files_list + + def _add_files_to_db(self, files): + if files: + for file_name in files: + file = open(file_name, 'r') + django_file = File(file) + f = FileUpload.objects.get_or_create(file=django_file, question=self) + os.remove(file_name) + + def _add_json_to_zip(self, zip_file, q_dict): + json_data = json.dumps(q_dict, indent=2) + with open("questions_dump.json", "w") as json_file: + json_file.write(json_data) + zip_file.write(json_file.name) + zip_file.close() + os.remove(json_file.name) + def __unicode__(self): return self.summary diff --git a/yaksh/views.py b/yaksh/views.py index e1ec44e..87e6005 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -22,6 +22,7 @@ import pytz from taggit.models import Tag from itertools import chain import json +import zipfile # Local imports. from yaksh.models import get_model_class, Quiz, Question, QuestionPaper, QuestionSet, Course @@ -73,6 +74,7 @@ def is_moderator(user): if user.groups.filter(name='moderator').exists(): return True + def add_to_group(users): """ add users to moderator group """ group = Group.objects.get(name="moderator") @@ -80,6 +82,22 @@ def add_to_group(users): if not is_moderator(user): user.groups.add(group) + +def extract_files(questions_file): + if zipfile.is_zipfile(questions_file): + zip_file = zipfile.ZipFile(questions_file, 'r') + zip_file.extractall() + + +def read_json(json_file, user): + question = Question() + if os.path.exists(json_file): + with open(json_file, 'r') as q_file: + questions_list = q_file.read() + question.load_from_json(questions_list, user) + os.remove(json_file) + + def index(request): """The start page. """ @@ -663,9 +681,11 @@ def courses(request): ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') - courses = Course.objects.filter(creator=user, is_trial=False) + demo_user = User.objects.get(username="demo_user") + courses = Course.objects.filter(Q(creator=user) | Q(creator=demo_user), + is_trial=False) return my_render_to_response('yaksh/courses.html', {'courses': courses}, - context_instance=ci) + context_instance=ci) @login_required @@ -869,22 +889,24 @@ def show_all_questions(request): form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): questions_file = request.FILES['file'] - if questions_file.name.split('.')[-1] == "json": - questions_list = questions_file.read() - question = Question() - question.load_from_json(questions_list, user) + file_name = questions_file.name.split('.') + if file_name[-1] == "zip": + extract_files(questions_file) + read_json("questions_dump.json", user) else: - message = "Please Upload a JSON file" + message = "Please Upload a ZIP file" context['message'] = message if request.POST.get('download') == 'download': question_ids = request.POST.getlist('question') if question_ids: question = Question() - questions = question.dump_into_json(question_ids, user) - response = HttpResponse(questions, content_type='text/json') - response['Content-Disposition'] = 'attachment; filename=\ - "{0}_questions.json"'.format(user) + zip_file = question.dump_into_json(question_ids, user) + response = HttpResponse(content_type='application/zip') + response['Content-Disposition'] = '''attachment;\ + filename={0}_questions.zip'''.format(user) + zip_file.seek(0) + response.write(zip_file.read()) return response else: context['msg'] = "Please select atleast one question to download" -- cgit From 074ca3fe68b790279c6ed8e0dda580b5ade8586e Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 25 Aug 2016 16:24:56 +0530 Subject: changed templates to view demo quiz --- yaksh/templates/yaksh/courses.html | 5 ++++- yaksh/templates/yaksh/showquestions.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'yaksh') diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index 06c848c..910a68d 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -15,9 +15,12 @@ {% else %}

Course(s) Added

{% for course in courses %} - {% if user != course.creator %} + {% if user != course.creator and course.name != "Demo_course"%}

{{course.creator.get_full_name}} added you to this course

{% endif %} + {% if course.name == "Demo_course" %} +

This is Demo Course

+ {% endif %}
diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html index 2f4d218..185cbfb 100644 --- a/yaksh/templates/yaksh/showquestions.html +++ b/yaksh/templates/yaksh/showquestions.html @@ -11,7 +11,7 @@ {% block manage %} -

Upload json file for adding questions

+

Upload ZIP file for adding questions

{% csrf_token %} {{ upload_form.as_p }} -- cgit From 40dc5e38c23d5c99475a6e9bbb811c5bb9b5d016 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 25 Aug 2016 16:29:29 +0530 Subject: changed testcases to test questions dump --- yaksh/test_models.py | 44 +++++++++++++++++++++++++++++++------------- yaksh/test_views.py | 6 ++++-- 2 files changed, 35 insertions(+), 15 deletions(-) (limited to 'yaksh') diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 8bd2dda..efd7b55 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -1,12 +1,16 @@ import unittest from yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\ QuestionSet, AnswerPaper, Answer, Course, StandardTestCase,\ - StdoutBasedTestCase + StdoutBasedTestCase, FileUpload import json from datetime import datetime, timedelta from django.utils import timezone import pytz from django.contrib.auth.models import Group +from django.core.files import File +import zipfile +import os +import shutil def setUpModule(): @@ -105,7 +109,8 @@ class QuestionTestCases(unittest.TestCase): user=self.user2 ) self.question2.save() - + file_path = os.path.join(os.getcwd(), "yaksh", "test.txt") + shutil.copy(file_path, "/tmp/") self.question1.tags.add('python', 'function') self.assertion_testcase = StandardTestCase(question=self.question1, test_case='assert myfunc(12, 13) == 15' @@ -122,6 +127,7 @@ class QuestionTestCases(unittest.TestCase): "language": "Python", "type": "Code", "test_case_type": "standardtestcase", "testcase": self.test_case_upload_data, + "files": ['/tmp/test.txt'], "summary": "Json Demo"}] self.json_questions_data = json.dumps(questions_data) @@ -143,24 +149,33 @@ class QuestionTestCases(unittest.TestCase): """ Test dump questions into json """ question = Question() question_id = [self.question2.id] - questions = json.loads(question.dump_into_json(question_id, self.user2)) + questions_zip = question.dump_into_json(question_id, self.user2) + zip_file = zipfile.ZipFile(questions_zip, "r") + zip_file.extractall("/tmp/") test_case = self.question2.get_test_cases() - for q in questions: - self.assertEqual(self.question2.summary, q['summary']) - self.assertEqual(self.question2.language, q['language']) - self.assertEqual(self.question2.type, q['type']) - self.assertEqual(self.question2.description, q['description']) - self.assertEqual(self.question2.points, q['points']) - self.assertTrue(self.question2.active) - self.assertEqual(self.question2.snippet, q['snippet']) - self.assertEqual(self.question2.test_case_type, q['test_case_type']) - self.assertEqual([case.get_field_value() for case in test_case], q['testcase']) + with open("/tmp/questions_dump.json", "r") as f: + questions = json.loads(f.read()) + for q in questions: + self.assertEqual(self.question2.summary, q['summary']) + self.assertEqual(self.question2.language, q['language']) + self.assertEqual(self.question2.type, q['type']) + self.assertEqual(self.question2.description, q['description']) + self.assertEqual(self.question2.points, q['points']) + self.assertTrue(self.question2.active) + self.assertEqual(self.question2.snippet, q['snippet']) + self.assertEqual(self.question2.test_case_type, q['test_case_type']) + self.assertEqual([case.get_field_value() for case in test_case], q['testcase']) + for file in zip_file.namelist(): + os.remove(os.path.join("/tmp/", file)) def test_load_questions_from_json(self): """ Test load questions into database from json """ + f_path = os.path.join(os.getcwd(), "yaksh", "data", + "question_25", "tmp", "test.txt") question = Question() result = question.load_from_json(self.json_questions_data, self.user1) question_data = Question.objects.get(pk=25) + file = FileUpload.objects.get(question=25) test_case = question_data.get_test_cases() self.assertEqual(question_data.summary, 'Json Demo') self.assertEqual(question_data.language, 'Python') @@ -170,7 +185,10 @@ class QuestionTestCases(unittest.TestCase): self.assertTrue(question_data.active) self.assertEqual(question_data.snippet, 'def fact()') self.assertEqual(question_data.test_case_type, 'standardtestcase') + self.assertEqual(os.path.basename(file.file.path), "test.txt") self.assertEqual([case.get_field_value() for case in test_case], self.test_case_upload_data) + rm_dir = os.path.dirname(os.path.dirname(f_path)) + shutil.rmtree(rm_dir) ############################################################################### diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 6e59e26..3c08e48 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -640,8 +640,10 @@ class TestCourses(TestCase): def setUp(self): self.client = Client() - self.mod_group = Group.objects.create(name='moderator') - + self.mod_group = Group.objects.create(name='moderator') + User.objects.get_or_create(username='demo_user', + password='demo', + email='demo@test.com') # Create Moderator with profile self.user1_plaintext_pass = 'demo1' self.user1 = User.objects.create_user( -- cgit From c231dcb006c7dc6db4dc0312f53447971776635f Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 25 Aug 2016 16:30:37 +0530 Subject: created a course fixtures for demo course --- yaksh/fixtures/demo_questions.zip | Bin 0 -> 1616 bytes yaksh/management/commands/create_demo_course.py | 74 ++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 yaksh/fixtures/demo_questions.zip create mode 100644 yaksh/management/commands/create_demo_course.py (limited to 'yaksh') diff --git a/yaksh/fixtures/demo_questions.zip b/yaksh/fixtures/demo_questions.zip new file mode 100644 index 0000000..d6c1b83 Binary files /dev/null and b/yaksh/fixtures/demo_questions.zip differ diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py new file mode 100644 index 0000000..9034283 --- /dev/null +++ b/yaksh/management/commands/create_demo_course.py @@ -0,0 +1,74 @@ +import os +from django.core.management.base import BaseCommand +from yaksh.models import Course, Question, Quiz, QuestionPaper, Profile, FileUpload +from yaksh.views import extract_files, read_json +from django.contrib.auth.models import User +from django.utils import timezone +from django.core.files import File +from datetime import datetime, timedelta +import pytz +import zipfile + + +def create_demo_course(): + """ creates a demo course, quiz """ + + success = False + print("Creating Demo User...") + # create a demo user + user, u_status = User.objects.get_or_create(username='demo_user', + password='demo', + email='demo@test.com') + Profile.objects.get_or_create(user=user, roll_number=0, + institute='demo_institute', + department='demo_department', + position='Faculty') + + print("Creating Demo Course...") + # create a demo course + course, c_status = Course.objects.get_or_create(name="Demo_course", + enrollment="open", + creator=user) + + print("Creating Demo Quiz...") + # create a demo quiz + quiz, q_status = Quiz.objects.get_or_create(start_date_time=timezone.now(), + end_date_time=timezone.now() + timedelta(176590), + duration=30, active=True, + attempts_allowed=-1, + time_between_attempts=0, + description='Demo_quiz', pass_criteria=0, + language='Python', prerequisite=None, + course=course) + + print("Creating Demo Questions...") + #create demo question + f_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.json') + zip_file_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.zip') + extract_files(zip_file_path) + read_json("questions_dump.json", user) + + questions = Question.objects.filter(active=True, summary="Demo_Question") + + print("Creating Demo Question Paper...") + # create a demo questionpaper + question_paper, q_ppr_status = QuestionPaper.objects.get_or_create(quiz=quiz, + total_marks=5.0, + shuffle_questions=True + ) + # add fixed set of questions to the question paper + for question in questions: + question_paper.fixed_questions.add(question) + + success = True + return success + + +class Command(BaseCommand): + help = "Create a Demo Course, Demo Quiz" + + def handle(self, *args, **options): + """ Handle command to create demo course """ + status = create_demo_course() + if status: + self.stdout.write("Successfully Created") -- cgit From 74745309a065399f6bd33544de8705f0004edf30 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 26 Aug 2016 11:31:33 +0530 Subject: changed models and views questions dump and load --- yaksh/models.py | 35 ++++++++++++++++++----------------- yaksh/views.py | 4 ++-- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index d626b26..5bb44fa 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -232,14 +232,14 @@ class Question(models.Model): return json.dumps(question_data) - def dump_into_json(self, question_ids, user): + def dump_questions(self, question_ids, user): questions = Question.objects.filter(id__in=question_ids, user_id=user.id) questions_dict = [] zip_file_name = StringIO() zip_file = zipfile.ZipFile(zip_file_name, "a") for question in questions: test_case = question.get_test_cases() - files = question._add_and_get_files(zip_file) + file_names = question._add_and_get_files(zip_file) q_dict = {'summary': question.summary, 'description': question.description, 'points': question.points, 'language': question.language, @@ -247,20 +247,20 @@ class Question(models.Model): 'test_case_type': question.test_case_type, 'snippet': question.snippet, 'testcase': [case.get_field_value() for case in test_case], - 'files': files} + 'files': file_names} questions_dict.append(q_dict) question._add_json_to_zip(zip_file, questions_dict) return zip_file_name - def load_from_json(self, questions_list, user): + def load_questions(self, questions_list, user): questions = json.loads(questions_list) - ques = Question() for question in questions: question['user'] = user - files = question.pop('files') + file_names = question.pop('files') test_cases = question.pop('testcase') que, result = Question.objects.get_or_create(**question) - que._add_files_to_db(files) + if file_names: + que._add_files_to_db(file_names) model_class = get_model_class(que.test_case_type) for test_case in test_cases: model_class.objects.get_or_create(question=que, **test_case) @@ -289,18 +289,19 @@ class Question(models.Model): def _add_and_get_files(self, zip_file): files = FileUpload.objects.filter(question=self) - for file in files: - zip_file.write(file.file.path, (os.path.basename(file.file.path))) - files_list = [os.path.basename(file.file.name) for file in files] + files_list = [] + for f in files: + zip_file.write(f.file.path, (os.path.basename(f.file.path))) + files_list = os.path.basename(f.file.path) return files_list - def _add_files_to_db(self, files): - if files: - for file_name in files: - file = open(file_name, 'r') - django_file = File(file) - f = FileUpload.objects.get_or_create(file=django_file, question=self) - os.remove(file_name) + def _add_files_to_db(self, file_names): + for file_name in file_names: + que_file = open(file_name, 'r') + #Converting to Python file object with some Django-specific additions + django_file = File(que_file) + f = FileUpload.objects.get_or_create(file=django_file, question=self) + os.remove(file_name) def _add_json_to_zip(self, zip_file, q_dict): json_data = json.dumps(q_dict, indent=2) diff --git a/yaksh/views.py b/yaksh/views.py index 87e6005..616c3cc 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -94,7 +94,7 @@ def read_json(json_file, user): if os.path.exists(json_file): with open(json_file, 'r') as q_file: questions_list = q_file.read() - question.load_from_json(questions_list, user) + question.load_questions(questions_list, user) os.remove(json_file) @@ -901,7 +901,7 @@ def show_all_questions(request): question_ids = request.POST.getlist('question') if question_ids: question = Question() - zip_file = question.dump_into_json(question_ids, user) + zip_file = question.dump_questions(question_ids, user) response = HttpResponse(content_type='application/zip') response['Content-Disposition'] = '''attachment;\ filename={0}_questions.zip'''.format(user) -- cgit From 57a1930125a94b26af5141296a769a8679e272c6 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 26 Aug 2016 11:32:39 +0530 Subject: added else condition to failure status --- yaksh/management/commands/create_demo_course.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py index 9034283..21c56b7 100644 --- a/yaksh/management/commands/create_demo_course.py +++ b/yaksh/management/commands/create_demo_course.py @@ -72,3 +72,5 @@ class Command(BaseCommand): status = create_demo_course() if status: self.stdout.write("Successfully Created") + else: + self.stdout.write("Unable to create Demo Course") -- cgit From 0f42918020b5eb436e73e564ca8b519e84aecfa2 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 26 Aug 2016 11:33:10 +0530 Subject: changed function calls in tests --- yaksh/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yaksh') diff --git a/yaksh/test_models.py b/yaksh/test_models.py index efd7b55..1716c73 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -149,7 +149,7 @@ class QuestionTestCases(unittest.TestCase): """ Test dump questions into json """ question = Question() question_id = [self.question2.id] - questions_zip = question.dump_into_json(question_id, self.user2) + questions_zip = question.dump_questions(question_id, self.user2) zip_file = zipfile.ZipFile(questions_zip, "r") zip_file.extractall("/tmp/") test_case = self.question2.get_test_cases() @@ -173,7 +173,7 @@ class QuestionTestCases(unittest.TestCase): f_path = os.path.join(os.getcwd(), "yaksh", "data", "question_25", "tmp", "test.txt") question = Question() - result = question.load_from_json(self.json_questions_data, self.user1) + result = question.load_questions(self.json_questions_data, self.user1) question_data = Question.objects.get(pk=25) file = FileUpload.objects.get(question=25) test_case = question_data.get_test_cases() -- cgit From e8769f5d8c43ee7c2655133b676ae53d2987c79c Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 26 Aug 2016 11:34:11 +0530 Subject: added bash script for bash demo question --- yaksh/bash_files/sample2.args | 1 + yaksh/bash_files/sample2.sh | 2 ++ 2 files changed, 3 insertions(+) create mode 100755 yaksh/bash_files/sample2.args create mode 100755 yaksh/bash_files/sample2.sh (limited to 'yaksh') diff --git a/yaksh/bash_files/sample2.args b/yaksh/bash_files/sample2.args new file mode 100755 index 0000000..cf4499d --- /dev/null +++ b/yaksh/bash_files/sample2.args @@ -0,0 +1 @@ +file1.csv file2.csv file3.csv diff --git a/yaksh/bash_files/sample2.sh b/yaksh/bash_files/sample2.sh new file mode 100755 index 0000000..5dc55b8 --- /dev/null +++ b/yaksh/bash_files/sample2.sh @@ -0,0 +1,2 @@ +#!/bin/bash +cat $1 | cut -d: -f2 | paste -d: $3 - $2 -- cgit From 32867d340cfb125a2fa20019997ae5e17f466574 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 30 Aug 2016 22:40:28 +0530 Subject: added extract status of file in demo_question.zip --- yaksh/fixtures/demo_questions.zip | Bin 1616 -> 1505 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'yaksh') diff --git a/yaksh/fixtures/demo_questions.zip b/yaksh/fixtures/demo_questions.zip index d6c1b83..9c584f6 100644 Binary files a/yaksh/fixtures/demo_questions.zip and b/yaksh/fixtures/demo_questions.zip differ -- cgit From d398cf7f30fe1f5e09fd0424824eff614374652d Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 30 Aug 2016 22:42:02 +0530 Subject: changes in create demo course --- yaksh/management/commands/create_demo_course.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py index 21c56b7..e71e0ae 100644 --- a/yaksh/management/commands/create_demo_course.py +++ b/yaksh/management/commands/create_demo_course.py @@ -1,7 +1,7 @@ import os from django.core.management.base import BaseCommand from yaksh.models import Course, Question, Quiz, QuestionPaper, Profile, FileUpload -from yaksh.views import extract_files, read_json +from yaksh.file_utils import extract_files from django.contrib.auth.models import User from django.utils import timezone from django.core.files import File @@ -46,7 +46,8 @@ def create_demo_course(): f_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.json') zip_file_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.zip') extract_files(zip_file_path) - read_json("questions_dump.json", user) + ques = Question() + ques.read_json("questions_dump.json", user) questions = Question.objects.filter(active=True, summary="Demo_Question") -- cgit From 4eb9778454dc5ecec99ccf951f012a69582b0ca3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 30 Aug 2016 22:44:16 +0530 Subject: added read_json func in Question model --- yaksh/models.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index e296524..4fb77fd 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -293,15 +293,17 @@ class Question(models.Model): files_list = [] for f in files: zip_file.write(f.file.path, (os.path.basename(f.file.path))) - files_list.append(os.path.basename(f.file.path)) + files_list.append(((os.path.basename(f.file.path)), f.extract)) return files_list def _add_files_to_db(self, file_names): - for file_name in file_names: + for file_name, extract in file_names: que_file = open(file_name, 'r') #Converting to Python file object with some Django-specific additions django_file = File(que_file) - f = FileUpload.objects.get_or_create(file=django_file, question=self) + f = FileUpload.objects.get_or_create(file=django_file, + question=self, + extract=extract) os.remove(file_name) def _add_json_to_zip(self, zip_file, q_dict): @@ -314,6 +316,13 @@ class Question(models.Model): zip_file.close() shutil.rmtree(tmp_file_path) + def read_json(self, json_file, user): + if os.path.exists(json_file): + with open(json_file, 'r') as q_file: + questions_list = q_file.read() + self.load_questions(questions_list, user) + os.remove(json_file) + def __unicode__(self): return self.summary -- cgit From 83fe192987c239287bf816a31f4da31910eb7087 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 30 Aug 2016 22:44:46 +0530 Subject: changed load and dump test cases --- yaksh/test_models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 5c34e8e..7b5dd5b 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -69,7 +69,7 @@ def tearDownModule(): shutil.rmtree(dir_path1) shutil.rmtree(dir_path2) shutil.rmtree(dir_path3) - #shutil.rmtree(dir_path4) + shutil.rmtree(dir_path4) ############################################################################### @@ -148,7 +148,7 @@ class QuestionTestCases(unittest.TestCase): "language": "Python", "type": "Code", "test_case_type": "standardtestcase", "testcase": self.test_case_upload_data, - "files": [file1], + "files": [[file1, 0]], "summary": "Json Demo"}] self.json_questions_data = json.dumps(questions_data) @@ -191,7 +191,7 @@ class QuestionTestCases(unittest.TestCase): self.assertTrue(self.question2.active) self.assertEqual(self.question2.snippet, q['snippet']) self.assertEqual(self.question2.test_case_type, q['test_case_type']) - self.assertEqual(os.path.basename(que_file.file.path), q['files'][0]) + self.assertEqual(os.path.basename(que_file.file.path), q['files'][0][0]) self.assertEqual([case.get_field_value() for case in test_case], q['testcase']) for file in zip_file.namelist(): os.remove(os.path.join(tmp_path, file)) -- cgit From b0d29a622f6d3fac39ac7881b3197d4db8fbd518 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 14 Sep 2016 16:24:01 +0530 Subject: added check conditions in demo fixtures --- yaksh/management/commands/create_demo_course.py | 69 +++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py index e71e0ae..9cb6058 100644 --- a/yaksh/management/commands/create_demo_course.py +++ b/yaksh/management/commands/create_demo_course.py @@ -2,9 +2,9 @@ import os from django.core.management.base import BaseCommand from yaksh.models import Course, Question, Quiz, QuestionPaper, Profile, FileUpload from yaksh.file_utils import extract_files +from yaksh.views import add_to_group from django.contrib.auth.models import User from django.utils import timezone -from django.core.files import File from datetime import datetime, timedelta import pytz import zipfile @@ -17,12 +17,15 @@ def create_demo_course(): print("Creating Demo User...") # create a demo user user, u_status = User.objects.get_or_create(username='demo_user', - password='demo', email='demo@test.com') + user.set_password("demo") + user.save() Profile.objects.get_or_create(user=user, roll_number=0, institute='demo_institute', department='demo_department', position='Faculty') + demo_user = User.objects.filter(username='demo_user') + add_to_group(demo_user) print("Creating Demo Course...") # create a demo course @@ -31,35 +34,47 @@ def create_demo_course(): creator=user) print("Creating Demo Quiz...") + demo_quiz = Quiz.objects.filter(course=course) + if not demo_quiz: # create a demo quiz - quiz, q_status = Quiz.objects.get_or_create(start_date_time=timezone.now(), - end_date_time=timezone.now() + timedelta(176590), - duration=30, active=True, - attempts_allowed=-1, - time_between_attempts=0, - description='Demo_quiz', pass_criteria=0, - language='Python', prerequisite=None, - course=course) + demo_quiz = Quiz.objects.get_or_create(start_date_time=timezone.now(), + end_date_time=timezone.now() + timedelta(176590), + duration=30, active=True, + attempts_allowed=-1, + time_between_attempts=0, + description='Demo_quiz', pass_criteria=0, + language='Python', prerequisite=None, + course=course) + else: + print("Demo Quiz Already Created") print("Creating Demo Questions...") - #create demo question - f_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.json') - zip_file_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.zip') - extract_files(zip_file_path) - ques = Question() - ques.read_json("questions_dump.json", user) + questions = Question.objects.filter(active=True, summary="Demo Question") + files = FileUpload.objects.filter(question__in=questions) + if not files: + #create demo question + f_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.json') + zip_file_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.zip') + extract_files(zip_file_path) + ques = Question() + ques.read_json("questions_dump.json", user) - questions = Question.objects.filter(active=True, summary="Demo_Question") - - print("Creating Demo Question Paper...") - # create a demo questionpaper - question_paper, q_ppr_status = QuestionPaper.objects.get_or_create(quiz=quiz, - total_marks=5.0, - shuffle_questions=True - ) - # add fixed set of questions to the question paper - for question in questions: - question_paper.fixed_questions.add(question) + if questions: + print("Creating Demo Question Paper...") + # create a demo questionpaper + que_ppr = QuestionPaper.objects.filter(quiz=demo_quiz[0]) + if not que_ppr: + question_paper, q_ppr_status = QuestionPaper.objects.get_or_create(quiz=demo_quiz[0], + total_marks=5.0, + shuffle_questions=True + ) + # add fixed set of questions to the question paper + for question in questions: + question_paper.fixed_questions.add(question) + else: + print("Question Paper Already Created") + else: + print("Questions Not Found Please Check Question Summary") success = True return success -- cgit From b5f4917eac3d6d308479f94346262d5ce9cf78f3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 16 Sep 2016 19:23:16 +0530 Subject: changed json question summary --- yaksh/fixtures/demo_questions.zip | Bin 1505 -> 1510 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'yaksh') diff --git a/yaksh/fixtures/demo_questions.zip b/yaksh/fixtures/demo_questions.zip index 9c584f6..562bf8a 100644 Binary files a/yaksh/fixtures/demo_questions.zip and b/yaksh/fixtures/demo_questions.zip differ -- cgit From 671eaf98c8bfe38db19867e29e5047973099b1cf Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 16 Sep 2016 19:24:52 +0530 Subject: changed fixtures and views --- yaksh/management/commands/create_demo_course.py | 10 +++++----- yaksh/views.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py index 9cb6058..ef3cb6b 100644 --- a/yaksh/management/commands/create_demo_course.py +++ b/yaksh/management/commands/create_demo_course.py @@ -16,7 +16,7 @@ def create_demo_course(): success = False print("Creating Demo User...") # create a demo user - user, u_status = User.objects.get_or_create(username='demo_user', + user, u_status = User.objects.get_or_create(username='yaksh_demo_user', email='demo@test.com') user.set_password("demo") user.save() @@ -24,12 +24,12 @@ def create_demo_course(): institute='demo_institute', department='demo_department', position='Faculty') - demo_user = User.objects.filter(username='demo_user') + demo_user = User.objects.filter(username='yaksh_demo_user') add_to_group(demo_user) print("Creating Demo Course...") # create a demo course - course, c_status = Course.objects.get_or_create(name="Demo_course", + course, c_status = Course.objects.get_or_create(name="Yaksh_Demo_course", enrollment="open", creator=user) @@ -42,14 +42,14 @@ def create_demo_course(): duration=30, active=True, attempts_allowed=-1, time_between_attempts=0, - description='Demo_quiz', pass_criteria=0, + description='Yaksh_Demo_quiz', pass_criteria=0, language='Python', prerequisite=None, course=course) else: print("Demo Quiz Already Created") print("Creating Demo Questions...") - questions = Question.objects.filter(active=True, summary="Demo Question") + questions = Question.objects.filter(active=True, summary="Yaksh Demo Question") files = FileUpload.objects.filter(question__in=questions) if not files: #create demo question diff --git a/yaksh/views.py b/yaksh/views.py index a9e17ab..95e4b7d 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -669,7 +669,7 @@ def courses(request): if not is_moderator(user): raise Http404('You are not allowed to view this page') try: - demo_user = User.objects.get(username="demo_user") + demo_user = User.objects.get(username="yaksh_demo_user") except User.DoesNotExist: demo_user = None courses = Course.objects.filter(Q(creator=user) | Q(creator=demo_user), -- cgit From 2efd65cb2dd276e1560c8993e13d9db95e6c8ba0 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 16 Sep 2016 19:25:33 +0530 Subject: changed courses template --- yaksh/templates/yaksh/courses.html | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'yaksh') diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index 4852d25..df46ba6 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -15,11 +15,24 @@ {% else %}

Course(s) Created

{% for course in courses %} - {% if user != course.creator and course.name != "Demo_course"%} + {% if user != course.creator and course.name != "Yaksh_Demo_course"%}

{{course.creator.get_full_name}} added you to this course

{% endif %} - {% if course.name == "Demo_course" %} -

This is Demo Course

+ {% if course.name == "Yaksh_Demo_course" %} +
This is a Demo Course + Help +
+ {% endif %}
@@ -83,7 +96,7 @@

{% endfor %} {% endif %} - +
{% if allotted_courses %}

Course(s) Allotted

@@ -150,6 +163,7 @@ {% else %}

No new Courses allotted

{% endif %} +
{% if courses or allotted_courses %} -- cgit From c3dd2ec955c5a2b46ea469d1aff0d3b8c1859e2e Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 16 Sep 2016 20:29:06 +0530 Subject: changed views to get demo course --- yaksh/views.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'yaksh') diff --git a/yaksh/views.py b/yaksh/views.py index 6644705..6d5ac30 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -256,8 +256,9 @@ def add_quiz(request, course_id, quiz_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) ci = RequestContext(request) - if not is_moderator(user) or (user != course.creator and user not in course.teachers.all()): - raise Http404('You are not allowed to view this page!') + if course.name != "Yaksh_Demo_course": + if not is_moderator(user) or (user != course.creator and user not in course.teachers.all()): + raise Http404('You are not allowed to view this page!') context = {} if request.method == "POST": if quiz_id is None: @@ -683,12 +684,16 @@ def courses(request): raise Http404('You are not allowed to view this page') try: demo_user = User.objects.get(username="yaksh_demo_user") - except User.DoesNotExist: + demo_course = Course.objects.get(creator=demo_user) + except User.DoesNotExist, Course.DoesNotExist: demo_user = None - courses = Course.objects.filter(Q(creator=user) | Q(creator=demo_user), - is_trial=False) + demo_course = None + + courses = Course.objects.filter(creator=user, is_trial=False) allotted_courses = Course.objects.filter(teachers=user, is_trial=False) - context = {'courses': courses, "allotted_courses": allotted_courses} + + context = {'courses': courses, "allotted_courses": allotted_courses, + 'demo_course': demo_course} return my_render_to_response('yaksh/courses.html', context, context_instance=ci) -- cgit From afdf3c394afd14459abdcbda81747e527ece92e2 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 19 Sep 2016 14:45:43 +0530 Subject: changed fixture to add demo user to moderator group --- yaksh/management/commands/create_demo_course.py | 39 +++++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py index ef3cb6b..6e2712f 100644 --- a/yaksh/management/commands/create_demo_course.py +++ b/yaksh/management/commands/create_demo_course.py @@ -1,35 +1,42 @@ import os +import sys from django.core.management.base import BaseCommand from yaksh.models import Course, Question, Quiz, QuestionPaper, Profile, FileUpload from yaksh.file_utils import extract_files from yaksh.views import add_to_group from django.contrib.auth.models import User from django.utils import timezone +from django.contrib.auth.models import Group from datetime import datetime, timedelta -import pytz -import zipfile def create_demo_course(): """ creates a demo course, quiz """ success = False - print("Creating Demo User...") - # create a demo user - user, u_status = User.objects.get_or_create(username='yaksh_demo_user', - email='demo@test.com') - user.set_password("demo") - user.save() - Profile.objects.get_or_create(user=user, roll_number=0, - institute='demo_institute', - department='demo_department', - position='Faculty') - demo_user = User.objects.filter(username='yaksh_demo_user') - add_to_group(demo_user) + group = Group.objects.filter(name="moderator") + if group: + print("Creating Demo User...") + # create a demo user + user, u_status = User.objects.get_or_create(username='yaksh_demo_user', + email='demo@test.com') + user.set_password("demo") + user.save() + Profile.objects.get_or_create(user=user, roll_number=0, + institute='demo_institute', + department='demo_department', + position='Faculty') + # add demo user to moderator group + demo_user = User.objects.filter(username='yaksh_demo_user') + add_to_group(demo_user) + else: + print ("Please Create 'moderator' Group") + print ("Unable to create Demo Course") + sys.exit() print("Creating Demo Course...") # create a demo course - course, c_status = Course.objects.get_or_create(name="Yaksh_Demo_course", + course, c_status = Course.objects.get_or_create(name="Yaksh Demo course", enrollment="open", creator=user) @@ -42,7 +49,7 @@ def create_demo_course(): duration=30, active=True, attempts_allowed=-1, time_between_attempts=0, - description='Yaksh_Demo_quiz', pass_criteria=0, + description='Yaksh Demo quiz', pass_criteria=0, language='Python', prerequisite=None, course=course) else: -- cgit From 89376074f8dcee778dfc43587d623d4e8d1b5520 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 19 Sep 2016 14:46:19 +0530 Subject: changed template tag --- yaksh/templates/yaksh/courses.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'yaksh') diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index fe15342..bfc3cd8 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -144,6 +144,7 @@ {% endif %}
+
@@ -156,7 +157,7 @@
{% if demo_course %} {% with demo_course as course %} -
This is a Demo Course +
Demo Course Help
{% endwith %} -{% endif %}
+{% endif %}
{% endblock %} -- cgit From 4bc766cb85fd999a8e2ac6d7e87e62730edb1244 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 19 Sep 2016 14:47:09 +0530 Subject: removed string comparison for demo course --- yaksh/test_views.py | 9 ++++++--- yaksh/views.py | 12 +++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'yaksh') diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 4f9b18d..e88956c 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -650,9 +650,12 @@ class TestCourses(TestCase): self.client = Client() self.mod_group = Group.objects.create(name='moderator') - User.objects.get_or_create(username='demo_user', - password='demo', - email='demo@test.com') + user = User.objects.get_or_create(username='yaksh_demo_user', + password='demo', + email='demo@test.com') + course = Course.objects.get_or_create(name="Yaksh Demo course", + enrollment="open", + creator=user[0]) # Create Moderator with profile self.user1_plaintext_pass = 'demo1' self.user1 = User.objects.create_user( diff --git a/yaksh/views.py b/yaksh/views.py index 6d5ac30..3e42b64 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -256,9 +256,15 @@ def add_quiz(request, course_id, quiz_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) ci = RequestContext(request) - if course.name != "Yaksh_Demo_course": - if not is_moderator(user) or (user != course.creator and user not in course.teachers.all()): - raise Http404('You are not allowed to view this page!') + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') + try: + demo_user = User.objects.get(username="yaksh_demo_user") + except User.DoesNotExist: + demo_user = None + if course.creator != demo_user: + if (user != course.creator and user not in course.teachers.all()): + raise Http404('You are not allowed to view this course !') context = {} if request.method == "POST": if quiz_id is None: -- cgit From 485f3a74a59402fa2adca7bbea025b856f12d854 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 14:52:05 +0530 Subject: deleted course fixture file --- yaksh/management/commands/create_demo_course.py | 99 ------------------------- 1 file changed, 99 deletions(-) delete mode 100644 yaksh/management/commands/create_demo_course.py (limited to 'yaksh') diff --git a/yaksh/management/commands/create_demo_course.py b/yaksh/management/commands/create_demo_course.py deleted file mode 100644 index 6e2712f..0000000 --- a/yaksh/management/commands/create_demo_course.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -import sys -from django.core.management.base import BaseCommand -from yaksh.models import Course, Question, Quiz, QuestionPaper, Profile, FileUpload -from yaksh.file_utils import extract_files -from yaksh.views import add_to_group -from django.contrib.auth.models import User -from django.utils import timezone -from django.contrib.auth.models import Group -from datetime import datetime, timedelta - - -def create_demo_course(): - """ creates a demo course, quiz """ - - success = False - group = Group.objects.filter(name="moderator") - if group: - print("Creating Demo User...") - # create a demo user - user, u_status = User.objects.get_or_create(username='yaksh_demo_user', - email='demo@test.com') - user.set_password("demo") - user.save() - Profile.objects.get_or_create(user=user, roll_number=0, - institute='demo_institute', - department='demo_department', - position='Faculty') - # add demo user to moderator group - demo_user = User.objects.filter(username='yaksh_demo_user') - add_to_group(demo_user) - else: - print ("Please Create 'moderator' Group") - print ("Unable to create Demo Course") - sys.exit() - - print("Creating Demo Course...") - # create a demo course - course, c_status = Course.objects.get_or_create(name="Yaksh Demo course", - enrollment="open", - creator=user) - - print("Creating Demo Quiz...") - demo_quiz = Quiz.objects.filter(course=course) - if not demo_quiz: - # create a demo quiz - demo_quiz = Quiz.objects.get_or_create(start_date_time=timezone.now(), - end_date_time=timezone.now() + timedelta(176590), - duration=30, active=True, - attempts_allowed=-1, - time_between_attempts=0, - description='Yaksh Demo quiz', pass_criteria=0, - language='Python', prerequisite=None, - course=course) - else: - print("Demo Quiz Already Created") - - print("Creating Demo Questions...") - questions = Question.objects.filter(active=True, summary="Yaksh Demo Question") - files = FileUpload.objects.filter(question__in=questions) - if not files: - #create demo question - f_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.json') - zip_file_path = os.path.join(os.getcwd(), 'yaksh', 'fixtures', 'demo_questions.zip') - extract_files(zip_file_path) - ques = Question() - ques.read_json("questions_dump.json", user) - - if questions: - print("Creating Demo Question Paper...") - # create a demo questionpaper - que_ppr = QuestionPaper.objects.filter(quiz=demo_quiz[0]) - if not que_ppr: - question_paper, q_ppr_status = QuestionPaper.objects.get_or_create(quiz=demo_quiz[0], - total_marks=5.0, - shuffle_questions=True - ) - # add fixed set of questions to the question paper - for question in questions: - question_paper.fixed_questions.add(question) - else: - print("Question Paper Already Created") - else: - print("Questions Not Found Please Check Question Summary") - - success = True - return success - - -class Command(BaseCommand): - help = "Create a Demo Course, Demo Quiz" - - def handle(self, *args, **options): - """ Handle command to create demo course """ - status = create_demo_course() - if status: - self.stdout.write("Successfully Created") - else: - self.stdout.write("Unable to create Demo Course") -- cgit From 6d3ece46b9a6569c711e20db2c3220e32a82751c Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 14:53:01 +0530 Subject: changed manage and courses template --- yaksh/templates/manage.html | 20 ++++++++++++++++ yaksh/templates/yaksh/courses.html | 47 -------------------------------------- 2 files changed, 20 insertions(+), 47 deletions(-) (limited to 'yaksh') diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html index b628a44..ea587df 100644 --- a/yaksh/templates/manage.html +++ b/yaksh/templates/manage.html @@ -77,6 +77,26 @@

Moderator's Dashboard!

Click on the button given below to add a new course.
+
Click on the button to Create a Demo course. + Help
+ + + {% if msg %} +

{{ msg }}

+ {% endif %} {% if trial_paper %}
You have trial papers. diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index bfc3cd8..43f323b 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -155,52 +155,5 @@

{% endif %}
-{% if demo_course %} -{% with demo_course as course %} -
Demo Course - Help -
- -
-
-
-
-

- Course - {% if course.active %} - Active - {% else %} - Closed - {% endif %} -

-
{{ course.name }}
-

-
-
-

Quiz(zes)

- {% if course.get_quizzes %} - {% for quiz in course.get_quizzes %} - {{ quiz.description }}
- {% endfor %} - {% else %} -

No quiz

- {% endif %} -
-
-
-
-{% endwith %} -
-{% endif %}
{% endblock %} -- cgit From f420bf2cf6b755dee76338134994f9746bbc0d2b Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 14:55:41 +0530 Subject: removed user creation for demo course --- yaksh/test_views.py | 6 ------ 1 file changed, 6 deletions(-) (limited to 'yaksh') diff --git a/yaksh/test_views.py b/yaksh/test_views.py index e88956c..8a38942 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -650,12 +650,6 @@ class TestCourses(TestCase): self.client = Client() self.mod_group = Group.objects.create(name='moderator') - user = User.objects.get_or_create(username='yaksh_demo_user', - password='demo', - email='demo@test.com') - course = Course.objects.get_or_create(name="Yaksh Demo course", - enrollment="open", - creator=user[0]) # Create Moderator with profile self.user1_plaintext_pass = 'demo1' self.user1 = User.objects.create_user( -- cgit From 2ac8383ceb3f8850043ab317a7a7ebd2bfcf3921 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 14:56:10 +0530 Subject: added url for demo course --- yaksh/urls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'yaksh') diff --git a/yaksh/urls.py b/yaksh/urls.py index daa6008..fb23c7b 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -101,5 +101,6 @@ urlpatterns += [ url(r'^manage/remove_teachers/(?P\d+)/$', views.remove_teachers, name='remove_teacher'), url(r'^manage/download_questions/$', views.show_all_questions), url(r'^manage/upload_questions/$', views.show_all_questions), - url(r'^manage/(?P[\w\-]+)/(?P\d+)/$', views.test_quiz) + url(r'^manage/(?P[\w\-]+)/(?P\d+)/$', views.test_quiz), + url(r'^manage/create_demo_course/$', views.create_demo_course), ] -- cgit From 4d8a0b41935ecc182c90acf34e7696a207a664f6 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 14:56:55 +0530 Subject: Demo course creation without initial fixtures --- yaksh/models.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yaksh/views.py | 38 ++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 18 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index e7a60df..870d8b9 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -17,6 +17,7 @@ import os import shutil import zipfile import tempfile +from file_utils import extract_files languages = ( @@ -155,6 +156,23 @@ class Course(models.Model): def remove_teachers(self, *teachers): self.teachers.remove(*teachers) + def create_demo(self, user): + course = Course.objects.filter(creator=user, name="Yaksh Demo course") + if not course: + course, c_status= Course.objects.get_or_create(name="Yaksh Demo course", + enrollment="open", + creator=user) + quiz = Quiz() + demo_quiz = quiz.create_demo_quiz(course) + demo_ques = Question() + demo_ques.create_demo_questions(user) + demo_que_ppr = QuestionPaper() + demo_que_ppr.create_demo_que_ppr(demo_quiz) + success = True + else: + success = False + return success + def __unicode__(self): return self.name @@ -323,6 +341,13 @@ class Question(models.Model): self.load_questions(questions_list, user) os.remove(json_file) + def create_demo_questions(self, user): + zip_file_path = os.path.join(os.getcwd(), 'yaksh', + 'fixtures', 'demo_questions.zip') + extract_files(zip_file_path) + self.read_json("questions_dump.json", user) + + def __unicode__(self): return self.summary @@ -487,6 +512,17 @@ class Quiz(models.Model): def has_prerequisite(self): return True if self.prerequisite else False + + def create_demo_quiz(self, course): + demo_quiz = Quiz.objects.get_or_create(start_date_time=timezone.now(), + end_date_time=timezone.now() + timedelta(176590), + duration=30, active=True, + attempts_allowed=-1, + time_between_attempts=0, + description='Yaksh Demo quiz', pass_criteria=0, + language='Python', prerequisite=None, + course=course) + return demo_quiz def __unicode__(self): desc = self.description or 'Quiz' @@ -618,6 +654,17 @@ class QuestionPaper(models.Model): if self.quiz.has_prerequisite(): prerequisite = self._get_prequisite_paper() return prerequisite._is_questionpaper_passed(user) + + def create_demo_que_ppr(self, demo_quiz): + question_paper = QuestionPaper.objects.get_or_create(quiz=demo_quiz[0], + total_marks=5.0, + shuffle_questions=True + ) + questions = Question.objects.filter(active=True, + summary="Yaksh Demo Question") + # add fixed set of questions to the question paper + for question in questions: + question_paper[0].fixed_questions.add(question) def __unicode__(self): return "Question Paper for " + self.quiz.description diff --git a/yaksh/views.py b/yaksh/views.py index 3e42b64..959d323 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -256,15 +256,8 @@ def add_quiz(request, course_id, quiz_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) ci = RequestContext(request) - if not is_moderator(user): - raise Http404('You are not allowed to view this page!') - try: - demo_user = User.objects.get(username="yaksh_demo_user") - except User.DoesNotExist: - demo_user = None - if course.creator != demo_user: - if (user != course.creator and user not in course.teachers.all()): - raise Http404('You are not allowed to view this course !') + if not is_moderator(user) or (user != course.creator and user not in course.teachers.all()): + raise Http404('You are not allowed to view this course !') context = {} if request.method == "POST": if quiz_id is None: @@ -688,18 +681,10 @@ def courses(request): ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') - try: - demo_user = User.objects.get(username="yaksh_demo_user") - demo_course = Course.objects.get(creator=demo_user) - except User.DoesNotExist, Course.DoesNotExist: - demo_user = None - demo_course = None - courses = Course.objects.filter(creator=user, is_trial=False) allotted_courses = Course.objects.filter(teachers=user, is_trial=False) - context = {'courses': courses, "allotted_courses": allotted_courses, - 'demo_course': demo_course} + context = {'courses': courses, "allotted_courses": allotted_courses} return my_render_to_response('yaksh/courses.html', context, context_instance=ci) @@ -1309,3 +1294,20 @@ def view_answerpaper(request, questionpaper_id): return my_render_to_response('yaksh/view_answerpaper.html', context) else: return my_redirect('/exam/quizzes/') + + +@login_required +def create_demo_course(request): + """ creates a demo course for user """ + user = request.user + ci = RequestContext(request) + if not is_moderator(user): + raise("You are not allowed to view this page") + demo_course = Course() + success = demo_course.create_demo(user) + if success: + msg = "Created Demo course successfully" + else: + msg = "Demo course already created" + context = {'msg': msg} + return my_render_to_response('manage.html', context, context_instance=ci) -- cgit From a689afd85ef3f0e4ddb8255e06c50f400bebd165 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Sep 2016 16:09:54 +0530 Subject: used create method instead of get_or_create to create course --- yaksh/models.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 870d8b9..d176c57 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -159,9 +159,9 @@ class Course(models.Model): def create_demo(self, user): course = Course.objects.filter(creator=user, name="Yaksh Demo course") if not course: - course, c_status= Course.objects.get_or_create(name="Yaksh Demo course", - enrollment="open", - creator=user) + course = Course.objects.create(name="Yaksh Demo course", + enrollment="open", + creator=user) quiz = Quiz() demo_quiz = quiz.create_demo_quiz(course) demo_ques = Question() @@ -514,7 +514,7 @@ class Quiz(models.Model): return True if self.prerequisite else False def create_demo_quiz(self, course): - demo_quiz = Quiz.objects.get_or_create(start_date_time=timezone.now(), + demo_quiz = Quiz.objects.create(start_date_time=timezone.now(), end_date_time=timezone.now() + timedelta(176590), duration=30, active=True, attempts_allowed=-1, @@ -656,15 +656,15 @@ class QuestionPaper(models.Model): return prerequisite._is_questionpaper_passed(user) def create_demo_que_ppr(self, demo_quiz): - question_paper = QuestionPaper.objects.get_or_create(quiz=demo_quiz[0], - total_marks=5.0, - shuffle_questions=True - ) + question_paper = QuestionPaper.objects.create(quiz=demo_quiz, + total_marks=5.0, + shuffle_questions=True + ) questions = Question.objects.filter(active=True, summary="Yaksh Demo Question") # add fixed set of questions to the question paper for question in questions: - question_paper[0].fixed_questions.add(question) + question_paper.fixed_questions.add(question) def __unicode__(self): return "Question Paper for " + self.quiz.description -- cgit From e1811e3560742a4070f3e92e059a7cd1c50f1f36 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 21 Sep 2016 14:38:00 +0530 Subject: changed func name from create_demo_que_ppr to create_demo_quiz_paper --- yaksh/models.py | 4 ++-- yaksh/templates/manage.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index d176c57..71cd258 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -167,7 +167,7 @@ class Course(models.Model): demo_ques = Question() demo_ques.create_demo_questions(user) demo_que_ppr = QuestionPaper() - demo_que_ppr.create_demo_que_ppr(demo_quiz) + demo_que_ppr.create_demo_quiz_ppr(demo_quiz) success = True else: success = False @@ -655,7 +655,7 @@ class QuestionPaper(models.Model): prerequisite = self._get_prequisite_paper() return prerequisite._is_questionpaper_passed(user) - def create_demo_que_ppr(self, demo_quiz): + def create_demo_quiz_ppr(self, demo_quiz): question_paper = QuestionPaper.objects.create(quiz=demo_quiz, total_marks=5.0, shuffle_questions=True diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html index ea587df..a736b0a 100644 --- a/yaksh/templates/manage.html +++ b/yaksh/templates/manage.html @@ -88,7 +88,7 @@
  • In Courses you can view Demo Quiz.
  • Click on the Demo Quiz and Click on User Mode or God Mode to take the quiz.
  • -
  • You can also edit Demo quiz. +
  • You can also edit the Demo quiz.
  • -- cgit From 95b7927ff4d192c58c1160531b6f8c8c9259f1e4 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Fri, 19 Aug 2016 20:21:36 +0530 Subject: Add selenium based test --- yaksh/selenium_test/selenium_test.py | 141 ++++++++++++++++++++++++++++++++ yaksh/selenium_test/test_load.py | 101 +++++++++++++++++++++++ yaksh/selenium_test/test_questions.json | 50 +++++++++++ 3 files changed, 292 insertions(+) create mode 100644 yaksh/selenium_test/selenium_test.py create mode 100644 yaksh/selenium_test/test_load.py create mode 100644 yaksh/selenium_test/test_questions.json (limited to 'yaksh') diff --git a/yaksh/selenium_test/selenium_test.py b/yaksh/selenium_test/selenium_test.py new file mode 100644 index 0000000..6a32b61 --- /dev/null +++ b/yaksh/selenium_test/selenium_test.py @@ -0,0 +1,141 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys + +import multiprocessing +import argparse + +class SeleniumTest(): + def __init__(self, url, quiz_name): + self.driver = webdriver.Firefox() + self.quiz_name = quiz_name + self.url = url + + def run_load_test(self, url, username, password): + try: + self.driver.delete_all_cookies() + self.driver.get(self.url) + self.login(username, password) + self.open_quiz() + self.close_quiz() + self.logout() + self.driver.close() + except Exception as e: + with open("/tmp/yaksh_load_test_log.txt", "ab") as f: + f.write('Username: {0}\nError: {1}\n'.format(username, e)) + self.driver.close() + + def login(self, username, password): + # get the username, password and submit form elements + username_elem = self.driver.find_element_by_id("id_username") + password_elem = self.driver.find_element_by_id("id_password") + submit_login_elem = self.driver.find_element_by_css_selector('button.btn') + + # Type in the username, password and submit form + username_elem.send_keys(username) + password_elem.send_keys(password) + submit_login_elem.click() + + def submit_answer(self, question_label, answer, loop_count=1): + self.driver.implicitly_wait(2) + for count in range(loop_count): + self.driver.find_element_by_link_text(question_label).click() + submit_answer_elem = self.driver.find_element_by_id("check") + self.driver.execute_script('editor.setValue({})'.format(answer)) + submit_answer_elem.click() + + def test_c_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"int add(int a, int b, int c)\\n{return;}\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"int add(int a, int b, int c)\\n{while(1){}}\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"int add(int a, int b, int c)\\n{return a + b + c;}\"' + self.submit_answer(question_label, answer, loop_count) + + def test_python_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"def is_palindrome(s):\\n return s\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"while True:\\n pass"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"def is_palindrome(s):\\n return s[::-1] == s\"' + self.submit_answer(question_label, answer, loop_count) + + def test_bash_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"#!/bin/bash\\nls\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"#!/bin/bash\\nwhile [ 1 ]; do : ; done\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"#!/bin/bash\\ncat $1| cut -d: -f2 | paste -d: $3 - $2\"' + self.submit_answer(question_label, answer, loop_count) + + def open_quiz(self): + # open quiz link + quiz_link_elem = self.driver.find_element_by_link_text(self.quiz_name).click() + self.driver.implicitly_wait(2) + + # Get page elements + start_exam_elem = self.driver.find_element_by_name("start") + start_exam_elem.click() + + quit_exam_elem = self.driver.find_element_by_name("quit") + + self.test_c_question(question_label=3) + self.test_python_question(question_label=1) + self.test_bash_question(question_label=2) + + def close_quiz(self): + self.driver.implicitly_wait(5) + quit_link_elem = self.driver.find_element_by_id("login_again") + quit_link_elem.click() + + def logout(self): + self.driver.implicitly_wait(5) + logout_link_elem = self.driver.find_element_by_id("logout") + logout_link_elem.click() + +def user_gen(url, ids): + return [(url, 'User%d'%x, 'User%d'%x) for x in ids] + +def wrap_run_load_test(args): + url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" + quiz_name = "sel quiz 1" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + return selenium_test.run_load_test(*args) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('start', type=int, help="Starting user id") + parser.add_argument("-n", "--number", type=int, default=10, help="number of users") + opts = parser.parse_args() + + url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" + quiz_name = "yaksh demo quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + pool = multiprocessing.Pool(opts.number) + pool.map(wrap_run_load_test, user_gen(url, range(opts.start, opts.start + opts.number))) + pool.close() + pool.join() + diff --git a/yaksh/selenium_test/test_load.py b/yaksh/selenium_test/test_load.py new file mode 100644 index 0000000..c552137 --- /dev/null +++ b/yaksh/selenium_test/test_load.py @@ -0,0 +1,101 @@ +import os +import signal +import subprocess +from datetime import datetime +import pytz +from threading import Thread +from selenium.webdriver.firefox.webdriver import WebDriver + +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase +from selenium_test import SeleniumTest + +from yaksh.code_server import ServerPool, SERVER_POOL_PORT, SERVER_PORTS +from yaksh import settings +from yaksh.xmlrpc_clients import CodeServerProxy + +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + +class MySeleniumTests(StaticLiveServerTestCase): + @classmethod + def setUpClass(cls): + super(MySeleniumTests, cls).setUpClass() + # setup a demo code server + settings.code_evaluators['python']['standardtestcase'] = \ + "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" + settings.code_evaluators['c']['standardtestcase'] = \ + "yaksh.cpp_code_evaluator.CppCodeEvaluator" + settings.code_evaluators['bash']['standardtestcase'] = \ + "yaksh.bash_code_evaluator.BashCodeEvaluator" + code_server_pool = ServerPool(ports=SERVER_PORTS, pool_port=SERVER_POOL_PORT) + cls.code_server_pool = code_server_pool + cls.code_server_thread = t = Thread(target=code_server_pool.run) + t.start() + + # Create set of demo users and profiles + mod_user = User.objects.create_user(username='yaksh_demo_mod', + password='yaksh_demo_mod', + email='yaksh_demo_mod@test.com' + ) + + user = User.objects.create_user(username='demo_yaksh_user', + password='demo_yaksh_user', + email='demo_yaksh_user@test.com' + ) + Profile.objects.create(user=user, + roll_number='demo_rn', + institute='IIT', + department='Chemical', + position='Student' + ) + + # create a course + course = Course.objects.create(name="Demo Load Course", + enrollment="Open Course", + creator=mod_user + ) + course.students.add(user) + + # create a Quiz + quiz = Quiz.objects.create( + start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + duration=30, active=True, + attempts_allowed=1, time_between_attempts=0, + description='yaksh demo quiz', pass_criteria=0, + language='Python', prerequisite=None, + course=course + ) + + # create a question set + question = Question() + with open(os.path.join(CUR_DIR, 'test_questions.json'), 'r') as f: + question_list = f.read() + question.load_from_json(question_list, mod_user) + + # create question paper + question_paper = QuestionPaper.objects.create(quiz=quiz, + total_marks=5, + shuffle_questions=False + ) + # add fixed set of questions to the question paper + question_paper.fixed_questions.add(*Question.objects.all()) + + @classmethod + def tearDownClass(cls): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + Course.objects.all().delete() + + cls.code_server_pool.stop() + cls.code_server_thread.join() + + super(MySeleniumTests, cls).tearDownClass() + + def test_load(self): + url = '%s%s' % (self.live_server_url, '/exam/login/') + quiz_name = "yaksh demo quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + selenium_test.run_load_test(url=url, username='demo_yaksh_user', password='demo_yaksh_user') diff --git a/yaksh/selenium_test/test_questions.json b/yaksh/selenium_test/test_questions.json new file mode 100644 index 0000000..f1cf02f --- /dev/null +++ b/yaksh/selenium_test/test_questions.json @@ -0,0 +1,50 @@ +[ + { + "snippet": "", + "testcase": [ + { + "test_case": "assert is_palindrome(\"hello\") == False" + }, + { + "test_case": "assert is_palindrome(\"nitin\") == True" + } + ], + "points": 3.0, + "test_case_type": "standardtestcase", + "description": "Write a function is_palindrome(arg) which will take one string argument. Return true if the argument is palindrome & false otherwise.\r\n

    \r\nFor Example:\r\n
    \r\nis_palindrome(\"Hello\") should return False\r\n
    \r\n

    ", + "language": "python", + "active": true, + "type": "code", + "summary": "Python, check palindrome (Code)" + }, + { + "snippet": "#!/bin/bash", + "testcase": [ + { + "test_case": "/src/yaksh/bash_files/sample.sh,/src/yaksh/bash_files/sample.args" + } + ], + "points": 1.0, + "test_case_type": "standardtestcase", + "description": "Write a bash script that takes exactly two arguments and returns the sum of the numbers", + "language": "bash", + "active": true, + "type": "code", + "summary": "Bash Question Concatenate Files(Code)" + }, + { + "snippet": "", + "testcase": [ + { + "test_case": "c_cpp_files/main2.c" + } + ], + "points": 1.0, + "test_case_type": "standardtestcase", + "description": "Write a program to add 3 nos", + "language": "c", + "active": true, + "type": "code", + "summary": "selenium test" + } +] -- cgit From 87930b211e3011ad0e2da982519ef5e6ef5ab865 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Mon, 29 Aug 2016 17:42:00 +0530 Subject: - Change path of selenium tests - Add to travis --- yaksh/selenium_test/selenium_test.py | 141 ------------------------------ yaksh/selenium_test/test_load.py | 101 ---------------------- yaksh/selenium_test/test_questions.json | 50 ----------- yaksh/tests/selenium_test.py | 148 ++++++++++++++++++++++++++++++++ yaksh/tests/test_load.py | 101 ++++++++++++++++++++++ yaksh/tests/test_questions.json | 50 +++++++++++ 6 files changed, 299 insertions(+), 292 deletions(-) delete mode 100644 yaksh/selenium_test/selenium_test.py delete mode 100644 yaksh/selenium_test/test_load.py delete mode 100644 yaksh/selenium_test/test_questions.json create mode 100644 yaksh/tests/selenium_test.py create mode 100644 yaksh/tests/test_load.py create mode 100644 yaksh/tests/test_questions.json (limited to 'yaksh') diff --git a/yaksh/selenium_test/selenium_test.py b/yaksh/selenium_test/selenium_test.py deleted file mode 100644 index 6a32b61..0000000 --- a/yaksh/selenium_test/selenium_test.py +++ /dev/null @@ -1,141 +0,0 @@ -from selenium import webdriver -from selenium.webdriver.common.keys import Keys - -import multiprocessing -import argparse - -class SeleniumTest(): - def __init__(self, url, quiz_name): - self.driver = webdriver.Firefox() - self.quiz_name = quiz_name - self.url = url - - def run_load_test(self, url, username, password): - try: - self.driver.delete_all_cookies() - self.driver.get(self.url) - self.login(username, password) - self.open_quiz() - self.close_quiz() - self.logout() - self.driver.close() - except Exception as e: - with open("/tmp/yaksh_load_test_log.txt", "ab") as f: - f.write('Username: {0}\nError: {1}\n'.format(username, e)) - self.driver.close() - - def login(self, username, password): - # get the username, password and submit form elements - username_elem = self.driver.find_element_by_id("id_username") - password_elem = self.driver.find_element_by_id("id_password") - submit_login_elem = self.driver.find_element_by_css_selector('button.btn') - - # Type in the username, password and submit form - username_elem.send_keys(username) - password_elem.send_keys(password) - submit_login_elem.click() - - def submit_answer(self, question_label, answer, loop_count=1): - self.driver.implicitly_wait(2) - for count in range(loop_count): - self.driver.find_element_by_link_text(question_label).click() - submit_answer_elem = self.driver.find_element_by_id("check") - self.driver.execute_script('editor.setValue({})'.format(answer)) - submit_answer_elem.click() - - def test_c_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"int add(int a, int b, int c)\\n{return;}\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"int add(int a, int b, int c)\\n{while(1){}}\"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"int add(int a, int b, int c)\\n{return a + b + c;}\"' - self.submit_answer(question_label, answer, loop_count) - - def test_python_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"def is_palindrome(s):\\n return s\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"while True:\\n pass"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"def is_palindrome(s):\\n return s[::-1] == s\"' - self.submit_answer(question_label, answer, loop_count) - - def test_bash_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"#!/bin/bash\\nls\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"#!/bin/bash\\nwhile [ 1 ]; do : ; done\"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"#!/bin/bash\\ncat $1| cut -d: -f2 | paste -d: $3 - $2\"' - self.submit_answer(question_label, answer, loop_count) - - def open_quiz(self): - # open quiz link - quiz_link_elem = self.driver.find_element_by_link_text(self.quiz_name).click() - self.driver.implicitly_wait(2) - - # Get page elements - start_exam_elem = self.driver.find_element_by_name("start") - start_exam_elem.click() - - quit_exam_elem = self.driver.find_element_by_name("quit") - - self.test_c_question(question_label=3) - self.test_python_question(question_label=1) - self.test_bash_question(question_label=2) - - def close_quiz(self): - self.driver.implicitly_wait(5) - quit_link_elem = self.driver.find_element_by_id("login_again") - quit_link_elem.click() - - def logout(self): - self.driver.implicitly_wait(5) - logout_link_elem = self.driver.find_element_by_id("logout") - logout_link_elem.click() - -def user_gen(url, ids): - return [(url, 'User%d'%x, 'User%d'%x) for x in ids] - -def wrap_run_load_test(args): - url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" - quiz_name = "sel quiz 1" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - return selenium_test.run_load_test(*args) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('start', type=int, help="Starting user id") - parser.add_argument("-n", "--number", type=int, default=10, help="number of users") - opts = parser.parse_args() - - url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" - quiz_name = "yaksh demo quiz" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - pool = multiprocessing.Pool(opts.number) - pool.map(wrap_run_load_test, user_gen(url, range(opts.start, opts.start + opts.number))) - pool.close() - pool.join() - diff --git a/yaksh/selenium_test/test_load.py b/yaksh/selenium_test/test_load.py deleted file mode 100644 index c552137..0000000 --- a/yaksh/selenium_test/test_load.py +++ /dev/null @@ -1,101 +0,0 @@ -import os -import signal -import subprocess -from datetime import datetime -import pytz -from threading import Thread -from selenium.webdriver.firefox.webdriver import WebDriver - -from django.contrib.staticfiles.testing import StaticLiveServerTestCase - -from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase -from selenium_test import SeleniumTest - -from yaksh.code_server import ServerPool, SERVER_POOL_PORT, SERVER_PORTS -from yaksh import settings -from yaksh.xmlrpc_clients import CodeServerProxy - -CUR_DIR = os.path.dirname(os.path.abspath(__file__)) - -class MySeleniumTests(StaticLiveServerTestCase): - @classmethod - def setUpClass(cls): - super(MySeleniumTests, cls).setUpClass() - # setup a demo code server - settings.code_evaluators['python']['standardtestcase'] = \ - "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" - settings.code_evaluators['c']['standardtestcase'] = \ - "yaksh.cpp_code_evaluator.CppCodeEvaluator" - settings.code_evaluators['bash']['standardtestcase'] = \ - "yaksh.bash_code_evaluator.BashCodeEvaluator" - code_server_pool = ServerPool(ports=SERVER_PORTS, pool_port=SERVER_POOL_PORT) - cls.code_server_pool = code_server_pool - cls.code_server_thread = t = Thread(target=code_server_pool.run) - t.start() - - # Create set of demo users and profiles - mod_user = User.objects.create_user(username='yaksh_demo_mod', - password='yaksh_demo_mod', - email='yaksh_demo_mod@test.com' - ) - - user = User.objects.create_user(username='demo_yaksh_user', - password='demo_yaksh_user', - email='demo_yaksh_user@test.com' - ) - Profile.objects.create(user=user, - roll_number='demo_rn', - institute='IIT', - department='Chemical', - position='Student' - ) - - # create a course - course = Course.objects.create(name="Demo Load Course", - enrollment="Open Course", - creator=mod_user - ) - course.students.add(user) - - # create a Quiz - quiz = Quiz.objects.create( - start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), - end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), - duration=30, active=True, - attempts_allowed=1, time_between_attempts=0, - description='yaksh demo quiz', pass_criteria=0, - language='Python', prerequisite=None, - course=course - ) - - # create a question set - question = Question() - with open(os.path.join(CUR_DIR, 'test_questions.json'), 'r') as f: - question_list = f.read() - question.load_from_json(question_list, mod_user) - - # create question paper - question_paper = QuestionPaper.objects.create(quiz=quiz, - total_marks=5, - shuffle_questions=False - ) - # add fixed set of questions to the question paper - question_paper.fixed_questions.add(*Question.objects.all()) - - @classmethod - def tearDownClass(cls): - User.objects.all().delete() - Question.objects.all().delete() - Quiz.objects.all().delete() - Course.objects.all().delete() - - cls.code_server_pool.stop() - cls.code_server_thread.join() - - super(MySeleniumTests, cls).tearDownClass() - - def test_load(self): - url = '%s%s' % (self.live_server_url, '/exam/login/') - quiz_name = "yaksh demo quiz" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - selenium_test.run_load_test(url=url, username='demo_yaksh_user', password='demo_yaksh_user') diff --git a/yaksh/selenium_test/test_questions.json b/yaksh/selenium_test/test_questions.json deleted file mode 100644 index f1cf02f..0000000 --- a/yaksh/selenium_test/test_questions.json +++ /dev/null @@ -1,50 +0,0 @@ -[ - { - "snippet": "", - "testcase": [ - { - "test_case": "assert is_palindrome(\"hello\") == False" - }, - { - "test_case": "assert is_palindrome(\"nitin\") == True" - } - ], - "points": 3.0, - "test_case_type": "standardtestcase", - "description": "Write a function is_palindrome(arg) which will take one string argument. Return true if the argument is palindrome & false otherwise.\r\n

    \r\nFor Example:\r\n
    \r\nis_palindrome(\"Hello\") should return False\r\n
    \r\n

    ", - "language": "python", - "active": true, - "type": "code", - "summary": "Python, check palindrome (Code)" - }, - { - "snippet": "#!/bin/bash", - "testcase": [ - { - "test_case": "/src/yaksh/bash_files/sample.sh,/src/yaksh/bash_files/sample.args" - } - ], - "points": 1.0, - "test_case_type": "standardtestcase", - "description": "Write a bash script that takes exactly two arguments and returns the sum of the numbers", - "language": "bash", - "active": true, - "type": "code", - "summary": "Bash Question Concatenate Files(Code)" - }, - { - "snippet": "", - "testcase": [ - { - "test_case": "c_cpp_files/main2.c" - } - ], - "points": 1.0, - "test_case_type": "standardtestcase", - "description": "Write a program to add 3 nos", - "language": "c", - "active": true, - "type": "code", - "summary": "selenium test" - } -] diff --git a/yaksh/tests/selenium_test.py b/yaksh/tests/selenium_test.py new file mode 100644 index 0000000..a0ce8f2 --- /dev/null +++ b/yaksh/tests/selenium_test.py @@ -0,0 +1,148 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +import multiprocessing +import argparse + +class SeleniumTest(): + def __init__(self, url, quiz_name): + try: + self.driver = webdriver.PhantomJS() + except WebDriverException: + self.driver = webdriver.Firefox() + self.quiz_name = quiz_name + self.url = url + + def run_load_test(self, url, username, password): + try: + self.driver.delete_all_cookies() + self.driver.get(self.url) + self.login(username, password) + self.open_quiz() + self.close_quiz() + self.logout() + self.driver.close() + except Exception as e: + with open("/tmp/yaksh_load_test_log.txt", "ab") as f: + f.write('Username: {0}\nError: {1}\n'.format(username, e)) + self.driver.close() + + def login(self, username, password): + # get the username, password and submit form elements + username_elem = self.driver.find_element_by_id("id_username") + password_elem = self.driver.find_element_by_id("id_password") + submit_login_elem = self.driver.find_element_by_css_selector('button.btn') + + # Type in the username, password and submit form + username_elem.send_keys(username) + password_elem.send_keys(password) + submit_login_elem.click() + + def submit_answer(self, question_label, answer, loop_count=1): + self.driver.implicitly_wait(2) + for count in range(loop_count): + self.driver.find_element_by_link_text(question_label).click() + submit_answer_elem = self.driver.find_element_by_id("check") + self.driver.execute_script('editor.setValue({})'.format(answer)) + submit_answer_elem.click() + + def test_c_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"int add(int a, int b, int c)\\n{return;}\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"int add(int a, int b, int c)\\n{while(1){}}\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"int add(int a, int b, int c)\\n{return a + b + c;}\"' + self.submit_answer(question_label, answer, loop_count) + + def test_python_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"def is_palindrome(s):\\n return s\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"while True:\\n pass"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"def is_palindrome(s):\\n return s[::-1] == s\"' + self.submit_answer(question_label, answer, loop_count) + + def test_bash_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"#!/bin/bash\\nls\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"#!/bin/bash\\nwhile [ 1 ]; do : ; done\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"#!/bin/bash\\n[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 ))\"' + self.submit_answer(question_label, answer, loop_count) + + def open_quiz(self): + # open quiz link + quiz_link_elem = self.driver.find_element_by_link_text(self.quiz_name).click() + + # Get page elements + start_exam_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.NAME, "start")) + ) + start_exam_elem.click() + + self.test_c_question(question_label=3) + self.test_python_question(question_label=1) + self.test_bash_question(question_label=2) + + def close_quiz(self): + quit_link_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.ID, "login_again")) + ) + quit_link_elem.click() + + def logout(self): + logout_link_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.ID, "logout")) + ) + logout_link_elem.click() + +def user_gen(url, ids): + return [(url, 'User%d'%x, 'User%d'%x) for x in ids] + +def wrap_run_load_test(args): + url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" + quiz_name = "yaksh_demo_quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + return selenium_test.run_load_test(*args) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('url', type=str, help="url of the website being tested") + parser.add_argument('start', type=int, help="Starting user id") + parser.add_argument("-n", "--number", type=int, default=10, help="number of users") + opts = parser.parse_args() + + quiz_name = "yaksh demo quiz" + selenium_test = SeleniumTest(url=opts.url, quiz_name=quiz_name) + pool = multiprocessing.Pool(opts.number) + pool.map(wrap_run_load_test, user_gen(opts.url, range(opts.start, opts.start + opts.number))) + pool.close() + pool.join() + diff --git a/yaksh/tests/test_load.py b/yaksh/tests/test_load.py new file mode 100644 index 0000000..c552137 --- /dev/null +++ b/yaksh/tests/test_load.py @@ -0,0 +1,101 @@ +import os +import signal +import subprocess +from datetime import datetime +import pytz +from threading import Thread +from selenium.webdriver.firefox.webdriver import WebDriver + +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase +from selenium_test import SeleniumTest + +from yaksh.code_server import ServerPool, SERVER_POOL_PORT, SERVER_PORTS +from yaksh import settings +from yaksh.xmlrpc_clients import CodeServerProxy + +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + +class MySeleniumTests(StaticLiveServerTestCase): + @classmethod + def setUpClass(cls): + super(MySeleniumTests, cls).setUpClass() + # setup a demo code server + settings.code_evaluators['python']['standardtestcase'] = \ + "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" + settings.code_evaluators['c']['standardtestcase'] = \ + "yaksh.cpp_code_evaluator.CppCodeEvaluator" + settings.code_evaluators['bash']['standardtestcase'] = \ + "yaksh.bash_code_evaluator.BashCodeEvaluator" + code_server_pool = ServerPool(ports=SERVER_PORTS, pool_port=SERVER_POOL_PORT) + cls.code_server_pool = code_server_pool + cls.code_server_thread = t = Thread(target=code_server_pool.run) + t.start() + + # Create set of demo users and profiles + mod_user = User.objects.create_user(username='yaksh_demo_mod', + password='yaksh_demo_mod', + email='yaksh_demo_mod@test.com' + ) + + user = User.objects.create_user(username='demo_yaksh_user', + password='demo_yaksh_user', + email='demo_yaksh_user@test.com' + ) + Profile.objects.create(user=user, + roll_number='demo_rn', + institute='IIT', + department='Chemical', + position='Student' + ) + + # create a course + course = Course.objects.create(name="Demo Load Course", + enrollment="Open Course", + creator=mod_user + ) + course.students.add(user) + + # create a Quiz + quiz = Quiz.objects.create( + start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + duration=30, active=True, + attempts_allowed=1, time_between_attempts=0, + description='yaksh demo quiz', pass_criteria=0, + language='Python', prerequisite=None, + course=course + ) + + # create a question set + question = Question() + with open(os.path.join(CUR_DIR, 'test_questions.json'), 'r') as f: + question_list = f.read() + question.load_from_json(question_list, mod_user) + + # create question paper + question_paper = QuestionPaper.objects.create(quiz=quiz, + total_marks=5, + shuffle_questions=False + ) + # add fixed set of questions to the question paper + question_paper.fixed_questions.add(*Question.objects.all()) + + @classmethod + def tearDownClass(cls): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + Course.objects.all().delete() + + cls.code_server_pool.stop() + cls.code_server_thread.join() + + super(MySeleniumTests, cls).tearDownClass() + + def test_load(self): + url = '%s%s' % (self.live_server_url, '/exam/login/') + quiz_name = "yaksh demo quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + selenium_test.run_load_test(url=url, username='demo_yaksh_user', password='demo_yaksh_user') diff --git a/yaksh/tests/test_questions.json b/yaksh/tests/test_questions.json new file mode 100644 index 0000000..d617f22 --- /dev/null +++ b/yaksh/tests/test_questions.json @@ -0,0 +1,50 @@ +[ + { + "snippet": "", + "testcase": [ + { + "test_case": "assert is_palindrome(\"hello\") == False" + }, + { + "test_case": "assert is_palindrome(\"nitin\") == True" + } + ], + "points": 3.0, + "test_case_type": "standardtestcase", + "description": "Write a function is_palindrome(arg) which will take one string argument. Return true if the argument is palindrome & false otherwise.\r\n

    \r\nFor Example:\r\n
    \r\nis_palindrome(\"Hello\") should return False\r\n
    \r\n

    ", + "language": "python", + "active": true, + "type": "code", + "summary": "Python, check palindrome (Code)" + }, + { + "snippet": "#!/bin/bash", + "testcase": [ + { + "test_case": "bash_files/sample.sh, bash_files/sample.args" + } + ], + "points": 1.0, + "test_case_type": "standardtestcase", + "description": "Write a bash script that takes exactly two arguments and returns the sum of the numbers", + "language": "bash", + "active": true, + "type": "code", + "summary": "Bash Question Concatenate Files(Code)" + }, + { + "snippet": "", + "testcase": [ + { + "test_case": "c_cpp_files/main2.c" + } + ], + "points": 1.0, + "test_case_type": "standardtestcase", + "description": "Write a program to add 3 nos", + "language": "c", + "active": true, + "type": "code", + "summary": "selenium test" + } +] -- cgit From 722e82275c28418dc7535ca7393b81eecadbeba9 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Tue, 6 Sep 2016 18:56:30 +0530 Subject: Modify selenium based test to accomodate create_demo_course command --- yaksh/tests/selenium_test.py | 14 +++++------ yaksh/tests/test_load.py | 56 +++++--------------------------------------- 2 files changed, 12 insertions(+), 58 deletions(-) (limited to 'yaksh') diff --git a/yaksh/tests/selenium_test.py b/yaksh/tests/selenium_test.py index a0ce8f2..15d730e 100644 --- a/yaksh/tests/selenium_test.py +++ b/yaksh/tests/selenium_test.py @@ -3,16 +3,14 @@ from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC +from selenium.common.exceptions import WebDriverException import multiprocessing import argparse class SeleniumTest(): def __init__(self, url, quiz_name): - try: - self.driver = webdriver.PhantomJS() - except WebDriverException: - self.driver = webdriver.Firefox() + self.driver = webdriver.Firefox() self.quiz_name = quiz_name self.url = url @@ -94,7 +92,7 @@ class SeleniumTest(): # Correct Answer loop_count = 1 - answer = '\"#!/bin/bash\\n[[ $# -eq 2 ]] && echo $(( $1 + $2 )) && exit $(( $1 + $2 ))\"' + answer = '\"#!/bin/bash\\ncat $1 | cut -d: -f2 | paste -d: $3 - $2\"' self.submit_answer(question_label, answer, loop_count) def open_quiz(self): @@ -107,8 +105,8 @@ class SeleniumTest(): ) start_exam_elem.click() - self.test_c_question(question_label=3) - self.test_python_question(question_label=1) + self.test_c_question(question_label=1) + self.test_python_question(question_label=3) self.test_bash_question(question_label=2) def close_quiz(self): @@ -139,7 +137,7 @@ if __name__ == '__main__': parser.add_argument("-n", "--number", type=int, default=10, help="number of users") opts = parser.parse_args() - quiz_name = "yaksh demo quiz" + quiz_name = "Demo quiz" selenium_test = SeleniumTest(url=opts.url, quiz_name=quiz_name) pool = multiprocessing.Pool(opts.number) pool.map(wrap_run_load_test, user_gen(opts.url, range(opts.start, opts.start + opts.number))) diff --git a/yaksh/tests/test_load.py b/yaksh/tests/test_load.py index c552137..27ae750 100644 --- a/yaksh/tests/test_load.py +++ b/yaksh/tests/test_load.py @@ -14,9 +14,12 @@ from selenium_test import SeleniumTest from yaksh.code_server import ServerPool, SERVER_POOL_PORT, SERVER_PORTS from yaksh import settings from yaksh.xmlrpc_clients import CodeServerProxy +from django.core.management import call_command + CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + class MySeleniumTests(StaticLiveServerTestCase): @classmethod def setUpClass(cls): @@ -33,54 +36,7 @@ class MySeleniumTests(StaticLiveServerTestCase): cls.code_server_thread = t = Thread(target=code_server_pool.run) t.start() - # Create set of demo users and profiles - mod_user = User.objects.create_user(username='yaksh_demo_mod', - password='yaksh_demo_mod', - email='yaksh_demo_mod@test.com' - ) - - user = User.objects.create_user(username='demo_yaksh_user', - password='demo_yaksh_user', - email='demo_yaksh_user@test.com' - ) - Profile.objects.create(user=user, - roll_number='demo_rn', - institute='IIT', - department='Chemical', - position='Student' - ) - - # create a course - course = Course.objects.create(name="Demo Load Course", - enrollment="Open Course", - creator=mod_user - ) - course.students.add(user) - - # create a Quiz - quiz = Quiz.objects.create( - start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), - end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), - duration=30, active=True, - attempts_allowed=1, time_between_attempts=0, - description='yaksh demo quiz', pass_criteria=0, - language='Python', prerequisite=None, - course=course - ) - - # create a question set - question = Question() - with open(os.path.join(CUR_DIR, 'test_questions.json'), 'r') as f: - question_list = f.read() - question.load_from_json(question_list, mod_user) - - # create question paper - question_paper = QuestionPaper.objects.create(quiz=quiz, - total_marks=5, - shuffle_questions=False - ) - # add fixed set of questions to the question paper - question_paper.fixed_questions.add(*Question.objects.all()) + call_command('create_demo_course') @classmethod def tearDownClass(cls): @@ -96,6 +52,6 @@ class MySeleniumTests(StaticLiveServerTestCase): def test_load(self): url = '%s%s' % (self.live_server_url, '/exam/login/') - quiz_name = "yaksh demo quiz" + quiz_name = "Demo_quiz" selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - selenium_test.run_load_test(url=url, username='demo_yaksh_user', password='demo_yaksh_user') + selenium_test.run_load_test(url=url, username='demo_student', password='demo_student') -- cgit From 953f856edc18ed22c72c56b58171e2ce5bc450e5 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Mon, 12 Sep 2016 16:22:55 +0530 Subject: Run the selenium and unit tests separately --- yaksh/tests/load_test.py | 60 ++++++++++++++++++++++++++++++++++++++++++++ yaksh/tests/selenium_test.py | 1 - yaksh/tests/test_load.py | 57 ----------------------------------------- 3 files changed, 60 insertions(+), 58 deletions(-) create mode 100644 yaksh/tests/load_test.py delete mode 100644 yaksh/tests/test_load.py (limited to 'yaksh') diff --git a/yaksh/tests/load_test.py b/yaksh/tests/load_test.py new file mode 100644 index 0000000..fd90b11 --- /dev/null +++ b/yaksh/tests/load_test.py @@ -0,0 +1,60 @@ +import os +import signal +import subprocess +from datetime import datetime +import pytz +from threading import Thread +from selenium.webdriver.firefox.webdriver import WebDriver + +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase +from selenium_test import SeleniumTest + +from yaksh.code_server import ServerPool #SERVER_POOL_PORT, SERVER_PORTS +from yaksh import settings +# from django.core.management import call_command +from yaksh.management.commands.create_demo_course import create_demo_course + + +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class MySeleniumTests(StaticLiveServerTestCase): + @classmethod + def setUpClass(cls): + super(MySeleniumTests, cls).setUpClass() + # setup a demo code server + settings.code_evaluators['python']['standardtestcase'] = \ + "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" + settings.code_evaluators['c']['standardtestcase'] = \ + "yaksh.cpp_code_evaluator.CppCodeEvaluator" + settings.code_evaluators['bash']['standardtestcase'] = \ + "yaksh.bash_code_evaluator.BashCodeEvaluator" + settings.SERVER_POOL_PORT = 53578 + code_server_pool = ServerPool(ports=settings.SERVER_PORTS, pool_port=settings.SERVER_POOL_PORT) + cls.code_server_pool = code_server_pool + cls.code_server_thread = t = Thread(target=code_server_pool.run) + t.start() + + demo_course_setup = create_demo_course() + + @classmethod + def tearDownClass(cls): + # User.objects.all().delete() + # Question.objects.all().delete() + # Quiz.objects.all().delete() + # Course.objects.all().delete() + + settings.SERVER_POOL_PORT = 53579 + + cls.code_server_pool.stop() + cls.code_server_thread.join() + + super(MySeleniumTests, cls).tearDownClass() + + def test_load(self): + url = '%s%s' % (self.live_server_url, '/exam/login/') + quiz_name = "Demo_quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + selenium_test.run_load_test(url=url, username='demo_student', password='demo_student') diff --git a/yaksh/tests/selenium_test.py b/yaksh/tests/selenium_test.py index 15d730e..01ccc96 100644 --- a/yaksh/tests/selenium_test.py +++ b/yaksh/tests/selenium_test.py @@ -126,7 +126,6 @@ def user_gen(url, ids): def wrap_run_load_test(args): url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" - quiz_name = "yaksh_demo_quiz" selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) return selenium_test.run_load_test(*args) diff --git a/yaksh/tests/test_load.py b/yaksh/tests/test_load.py deleted file mode 100644 index 27ae750..0000000 --- a/yaksh/tests/test_load.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -import signal -import subprocess -from datetime import datetime -import pytz -from threading import Thread -from selenium.webdriver.firefox.webdriver import WebDriver - -from django.contrib.staticfiles.testing import StaticLiveServerTestCase - -from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase -from selenium_test import SeleniumTest - -from yaksh.code_server import ServerPool, SERVER_POOL_PORT, SERVER_PORTS -from yaksh import settings -from yaksh.xmlrpc_clients import CodeServerProxy -from django.core.management import call_command - - -CUR_DIR = os.path.dirname(os.path.abspath(__file__)) - - -class MySeleniumTests(StaticLiveServerTestCase): - @classmethod - def setUpClass(cls): - super(MySeleniumTests, cls).setUpClass() - # setup a demo code server - settings.code_evaluators['python']['standardtestcase'] = \ - "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" - settings.code_evaluators['c']['standardtestcase'] = \ - "yaksh.cpp_code_evaluator.CppCodeEvaluator" - settings.code_evaluators['bash']['standardtestcase'] = \ - "yaksh.bash_code_evaluator.BashCodeEvaluator" - code_server_pool = ServerPool(ports=SERVER_PORTS, pool_port=SERVER_POOL_PORT) - cls.code_server_pool = code_server_pool - cls.code_server_thread = t = Thread(target=code_server_pool.run) - t.start() - - call_command('create_demo_course') - - @classmethod - def tearDownClass(cls): - User.objects.all().delete() - Question.objects.all().delete() - Quiz.objects.all().delete() - Course.objects.all().delete() - - cls.code_server_pool.stop() - cls.code_server_thread.join() - - super(MySeleniumTests, cls).tearDownClass() - - def test_load(self): - url = '%s%s' % (self.live_server_url, '/exam/login/') - quiz_name = "Demo_quiz" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - selenium_test.run_load_test(url=url, username='demo_student', password='demo_student') -- cgit From bf1986b58ce0e5619a2af221d5897f5f7fc708f0 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Sun, 18 Sep 2016 10:21:18 +0530 Subject: Remove commented code --- yaksh/tests/load_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'yaksh') diff --git a/yaksh/tests/load_test.py b/yaksh/tests/load_test.py index fd90b11..05fd02f 100644 --- a/yaksh/tests/load_test.py +++ b/yaksh/tests/load_test.py @@ -20,10 +20,10 @@ from yaksh.management.commands.create_demo_course import create_demo_course CUR_DIR = os.path.dirname(os.path.abspath(__file__)) -class MySeleniumTests(StaticLiveServerTestCase): +class YakshSeleniumTests(StaticLiveServerTestCase): @classmethod def setUpClass(cls): - super(MySeleniumTests, cls).setUpClass() + super(YakshSeleniumTests, cls).setUpClass() # setup a demo code server settings.code_evaluators['python']['standardtestcase'] = \ "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" @@ -41,17 +41,17 @@ class MySeleniumTests(StaticLiveServerTestCase): @classmethod def tearDownClass(cls): - # User.objects.all().delete() - # Question.objects.all().delete() - # Quiz.objects.all().delete() - # Course.objects.all().delete() + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + Course.objects.all().delete() settings.SERVER_POOL_PORT = 53579 cls.code_server_pool.stop() cls.code_server_thread.join() - super(MySeleniumTests, cls).tearDownClass() + super(YakshSeleniumTests, cls).tearDownClass() def test_load(self): url = '%s%s' % (self.live_server_url, '/exam/login/') -- cgit From 48f5117a0a0f7f712d3bafabf06e1c63de56e9fa Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Wed, 21 Sep 2016 15:51:19 +0530 Subject: Place selenium script and unit tests in live_server_tests dir --- yaksh/live_server_tests/__init__.py | 0 yaksh/live_server_tests/load_test.py | 77 ++++++++++++++++ yaksh/live_server_tests/selenium_test.py | 145 +++++++++++++++++++++++++++++++ yaksh/tests/load_test.py | 60 ------------- yaksh/tests/selenium_test.py | 145 ------------------------------- 5 files changed, 222 insertions(+), 205 deletions(-) create mode 100644 yaksh/live_server_tests/__init__.py create mode 100644 yaksh/live_server_tests/load_test.py create mode 100644 yaksh/live_server_tests/selenium_test.py delete mode 100644 yaksh/tests/load_test.py delete mode 100644 yaksh/tests/selenium_test.py (limited to 'yaksh') diff --git a/yaksh/live_server_tests/__init__.py b/yaksh/live_server_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/yaksh/live_server_tests/load_test.py b/yaksh/live_server_tests/load_test.py new file mode 100644 index 0000000..17934d4 --- /dev/null +++ b/yaksh/live_server_tests/load_test.py @@ -0,0 +1,77 @@ +import os +import signal +import subprocess +from datetime import datetime +import pytz +from threading import Thread +from selenium.webdriver.firefox.webdriver import WebDriver + +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase +from selenium_test import SeleniumTest + +from yaksh.code_server import ServerPool +from yaksh import settings + + +class YakshSeleniumTests(StaticLiveServerTestCase): + @classmethod + def setUpClass(cls): + super(YakshSeleniumTests, cls).setUpClass() + # setup a demo code server + settings.code_evaluators['python']['standardtestcase'] = \ + "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" + settings.code_evaluators['c']['standardtestcase'] = \ + "yaksh.cpp_code_evaluator.CppCodeEvaluator" + settings.code_evaluators['bash']['standardtestcase'] = \ + "yaksh.bash_code_evaluator.BashCodeEvaluator" + settings.SERVER_POOL_PORT = 53578 + code_server_pool = ServerPool(ports=settings.SERVER_PORTS, pool_port=settings.SERVER_POOL_PORT) + cls.code_server_pool = code_server_pool + cls.code_server_thread = t = Thread(target=code_server_pool.run) + t.start() + + demo_student = User.objects.create_user(username='demo_student', + password='demo_student', + email='demo_student@test.com' + ) + demo_student_profile = Profile.objects.create(user=demo_student, + roll_number=3, institute='IIT', + department='Chemical', position='Student' + ) + + demo_mod = User.objects.create_user(username='demo_mod', + password='demo_mod', + email='demo_mod@test.com' + ) + demo_mod_profile = Profile.objects.create(user=demo_mod, + roll_number=0, institute='IIT', + department='Chemical', position='Moderator' + ) + + course_obj = Course() + course_obj.create_demo(demo_mod) + demo_course = Course.objects.get(id=1) + + demo_course.students.add(demo_student) + + @classmethod + def tearDownClass(cls): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + Course.objects.all().delete() + + settings.SERVER_POOL_PORT = 53579 + + cls.code_server_pool.stop() + cls.code_server_thread.join() + + super(YakshSeleniumTests, cls).tearDownClass() + + def test_load(self): + url = '%s%s' % (self.live_server_url, '/exam/login/') + quiz_name = "Yaksh Demo quiz" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + selenium_test.run_load_test(url=url, username='demo_student', password='demo_student') diff --git a/yaksh/live_server_tests/selenium_test.py b/yaksh/live_server_tests/selenium_test.py new file mode 100644 index 0000000..01ccc96 --- /dev/null +++ b/yaksh/live_server_tests/selenium_test.py @@ -0,0 +1,145 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.common.exceptions import WebDriverException + +import multiprocessing +import argparse + +class SeleniumTest(): + def __init__(self, url, quiz_name): + self.driver = webdriver.Firefox() + self.quiz_name = quiz_name + self.url = url + + def run_load_test(self, url, username, password): + try: + self.driver.delete_all_cookies() + self.driver.get(self.url) + self.login(username, password) + self.open_quiz() + self.close_quiz() + self.logout() + self.driver.close() + except Exception as e: + with open("/tmp/yaksh_load_test_log.txt", "ab") as f: + f.write('Username: {0}\nError: {1}\n'.format(username, e)) + self.driver.close() + + def login(self, username, password): + # get the username, password and submit form elements + username_elem = self.driver.find_element_by_id("id_username") + password_elem = self.driver.find_element_by_id("id_password") + submit_login_elem = self.driver.find_element_by_css_selector('button.btn') + + # Type in the username, password and submit form + username_elem.send_keys(username) + password_elem.send_keys(password) + submit_login_elem.click() + + def submit_answer(self, question_label, answer, loop_count=1): + self.driver.implicitly_wait(2) + for count in range(loop_count): + self.driver.find_element_by_link_text(question_label).click() + submit_answer_elem = self.driver.find_element_by_id("check") + self.driver.execute_script('editor.setValue({})'.format(answer)) + submit_answer_elem.click() + + def test_c_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"int add(int a, int b, int c)\\n{return;}\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"int add(int a, int b, int c)\\n{while(1){}}\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"int add(int a, int b, int c)\\n{return a + b + c;}\"' + self.submit_answer(question_label, answer, loop_count) + + def test_python_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"def is_palindrome(s):\\n return s\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"while True:\\n pass"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"def is_palindrome(s):\\n return s[::-1] == s\"' + self.submit_answer(question_label, answer, loop_count) + + def test_bash_question(self, question_label): + # Incorrect Answer + loop_count = 10 + answer = '\"#!/bin/bash\\nls\"' + self.submit_answer(question_label, answer, loop_count) + + # Infinite Loop + loop_count = 3 + answer = '\"#!/bin/bash\\nwhile [ 1 ]; do : ; done\"' + self.submit_answer(question_label, answer, loop_count) + + # Correct Answer + loop_count = 1 + answer = '\"#!/bin/bash\\ncat $1 | cut -d: -f2 | paste -d: $3 - $2\"' + self.submit_answer(question_label, answer, loop_count) + + def open_quiz(self): + # open quiz link + quiz_link_elem = self.driver.find_element_by_link_text(self.quiz_name).click() + + # Get page elements + start_exam_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.NAME, "start")) + ) + start_exam_elem.click() + + self.test_c_question(question_label=1) + self.test_python_question(question_label=3) + self.test_bash_question(question_label=2) + + def close_quiz(self): + quit_link_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.ID, "login_again")) + ) + quit_link_elem.click() + + def logout(self): + logout_link_elem = WebDriverWait(self.driver, 5).until( + EC.presence_of_element_located((By.ID, "logout")) + ) + logout_link_elem.click() + +def user_gen(url, ids): + return [(url, 'User%d'%x, 'User%d'%x) for x in ids] + +def wrap_run_load_test(args): + url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" + selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) + return selenium_test.run_load_test(*args) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('url', type=str, help="url of the website being tested") + parser.add_argument('start', type=int, help="Starting user id") + parser.add_argument("-n", "--number", type=int, default=10, help="number of users") + opts = parser.parse_args() + + quiz_name = "Demo quiz" + selenium_test = SeleniumTest(url=opts.url, quiz_name=quiz_name) + pool = multiprocessing.Pool(opts.number) + pool.map(wrap_run_load_test, user_gen(opts.url, range(opts.start, opts.start + opts.number))) + pool.close() + pool.join() + diff --git a/yaksh/tests/load_test.py b/yaksh/tests/load_test.py deleted file mode 100644 index 05fd02f..0000000 --- a/yaksh/tests/load_test.py +++ /dev/null @@ -1,60 +0,0 @@ -import os -import signal -import subprocess -from datetime import datetime -import pytz -from threading import Thread -from selenium.webdriver.firefox.webdriver import WebDriver - -from django.contrib.staticfiles.testing import StaticLiveServerTestCase - -from yaksh.models import User, Profile, Question, Quiz, Course, QuestionPaper, TestCase -from selenium_test import SeleniumTest - -from yaksh.code_server import ServerPool #SERVER_POOL_PORT, SERVER_PORTS -from yaksh import settings -# from django.core.management import call_command -from yaksh.management.commands.create_demo_course import create_demo_course - - -CUR_DIR = os.path.dirname(os.path.abspath(__file__)) - - -class YakshSeleniumTests(StaticLiveServerTestCase): - @classmethod - def setUpClass(cls): - super(YakshSeleniumTests, cls).setUpClass() - # setup a demo code server - settings.code_evaluators['python']['standardtestcase'] = \ - "yaksh.python_assertion_evaluator.PythonAssertionEvaluator" - settings.code_evaluators['c']['standardtestcase'] = \ - "yaksh.cpp_code_evaluator.CppCodeEvaluator" - settings.code_evaluators['bash']['standardtestcase'] = \ - "yaksh.bash_code_evaluator.BashCodeEvaluator" - settings.SERVER_POOL_PORT = 53578 - code_server_pool = ServerPool(ports=settings.SERVER_PORTS, pool_port=settings.SERVER_POOL_PORT) - cls.code_server_pool = code_server_pool - cls.code_server_thread = t = Thread(target=code_server_pool.run) - t.start() - - demo_course_setup = create_demo_course() - - @classmethod - def tearDownClass(cls): - User.objects.all().delete() - Question.objects.all().delete() - Quiz.objects.all().delete() - Course.objects.all().delete() - - settings.SERVER_POOL_PORT = 53579 - - cls.code_server_pool.stop() - cls.code_server_thread.join() - - super(YakshSeleniumTests, cls).tearDownClass() - - def test_load(self): - url = '%s%s' % (self.live_server_url, '/exam/login/') - quiz_name = "Demo_quiz" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - selenium_test.run_load_test(url=url, username='demo_student', password='demo_student') diff --git a/yaksh/tests/selenium_test.py b/yaksh/tests/selenium_test.py deleted file mode 100644 index 01ccc96..0000000 --- a/yaksh/tests/selenium_test.py +++ /dev/null @@ -1,145 +0,0 @@ -from selenium import webdriver -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.common.exceptions import WebDriverException - -import multiprocessing -import argparse - -class SeleniumTest(): - def __init__(self, url, quiz_name): - self.driver = webdriver.Firefox() - self.quiz_name = quiz_name - self.url = url - - def run_load_test(self, url, username, password): - try: - self.driver.delete_all_cookies() - self.driver.get(self.url) - self.login(username, password) - self.open_quiz() - self.close_quiz() - self.logout() - self.driver.close() - except Exception as e: - with open("/tmp/yaksh_load_test_log.txt", "ab") as f: - f.write('Username: {0}\nError: {1}\n'.format(username, e)) - self.driver.close() - - def login(self, username, password): - # get the username, password and submit form elements - username_elem = self.driver.find_element_by_id("id_username") - password_elem = self.driver.find_element_by_id("id_password") - submit_login_elem = self.driver.find_element_by_css_selector('button.btn') - - # Type in the username, password and submit form - username_elem.send_keys(username) - password_elem.send_keys(password) - submit_login_elem.click() - - def submit_answer(self, question_label, answer, loop_count=1): - self.driver.implicitly_wait(2) - for count in range(loop_count): - self.driver.find_element_by_link_text(question_label).click() - submit_answer_elem = self.driver.find_element_by_id("check") - self.driver.execute_script('editor.setValue({})'.format(answer)) - submit_answer_elem.click() - - def test_c_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"int add(int a, int b, int c)\\n{return;}\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"int add(int a, int b, int c)\\n{while(1){}}\"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"int add(int a, int b, int c)\\n{return a + b + c;}\"' - self.submit_answer(question_label, answer, loop_count) - - def test_python_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"def is_palindrome(s):\\n return s\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"while True:\\n pass"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"def is_palindrome(s):\\n return s[::-1] == s\"' - self.submit_answer(question_label, answer, loop_count) - - def test_bash_question(self, question_label): - # Incorrect Answer - loop_count = 10 - answer = '\"#!/bin/bash\\nls\"' - self.submit_answer(question_label, answer, loop_count) - - # Infinite Loop - loop_count = 3 - answer = '\"#!/bin/bash\\nwhile [ 1 ]; do : ; done\"' - self.submit_answer(question_label, answer, loop_count) - - # Correct Answer - loop_count = 1 - answer = '\"#!/bin/bash\\ncat $1 | cut -d: -f2 | paste -d: $3 - $2\"' - self.submit_answer(question_label, answer, loop_count) - - def open_quiz(self): - # open quiz link - quiz_link_elem = self.driver.find_element_by_link_text(self.quiz_name).click() - - # Get page elements - start_exam_elem = WebDriverWait(self.driver, 5).until( - EC.presence_of_element_located((By.NAME, "start")) - ) - start_exam_elem.click() - - self.test_c_question(question_label=1) - self.test_python_question(question_label=3) - self.test_bash_question(question_label=2) - - def close_quiz(self): - quit_link_elem = WebDriverWait(self.driver, 5).until( - EC.presence_of_element_located((By.ID, "login_again")) - ) - quit_link_elem.click() - - def logout(self): - logout_link_elem = WebDriverWait(self.driver, 5).until( - EC.presence_of_element_located((By.ID, "logout")) - ) - logout_link_elem.click() - -def user_gen(url, ids): - return [(url, 'User%d'%x, 'User%d'%x) for x in ids] - -def wrap_run_load_test(args): - url = "http://yaksh.fossee.aero.iitb.ac.in/exam/" - selenium_test = SeleniumTest(url=url, quiz_name=quiz_name) - return selenium_test.run_load_test(*args) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('url', type=str, help="url of the website being tested") - parser.add_argument('start', type=int, help="Starting user id") - parser.add_argument("-n", "--number", type=int, default=10, help="number of users") - opts = parser.parse_args() - - quiz_name = "Demo quiz" - selenium_test = SeleniumTest(url=opts.url, quiz_name=quiz_name) - pool = multiprocessing.Pool(opts.number) - pool.map(wrap_run_load_test, user_gen(opts.url, range(opts.start, opts.start + opts.number))) - pool.close() - pool.join() - -- cgit