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