diff options
author | ankitjavalkar | 2015-02-05 14:28:48 +0530 |
---|---|---|
committer | ankitjavalkar | 2015-04-26 19:31:24 +0530 |
commit | ecb202633d3b90c55128030adb7817387bf28c95 (patch) | |
tree | bc90138ce3e57ce3c2d6db3c845673077145e4c0 /testapp | |
parent | 28e2d32f9839b0e3cb3e99ce0113832627610bd7 (diff) | |
download | online_test-ecb202633d3b90c55128030adb7817387bf28c95.tar.gz online_test-ecb202633d3b90c55128030adb7817387bf28c95.tar.bz2 online_test-ecb202633d3b90c55128030adb7817387bf28c95.zip |
Modify method of passing test case attributes to code server
Conflicts:
testapp/exam/admin.py
testapp/exam/models.py
testapp/exam/views.py
Diffstat (limited to 'testapp')
-rw-r--r-- | testapp/exam/admin.py | 3 | ||||
-rwxr-xr-x | testapp/exam/code_server.py | 32 | ||||
-rw-r--r-- | testapp/exam/models.py | 75 | ||||
-rw-r--r-- | testapp/exam/views.py | 76 | ||||
-rw-r--r-- | testapp/exam/xmlrpc_clients.py | 4 |
5 files changed, 154 insertions, 36 deletions
diff --git a/testapp/exam/admin.py b/testapp/exam/admin.py index 060859a..1bdf436 100644 --- a/testapp/exam/admin.py +++ b/testapp/exam/admin.py @@ -1,5 +1,6 @@ -from testapp.exam.models import Question, Quiz +from exam.models import Question, Quiz, TestCase from django.contrib import admin admin.site.register(Question) +admin.site.register(TestCase) admin.site.register(Quiz) diff --git a/testapp/exam/code_server.py b/testapp/exam/code_server.py index 64d6a47..c070986 100755 --- a/testapp/exam/code_server.py +++ b/testapp/exam/code_server.py @@ -68,7 +68,8 @@ class CodeServer(object): 'have an infinite loop in your code.' % SERVER_TIMEOUT self.timeout_msg = msg - def run_python_code(self, answer, test_code, test_obj, in_dir=None): #### + def run_python_code(self, answer, test_code, test_parameter, in_dir=None): #### + # def run_python_code(self, answer, test_code, in_dir=None): #### """Tests given Python function (`answer`) with the `test_code` supplied. If the optional `in_dir` keyword argument is supplied it changes the directory to that directory (it does not change @@ -90,11 +91,23 @@ class CodeServer(object): success = False tb = None + + test_code_eval = "" + for test_case in test_parameter: + # for key, val in test_case.iteritems(): + pos_args = ", ".join(str(i) for i in test_case.get('pos_args')) if test_case.get('pos_args') \ + else "" + kw_args = ", ".join(str(k+"="+a) for k, a in test_case.get('kw_args').iteritems()) \ + if test_case.get('kw_args') else "" + args = pos_args + ", " + kw_args if pos_args and kw_args else pos_args or kw_args + tcode = "assert {0}({1}) == {2}" \ + .format(test_case.get('func_name'), args, test_case.get('expected_answer')) + test_code_eval += tcode + "\n" try: submitted = compile(answer, '<string>', mode='exec') g = {} exec submitted in g - _tests = compile(test_code, '<string>', mode='exec') + _tests = compile(test_code_eval, '<string>', mode='exec') exec _tests in g except TimeoutException: err = self.timeout_msg @@ -123,7 +136,8 @@ class CodeServer(object): return success, err - def run_bash_code(self, answer, test_code, test_obj, in_dir=None): #### + # def run_bash_code(self, answer, test_code, test_parameter, in_dir=None): #### + def run_bash_code(self, answer, test_code, in_dir=None): #### """Tests given Bash code (`answer`) with the `test_code` supplied. The testcode should typically contain two lines, the first is a path to @@ -290,7 +304,8 @@ class CodeServer(object): stdnt_stdout+stdnt_stderr) return False, err - def run_c_code(self, answer, test_code, test_obj, in_dir=None): #### + # def run_c_code(self, answer, test_code, test_parameter, in_dir=None): #### + def run_c_code(self, answer, test_code, in_dir=None): #### """Tests given C code (`answer`) with the `test_code` supplied. The testcode is a path to the reference code. @@ -442,7 +457,8 @@ class CodeServer(object): err = err + "\n" + stdnt_stderr return success, err - def run_cplus_code(self, answer, test_code, test_obj, in_dir=None): #### + # def run_cplus_code(self, answer, test_code, test_parameter, in_dir=None): #### + def run_cplus_code(self, answer, test_code, in_dir=None): #### """Tests given C++ code (`answer`) with the `test_code` supplied. The testcode is a path to the reference code. @@ -504,7 +520,8 @@ class CodeServer(object): return success, err - def run_java_code(self, answer, test_code, test_obj, in_dir=None): #### + # def run_java_code(self, answer, test_code, test_parameter, in_dir=None): #### + def run_java_code(self, answer, test_code, in_dir=None): #### """Tests given java code (`answer`) with the `test_code` supplied. The testcode is a path to the reference code. @@ -659,7 +676,8 @@ class CodeServer(object): stripped = stripped + c return ''.join(stripped) - def run_scilab_code(self, answer, test_code, test_obj, in_dir=None): #### + # def run_scilab_code(self, answer, test_code, test_parameter, in_dir=None): #### + def run_scilab_code(self, answer, test_code, in_dir=None): #### """Tests given Scilab function (`answer`) with the `test_code` supplied. If the optional `in_dir` keyword argument is supplied it changes the directory to that directory (it does not change diff --git a/testapp/exam/models.py b/testapp/exam/models.py index df3b485..4eeceac 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -62,15 +62,6 @@ class Question(models.Model): # Test cases for the question in the form of code that is run. test = models.TextField(blank=True) - #Test case Keyword arguments in dict form - test_keyword_args = models.TextField(blank=True) #### - - #Test case Positional arguments in list form - test_pos_args = models.TextField(blank=True) #### - - #Test case Expected answer in list form - test_expected_answer = models.TextField(blank=True) #### - # Any multiple choice options. Place one option per line. options = models.TextField(blank=True) @@ -91,6 +82,34 @@ class Question(models.Model): # Tags for the Question. tags = TaggableManager() + def consolidate_test_cases(self, test): + test_case_parameter= [] + + for i in test: + kw_args_dict = {} + pos_args_list = [] + + parameter_dict = {} + parameter_dict['test_id'] = i.id + parameter_dict['func_name'] = i.func_name + parameter_dict['expected_answer'] = i.expected_answer + parameter_dict['ref_code_path'] = i.ref_code_path + + if i.kw_args: + for args in i.kw_args.split(","): + key, val = args.split("=") + kw_args_dict[key.strip()] = val.strip() + + if i.pos_args: + for args in i.pos_args.split(","): + pos_args_list.append(args.strip()) + + parameter_dict['kw_args'] = kw_args_dict + parameter_dict['pos_args'] = pos_args_list + test_case_parameter.append(parameter_dict) + + return test_case_parameter + def __unicode__(self): return self.summary @@ -411,16 +430,48 @@ class AssignmentUpload(models.Model): class TestCase(models.Model): question = models.ForeignKey(Question) + # Test case function name + func_name = models.CharField(max_length=200) + # Test case Keyword arguments in dict form - test_keyword_args = models.TextField(blank=True) + kw_args = models.TextField(blank=True) # Test case Positional arguments in list form - test_pos_args = models.TextField(blank=True) + pos_args = models.TextField(blank=True) # Test case Expected answer in list form - test_expected_answer = models.TextField(blank=True) + expected_answer = models.TextField(blank=True) + + # Test case path to system test code applicable for CPP, C, Java and Scilab + ref_code_path = models.TextField(blank=True) # Is this Test Case public or not. If it is not # public it will not be visible to the user # public = models.BooleanField(default=False) + # def consolidate_test_cases(self): + # test_case_parameter= {} + # kw_args_dict = {} + # pos_args_list = [] + + # for i in self: + # test_case_parameter.setdefault(i.id, {}) + # test_case_parameter[i.id]['func_name'] = i.func_name + # test_case_parameter[i.id]['expected_answer'] = i.expected_answer + + # for args in i.kw_args.split(","): + # key, val = args.split("=") + # kw_args_dict[key.strip()] = val.strip() + + + # for args in i.pos_args.split(","): + # pos_args_list.append(args.strip()) + + # test_case_parameter[i.id]['kw_args'] = kw_args_dict + # test_case_parameter[i.id]['pos_args'] = pos_args_list + + # # test_case_parameter[i.id]['kw_args'] = i.kw_args + # # test_case_parameter[i.id]['pos_args'] = i.pos_args + + # return test_case_parameter + diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 9b6ce69..ac2668c 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -16,7 +16,7 @@ from taggit.models import Tag from itertools import chain # Local imports. from testapp.exam.models import Quiz, Question, QuestionPaper, QuestionSet -from testapp.exam.models import Profile, Answer, AnswerPaper, User +from testapp.exam.models import Profile, Answer, AnswerPaper, User, TestCase from testapp.exam.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionForm, RandomQuestionForm from testapp.exam.xmlrpc_clients import code_server @@ -848,6 +848,49 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): return my_redirect('/exam/login/') question = get_object_or_404(Question, pk=q_id) + q_paper = QuestionPaper.objects.get(id=questionpaper_id) + paper = AnswerPaper.objects.get(user=request.user, question_paper=q_paper) + test = TestCase.objects.filter(question=question) + test_parameter = question.consolidate_test_cases(test) + + # #### + # for i in TestCase.objects.all(): + # print "=====$$$$$=====KEY", i.kw_args + # print "=====$$$$$=====POS", i.pos_args + # print "=====$$$$$=====FUNC", i.func_name + + # test_case_parameters = {} + # kw_args_dict = {} + # pos_args_list = [] + + # for i in TestCase.objects.all(): + # test_case_parameters.setdefault(i.id, {}) + # test_case_parameters[i.id]['func_name'] = i.func_name + # test_case_parameters[i.id]['expected_answer'] = i.expected_answer + + # for args in i.kw_args.split(","): + # key, val = args.split("=") + # kw_args_dict[key.strip()] = val.strip() + + + # for args in i.pos_args.split(","): + # pos_args_list.append(args.strip()) + + # test_case_parameters[i.id]['kw_args'] = kw_args_dict + # test_case_parameters[i.id]['pos_args'] = pos_args_list + + # print "######-----####-----", test_case_parameters + + # test_obj = TestCase.objects.filter(question=question) + # test_parameter = [] + # for i in test_obj: + # d = {} + # d['test_func_name'] = i.test_func_name + # d['test_keyword_args'] = i.test_keyword_args + # d['test_pos_args'] = i.test_pos_args + # d['test_expected_answer'] = i.test_expected_answer + # test_parameter.append(d) + # #### snippet_code = request.POST.get('snippet') user_code = request.POST.get('answer') skip = request.POST.get('skip', None) @@ -860,6 +903,19 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): next_q = paper.skip() return show_question(request, next_q, attempt_num, questionpaper_id) + # ### of the form addnum(1, 2, one=2, two=2) + # test_code_eval = "" + # for param in test_parameter: + # # print "TESTCASE----OUTLOOP", literal_eval(test_case['test_keyword_args']) + + # tcode = "assert {0}({1}, {2})\n""" \ + # .format(param.get('test_func_name'), param.get('test_pos_args'), param.get('test_keyword_args')) + # # .format(", ".join(str(i) for i in test_case['test_pos_args']), + # # ", ".join(str(key+"="+arg) for key, arg in eval(test_case['test_keyword_args']).iteritems())) + # test_code_eval = "\n".join(tcode) + + # print test_code_eval + # Add the answer submitted, regardless of it being correct or not. if question.type == 'mcq': user_answer = request.POST.get('answer') @@ -876,7 +932,8 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): assign.save() user_answer = 'ASSIGNMENT UPLOADED' else: - user_answer = snippet_code + "\n" + user_code + user_code = request.POST.get('answer') + user_answer = user_code #snippet_code + "\n" + user_code new_answer = Answer(question=question, answer=user_answer, correct=False) @@ -887,7 +944,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # questions, we obtain the results via XML-RPC with the code executed # safely in a separate process (the code_server.py) running as nobody. if not question.type == 'upload': - correct, success, err_msg = validate_answer(user, user_answer, question) + correct, success, err_msg = validate_answer(user, user_answer, question, test_parameter) if correct: new_answer.correct = correct new_answer.marks = question.points @@ -933,7 +990,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): questionpaper_id, success_msg) -def validate_answer(user, user_answer, question): +def validate_answer(user, user_answer, question, test_parameter):#### """ Checks whether the answer submitted by the user is right or wrong. If right then returns correct = True, success and @@ -958,18 +1015,9 @@ def validate_answer(user, user_answer, question): message = 'Correct answer' elif question.type == 'code': user_dir = get_user_dir(user) - success, message = code_server.run_code(user_answer, question.test, - question.test_keyword_args, question.test_pos_args, - question.test_expected_answer, user_dir, question.language) #### + success, message = code_server.run_code(user_answer, question.test, test_parameter, user_dir, question.language) #### if success: correct = True - - #### - print "MESS>>>", question.test - print "POS>>>", question.test_pos_args - print "KEY>>>", question.test_keyword_args - print "EXP>>>", question.test_expected_answer - #### return correct, success, message diff --git a/testapp/exam/xmlrpc_clients.py b/testapp/exam/xmlrpc_clients.py index 1aab8de..320d627 100644 --- a/testapp/exam/xmlrpc_clients.py +++ b/testapp/exam/xmlrpc_clients.py @@ -29,7 +29,7 @@ class CodeServerProxy(object): "scilab": "run_scilab_code", } - def run_code(self, answer, test_code, test_obj, keyword_args, pos_args, expected_answer, user_dir, language): #### + def run_code(self, answer, test_code, test_parameter, user_dir, language): #### """Tests given code (`answer`) with the `test_code` supplied. If the optional `in_dir` keyword argument is supplied it changes the directory to that directory (it does not change it back to the original when @@ -55,7 +55,7 @@ class CodeServerProxy(object): try: server = self._get_server() method = getattr(server, method_name) - result = method(answer, test_code, test_obj, user_dir) #### + result = method(answer, test_code, test_parameter, user_dir) #### except ConnectionError: result = [False, 'Unable to connect to any code servers!'] return result |