Instructor Dashboard management tools for Entrance Exams

Conflicts:
	lms/djangoapps/courseware/courses.py
	lms/djangoapps/instructor_task/api.py

refined entrance exam student attempts reset
added rescore, delete state and task history functionality
This commit is contained in:
Zia Fazal
2015-01-15 19:01:51 +05:00
committed by Matt Drayer
parent 80ae71765d
commit b3f85e1d4a
19 changed files with 1503 additions and 39 deletions

View File

@@ -102,7 +102,7 @@ class CourseFixture(XBlockContainerFixture):
between tests, you should use unique course identifiers for each fixture.
"""
def __init__(self, org, number, run, display_name, start_date=None, end_date=None):
def __init__(self, org, number, run, display_name, start_date=None, end_date=None, settings=None):
"""
Configure the course fixture to create a course with
@@ -112,6 +112,8 @@ class CourseFixture(XBlockContainerFixture):
The default is for the course to have started in the distant past, which is generally what
we want for testing so students can enroll.
`settings` can be any additional course settings needs to be enabled. for example
to enable entrance exam settings would be a dict like this {"entrance_exam_enabled": "true"}
These have the same meaning as in the Studio restful API /course end-point.
"""
super(CourseFixture, self).__init__()
@@ -134,6 +136,9 @@ class CourseFixture(XBlockContainerFixture):
if end_date is not None:
self._course_details['end_date'] = end_date.isoformat()
if settings is not None:
self._course_details.update(settings)
self._updates = []
self._handouts = []
self._assets = []

View File

@@ -37,6 +37,15 @@ class InstructorDashboardPage(CoursePage):
data_download_section.wait_for_page()
return data_download_section
def select_student_admin(self):
"""
Selects the student admin tab and returns the MembershipSection
"""
self.q(css='a[data-section=student_admin]').first.click()
student_admin_section = StudentAdminPage(self.browser)
student_admin_section.wait_for_page()
return student_admin_section
@staticmethod
def get_asset_path(file_name):
"""
@@ -460,3 +469,126 @@ class DataDownloadPage(PageObject):
"""
reports = self.q(css="#report-downloads-table .file-download-link>a").map(lambda el: el.text)
return reports.results
class StudentAdminPage(PageObject):
"""
Student admin section of the Instructor dashboard.
"""
url = None
EE_CONTAINER = ".entrance-exam-grade-container"
def is_browser_on_page(self):
"""
Confirms student admin section is present
"""
return self.q(css='a[data-section=student_admin].active-section').present
@property
def student_email_input(self):
"""
Returns email address/username input box.
"""
return self.q(css='{} input[name=entrance-exam-student-select-grade]'.format(self.EE_CONTAINER))
@property
def reset_attempts_button(self):
"""
Returns reset student attempts button.
"""
return self.q(css='{} input[name=reset-entrance-exam-attempts]'.format(self.EE_CONTAINER))
@property
def rescore_submission_button(self):
"""
Returns rescore student submission button.
"""
return self.q(css='{} input[name=rescore-entrance-exam]'.format(self.EE_CONTAINER))
@property
def delete_student_state_button(self):
"""
Returns delete student state button.
"""
return self.q(css='{} input[name=delete-entrance-exam-state]'.format(self.EE_CONTAINER))
@property
def background_task_history_button(self):
"""
Returns show background task history for student button.
"""
return self.q(css='{} input[name=entrance-exam-task-history]'.format(self.EE_CONTAINER))
@property
def top_notification(self):
"""
Returns show background task history for student button.
"""
return self.q(css='{} .request-response-error'.format(self.EE_CONTAINER)).first
def is_student_email_input_visible(self):
"""
Returns True if student email address/username input box is present.
"""
return self.student_email_input.is_present()
def is_reset_attempts_button_visible(self):
"""
Returns True if reset student attempts button is present.
"""
return self.reset_attempts_button.is_present()
def is_rescore_submission_button_visible(self):
"""
Returns True if rescore student submission button is present.
"""
return self.rescore_submission_button.is_present()
def is_delete_student_state_button_visible(self):
"""
Returns True if delete student state for entrance exam button is present.
"""
return self.delete_student_state_button.is_present()
def is_background_task_history_button_visible(self):
"""
Returns True if show background task history for student button is present.
"""
return self.background_task_history_button.is_present()
def is_background_task_history_table_visible(self):
"""
Returns True if background task history table is present.
"""
return self.q(css='{} .entrance-exam-task-history-table'.format(self.EE_CONTAINER)).is_present()
def click_reset_attempts_button(self):
"""
clicks reset student attempts button.
"""
return self.reset_attempts_button.click()
def click_rescore_submissions_button(self):
"""
clicks rescore submissions button.
"""
return self.rescore_submission_button.click()
def click_delete_student_state_button(self):
"""
clicks delete student state button.
"""
return self.delete_student_state_button.click()
def click_task_history_button(self):
"""
clicks background task history button.
"""
return self.background_task_history_button.click()
def set_student_email(self, email_addres):
"""
Sets given email address as value of student email address/username input box.
"""
input_box = self.student_email_input.first.results[0]
input_box.send_keys(email_addres)

View File

@@ -13,6 +13,8 @@ from opaque_keys.edx.locator import CourseLocator
from xmodule.partitions.partitions import UserPartition
from xmodule.partitions.tests.test_partitions import MockUserPartitionScheme
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def skip_if_browser(browser):
@@ -252,6 +254,15 @@ def assert_event_emitted_num_times(event_collection, event_name, event_time, eve
)
def get_modal_alert(browser):
"""
Returns instance of modal alert box shown in browser after waiting
for 4 seconds
"""
WebDriverWait(browser, 4).until(EC.alert_is_present())
return browser.switch_to.alert
class UniqueCourseTest(WebAppTest):
"""
Test that provides a unique course ID.

