summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrabhu Ramachandran2016-09-21 17:58:12 +0530
committerGitHub2016-09-21 17:58:12 +0530
commit8e4ead8ab4caa9366e5357840e1912cbfb8cdb85 (patch)
treea8a9b90e0df9ce0893e7741bc33309af86ea034d
parent4f384f81cbde58f5eaa616dce85f1e4d60ea2c66 (diff)
parent48f5117a0a0f7f712d3bafabf06e1c63de56e9fa (diff)
downloadonline_test-8e4ead8ab4caa9366e5357840e1912cbfb8cdb85.tar.gz
online_test-8e4ead8ab4caa9366e5357840e1912cbfb8cdb85.tar.bz2
online_test-8e4ead8ab4caa9366e5357840e1912cbfb8cdb85.zip
Merge pull request #134 from ankitjavalkar/selenium-test-with-qdemo
Selenium test with qdemo
-rw-r--r--.travis.yml5
-rw-r--r--yaksh/live_server_tests/__init__.py0
-rw-r--r--yaksh/live_server_tests/load_test.py77
-rw-r--r--yaksh/live_server_tests/selenium_test.py145
-rw-r--r--yaksh/tests/test_questions.json50
5 files changed, 277 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml
index 8ad6c5f..3484d2d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,11 +14,16 @@ install:
- pip install -q Django==$DJANGO
- pip install -q pytz==2016.4
- pip install -q python-social-auth==0.2.19
+ - pip install selenium
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y scilab
+ - "export DISPLAY=:99.0"
+ - "sh -e /etc/init.d/xvfb start"
+ - sleep 3 # give xvfb some time to start
# command to run tests
script:
- python manage.py test -v 2 yaksh
+ - python manage.py test -v 2 yaksh.live_server_tests
diff --git a/yaksh/live_server_tests/__init__.py b/yaksh/live_server_tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/yaksh/live_server_tests/__init__.py
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/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 <code>is_palindrome(arg)</code> which will take one string argument. Return true if the argument is palindrome & false otherwise.\r\n<br><br>\r\nFor Example:\r\n<br>\r\n<code>is_palindrome(\"Hello\")</code> should return <code>False</code>\r\n<br>\r\n<br><br>",
+ "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"
+ }
+]