View File

@@ -3,7 +3,8 @@
End-to-end tests for the LMS Instructor Dashboard.
"""
from ..helpers import UniqueCourseTest
from ..helpers import UniqueCourseTest, get_modal_alert
from ...pages.common.logout import LogoutPage
from ...pages.lms.auto_auth import AutoAuthPage
from ...pages.lms.instructor_dashboard import InstructorDashboardPage
from ...fixtures.course import CourseFixture
@@ -84,3 +85,166 @@ class AutoEnrollmentWithCSVTest(UniqueCourseTest):
self.auto_enroll_section.upload_non_csv_file()
self.assertTrue(self.auto_enroll_section.is_notification_displayed(section_type=self.auto_enroll_section.NOTIFICATION_ERROR))
self.assertEqual(self.auto_enroll_section.first_notification_message(section_type=self.auto_enroll_section.NOTIFICATION_ERROR), "Make sure that the file you upload is in CSV format with no extraneous characters or rows.")
class EntranceExamGradeTest(UniqueCourseTest):
"""
Tests for Entrance exam specific student grading tasks.
"""
def setUp(self):
super(EntranceExamGradeTest, self).setUp()
self.course_info.update({"settings": {"entrance_exam_enabled": "true"}})
CourseFixture(**self.course_info).install()
self.student_identifier = "johndoe_saee@example.com"
# Create the user (automatically logs us in)
AutoAuthPage(
self.browser,
username="johndoe_saee",
email=self.student_identifier,
course_id=self.course_id,
staff=False
).visit()
LogoutPage(self.browser).visit()
# login as an instructor
AutoAuthPage(self.browser, course_id=self.course_id, staff=True).visit()
# go to the student admin page on the instructor dashboard
instructor_dashboard_page = InstructorDashboardPage(self.browser, self.course_id)
instructor_dashboard_page.visit()
self.student_admin_section = instructor_dashboard_page.select_student_admin()
def test_input_text_and_buttons_are_visible(self):
"""
Scenario: On the Student admin tab of the Instructor Dashboard, Student Email input box,
Reset Student Attempt, Rescore Student Submission, Delete Student State for entrance exam
and Show Background Task History for Student buttons are visible
Given that I am on the Student Admin tab on the Instructor Dashboard
Then I see Student Email input box, Reset Student Attempt, Rescore Student Submission,
Delete Student State for entrance exam and Show Background Task History for Student buttons
"""
self.assertTrue(self.student_admin_section.is_student_email_input_visible())
self.assertTrue(self.student_admin_section.is_reset_attempts_button_visible())
self.assertTrue(self.student_admin_section.is_rescore_submission_button_visible())
self.assertTrue(self.student_admin_section.is_delete_student_state_button_visible())
self.assertTrue(self.student_admin_section.is_background_task_history_button_visible())
def test_clicking_reset_student_attempts_button_without_email_shows_error(self):
"""
Scenario: Clicking on the Reset Student Attempts button without entering student email
address or username results in error.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Reset Student Attempts Button under Entrance Exam Grade
Adjustment without enter an email address
Then I should be shown an Error Notification
And The Notification message should read 'Please enter a student email address or username.'
"""
self.student_admin_section.click_reset_attempts_button()
self.assertEqual(
'Please enter a student email address or username.',
self.student_admin_section.top_notification.text[0]
)
def test_clicking_reset_student_attempts_button_with_success(self):
"""
Scenario: Clicking on the Reset Student Attempts button with valid student email
address or username should result in success prompt.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Reset Student Attempts Button under Entrance Exam Grade
Adjustment after entering a valid student
email address or username
Then I should be shown an alert with success message
"""
self.student_admin_section.set_student_email(self.student_identifier)
self.student_admin_section.click_reset_attempts_button()
alert = get_modal_alert(self.student_admin_section.browser)
alert.dismiss()
def test_clicking_reset_student_attempts_button_with_error(self):
"""
Scenario: Clicking on the Reset Student Attempts button with email address or username
of a non existing student should result in error message.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Reset Student Attempts Button under Entrance Exam Grade
Adjustment after non existing student email address or username
Then I should be shown an error message
"""
self.student_admin_section.set_student_email('non_existing@example.com')
self.student_admin_section.click_reset_attempts_button()
self.student_admin_section.wait_for_ajax()
self.assertGreater(len(self.student_admin_section.top_notification.text[0]), 0)
def test_clicking_rescore_submission_button_with_success(self):
"""
Scenario: Clicking on the Rescore Student Submission button with valid student email
address or username should result in success prompt.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Rescore Student Submission Button under Entrance Exam Grade
Adjustment after entering a valid student email address or username
Then I should be shown an alert with success message
"""
self.student_admin_section.set_student_email(self.student_identifier)
self.student_admin_section.click_rescore_submissions_button()
alert = get_modal_alert(self.student_admin_section.browser)
alert.dismiss()
def test_clicking_rescore_submission_button_with_error(self):
"""
Scenario: Clicking on the Rescore Student Submission button with email address or username
of a non existing student should result in error message.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Rescore Student Submission Button under Entrance Exam Grade
Adjustment after non existing student email address or username
Then I should be shown an error message
"""
self.student_admin_section.set_student_email('non_existing@example.com')
self.student_admin_section.click_rescore_submissions_button()
self.student_admin_section.wait_for_ajax()
self.assertGreater(len(self.student_admin_section.top_notification.text[0]), 0)
def test_clicking_delete_student_attempts_button_with_success(self):
"""
Scenario: Clicking on the Delete Student State for entrance exam button
with valid student email address or username should result in success prompt.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Delete Student State for entrance exam Button
under Entrance Exam Grade Adjustment after entering a valid student
email address or username
Then I should be shown an alert with success message
"""
self.student_admin_section.set_student_email(self.student_identifier)
self.student_admin_section.click_delete_student_state_button()
alert = get_modal_alert(self.student_admin_section.browser)
alert.dismiss()
def test_clicking_delete_student_attempts_button_with_error(self):
"""
Scenario: Clicking on the Delete Student State for entrance exam button
with email address or username of a non existing student should result
in error message.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Delete Student State for entrance exam Button
under Entrance Exam Grade Adjustment after non existing student
email address or username
Then I should be shown an error message
"""
self.student_admin_section.set_student_email('non_existing@example.com')
self.student_admin_section.click_delete_student_state_button()
self.student_admin_section.wait_for_ajax()
self.assertGreater(len(self.student_admin_section.top_notification.text[0]), 0)
def test_clicking_task_history_button_with_success(self):
"""
Scenario: Clicking on the Show Background Task History for Student
with valid student email address or username should result in table of tasks.
Given that I am on the Student Admin tab on the Instructor Dashboard
When I click the Show Background Task History for Student Button
under Entrance Exam Grade Adjustment after entering a valid student
email address or username
Then I should be shown an table listing all background tasks
"""
self.student_admin_section.set_student_email(self.student_identifier)
self.student_admin_section.click_task_history_button()
self.assertTrue(self.student_admin_section.is_background_task_history_table_visible())