Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
a98e33af
Commit
a98e33af
authored
Sep 16, 2016
by
Sanford Student
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TNL-5466 tests for changing grade policy
and moving progress page tests into separate file
parent
2a0bdeb3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
338 additions
and
276 deletions
+338
-276
common/test/acceptance/pages/lms/problem.py
+1
-1
common/test/acceptance/pages/lms/progress.py
+7
-0
common/test/acceptance/tests/helpers.py
+29
-0
common/test/acceptance/tests/lms/test_lms_courseware.py
+28
-275
common/test/acceptance/tests/lms/test_progress_page.py
+273
-0
No files found.
common/test/acceptance/pages/lms/problem.py
View file @
a98e33af
...
...
@@ -162,7 +162,7 @@ class ProblemPage(PageObject):
"""
Click the choice input(radio, checkbox or option) where value matches `choice_value` in choice group.
"""
self
.
q
(
css
=
'div.problem .choicegroup input[value="'
+
choice_value
+
'"]'
)
.
click
()
self
.
q
(
css
=
'div.problem .choicegroup input[value="'
+
choice_value
+
'"]'
)
.
first
.
click
()
self
.
wait_for_ajax
()
def
is_correct
(
self
):
...
...
common/test/acceptance/pages/lms/progress.py
View file @
a98e33af
...
...
@@ -67,6 +67,13 @@ class ProgressPage(CoursePage):
# Retrieve the scores for the section
return
self
.
_section_scores
(
chapter_index
,
section_index
)
def
text_on_page
(
self
,
text
):
"""
Return whether the given text appears
on the page.
"""
return
text
in
self
.
q
(
css
=
".view-in-course"
)
.
html
[
0
]
def
_chapter_index
(
self
,
title
):
"""
Return the CSS index of the chapter with `title`.
...
...
common/test/acceptance/tests/helpers.py
View file @
a98e33af
...
...
@@ -17,6 +17,9 @@ from bok_choy.javascript import js_defined
from
bok_choy.web_app_test
import
WebAppTest
from
bok_choy.promise
import
EmptyPromise
,
Promise
from
bok_choy.page_object
import
XSS_INJECTION
from
capa.tests.response_xml_factory
import
MultipleChoiceResponseXMLFactory
from
common.test.acceptance.pages.studio.auto_auth
import
AutoAuthPage
from
common.test.acceptance.fixtures.course
import
XBlockFixtureDesc
from
opaque_keys.edx.locator
import
CourseLocator
from
pymongo
import
MongoClient
,
ASCENDING
from
openedx.core.lib.tests.assertions.events
import
assert_event_matches
,
is_matching_event
,
EventMatchTolerates
...
...
@@ -350,6 +353,32 @@ def is_404_page(browser):
return
'Page not found (404)'
in
browser
.
find_element_by_tag_name
(
'h1'
)
.
text
def
create_multiple_choice_problem
(
problem_name
):
"""
Return the Multiple Choice Problem Descriptor, given the name of the problem.
"""
factory
=
MultipleChoiceResponseXMLFactory
()
xml_data
=
factory
.
build_xml
(
question_text
=
'The correct answer is Choice 2'
,
choices
=
[
False
,
False
,
True
,
False
],
choice_names
=
[
'choice_0'
,
'choice_1'
,
'choice_2'
,
'choice_3'
]
)
return
XBlockFixtureDesc
(
'problem'
,
problem_name
,
data
=
xml_data
,
metadata
=
{
'rerandomize'
:
'always'
}
)
def
auto_auth
(
browser
,
username
,
email
,
staff
,
course_id
):
"""
Logout and login with given credentials.
"""
AutoAuthPage
(
browser
,
username
=
username
,
email
=
email
,
course_id
=
course_id
,
staff
=
staff
)
.
visit
()
class
EventsTestMixin
(
TestCase
):
"""
Helpers and setup for running tests that evaluate events emitted
...
...
common/test/acceptance/tests/lms/test_lms_courseware.py
View file @
a98e33af
...
...
@@ -3,58 +3,26 @@
End-to-end tests for the LMS.
"""
from
contextlib
import
contextmanager
import
json
from
datetime
import
datetime
,
timedelta
import
ddt
from
nose.plugins.attrib
import
attr
from
capa.tests.response_xml_factory
import
MultipleChoiceResponseXMLFactory
from
..helpers
import
UniqueCourseTest
,
EventsTestMixin
from
...pages.studio.auto_auth
import
AutoAuthPage
from
...pages.lms.create_mode
import
ModeCreationPage
from
...pages.studio.component_editor
import
ComponentEditorView
from
...pages.studio.overview
import
CourseOutlinePage
from
...pages.studio.utils
import
type_in_codemirror
from
...pages.lms.courseware
import
CoursewarePage
,
CoursewareSequentialTabPage
from
..helpers
import
UniqueCourseTest
,
EventsTestMixin
,
auto_auth
,
create_multiple_choice_problem
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
...pages.common.logout
import
LogoutPage
from
...pages.lms.course_nav
import
CourseNavPage
from
...pages.lms.instructor_dashboard
import
InstructorDashboardPage
from
...pages.lms.courseware
import
CoursewarePage
,
CoursewareSequentialTabPage
from
...pages.lms.create_mode
import
ModeCreationPage
from
...pages.lms.dashboard
import
DashboardPage
from
...pages.lms.pay_and_verify
import
PaymentAndVerificationFlow
,
FakePaymentPage
from
...pages.lms.problem
import
ProblemPage
from
...pages.
common.logout
import
Logout
Page
from
...pages.
lms.progress
import
Progress
Page
from
...pages.lms.staff_view
import
StaffPage
from
...pages.lms.track_selection
import
TrackSelectionPage
from
...pages.lms.pay_and_verify
import
PaymentAndVerificationFlow
,
FakePaymentPage
from
...pages.lms.dashboard
import
DashboardPage
from
...pages.lms.progress
import
ProgressPage
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
def
create_multiple_choice_problem
(
problem_name
):
"""
Return the Multiple Choice Problem Descriptor, given the name of the problem.
"""
factory
=
MultipleChoiceResponseXMLFactory
()
xml_data
=
factory
.
build_xml
(
question_text
=
'The correct answer is Choice 2'
,
choices
=
[
False
,
False
,
True
,
False
],
choice_names
=
[
'choice_0'
,
'choice_1'
,
'choice_2'
,
'choice_3'
]
)
return
XBlockFixtureDesc
(
'problem'
,
problem_name
,
data
=
xml_data
,
metadata
=
{
'rerandomize'
:
'always'
}
)
def
_auto_auth
(
browser
,
username
,
email
,
staff
,
course_id
):
"""
Logout and login with given credentials.
"""
AutoAuthPage
(
browser
,
username
=
username
,
email
=
email
,
course_id
=
course_id
,
staff
=
staff
)
.
visit
()
from
...pages.studio.auto_auth
import
AutoAuthPage
from
...pages.studio.overview
import
CourseOutlinePage
class
CoursewareTest
(
UniqueCourseTest
):
...
...
@@ -97,7 +65,7 @@ class CoursewareTest(UniqueCourseTest):
)
.
install
()
# Auto-auth register for the course.
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
def
_goto_problem_page
(
self
):
"""
...
...
@@ -121,7 +89,7 @@ class CoursewareTest(UniqueCourseTest):
# Logout and login as a staff user.
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
# Visit course outline page in studio.
self
.
course_outline
.
visit
()
...
...
@@ -131,7 +99,7 @@ class CoursewareTest(UniqueCourseTest):
# Logout and login as a student.
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
# Visit courseware as a student.
self
.
courseware_page
.
visit
()
...
...
@@ -210,14 +178,14 @@ class ProctoredExamTest(UniqueCourseTest):
)
.
visit
()
# Auto-auth register for the course.
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
def
_login_as_a_verified_user
(
self
):
"""
login as a verififed user
"""
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
# the track selection page cannot be visited. see the other tests to see if any prereq is there.
# Navigate to the track selection page
...
...
@@ -240,7 +208,7 @@ class ProctoredExamTest(UniqueCourseTest):
Then I can view all settings related to Proctored and timed exams
"""
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
self
.
course_outline
.
open_subsection_settings_dialog
()
...
...
@@ -256,7 +224,7 @@ class ProctoredExamTest(UniqueCourseTest):
Then I can see an option to take the exam as a proctored exam.
"""
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
self
.
course_outline
.
open_subsection_settings_dialog
()
...
...
@@ -275,7 +243,7 @@ class ProctoredExamTest(UniqueCourseTest):
then take it as student"
"""
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
self
.
course_outline
.
open_subsection_settings_dialog
()
...
...
@@ -314,13 +282,13 @@ class ProctoredExamTest(UniqueCourseTest):
self
.
_setup_and_take_timed_exam
(
hide_after_due
)
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
last_week
=
(
datetime
.
today
()
-
timedelta
(
days
=
7
))
.
strftime
(
"
%
m/
%
d/
%
Y"
)
self
.
course_outline
.
change_problem_due_date
(
last_week
)
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
self
.
courseware_page
.
visit
()
self
.
assertEqual
(
self
.
courseware_page
.
has_submitted_exam_message
(),
hide_after_due
)
...
...
@@ -335,7 +303,7 @@ class ProctoredExamTest(UniqueCourseTest):
self
.
_setup_and_take_timed_exam
()
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
courseware_page
.
visit
()
staff_page
=
StaffPage
(
self
.
browser
,
self
.
course_id
)
self
.
assertEqual
(
staff_page
.
staff_view_mode
,
'Staff'
)
...
...
@@ -357,7 +325,7 @@ class ProctoredExamTest(UniqueCourseTest):
Practice: True, False
"""
LogoutPage
(
self
.
browser
)
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
self
.
course_outline
.
open_subsection_settings_dialog
()
...
...
@@ -853,7 +821,7 @@ class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
self
.
_setup_subsection
()
# Auto-auth register for the course.
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
def
_setup_subsection
(
self
):
"""
...
...
@@ -861,7 +829,7 @@ class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
it as a student.
"""
self
.
logout_page
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
self
.
course_outline
.
open_subsection_settings_dialog
()
...
...
@@ -869,7 +837,7 @@ class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
self
.
course_outline
.
make_subsection_hidden_after_due_date
()
self
.
logout_page
.
visit
()
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
self
.
courseware_page
.
visit
()
self
.
logout_page
.
visit
()
...
...
@@ -893,7 +861,7 @@ class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
Then I should be able to see my grade on the progress page
"""
self
.
logout_page
.
visit
()
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
self
.
courseware_page
.
visit
()
self
.
assertFalse
(
self
.
courseware_page
.
content_hidden_past_due_date
())
...
...
@@ -901,230 +869,15 @@ class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
self
.
assertEqual
(
self
.
progress_page
.
scores
(
'Test Section 1'
,
'Test Subsection 1'
),
[(
0
,
1
)])
self
.
logout_page
.
visit
()
_
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
self
.
course_outline
.
visit
()
last_week
=
(
datetime
.
today
()
-
timedelta
(
days
=
7
))
.
strftime
(
"
%
m/
%
d/
%
Y"
)
self
.
course_outline
.
change_problem_due_date
(
last_week
)
self
.
logout_page
.
visit
()
_
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
self
.
courseware_page
.
visit
()
self
.
assertTrue
(
self
.
courseware_page
.
content_hidden_past_due_date
())
self
.
progress_page
.
visit
()
self
.
assertEqual
(
self
.
progress_page
.
scores
(
'Test Section 1'
,
'Test Subsection 1'
),
[(
0
,
1
)])
class
ProgressPageBaseTest
(
UniqueCourseTest
):
"""
Provides utility methods for tests retrieving
scores from the progress page.
"""
USERNAME
=
"STUDENT_TESTER"
EMAIL
=
"student101@example.com"
SECTION_NAME
=
'Test Section 1'
SUBSECTION_NAME
=
'Test Subsection 1'
UNIT_NAME
=
'Test Unit 1'
PROBLEM_NAME
=
'Test Problem 1'
def
setUp
(
self
):
super
(
ProgressPageBaseTest
,
self
)
.
setUp
()
self
.
courseware_page
=
CoursewarePage
(
self
.
browser
,
self
.
course_id
)
self
.
problem_page
=
ProblemPage
(
self
.
browser
)
# pylint: disable=attribute-defined-outside-init
self
.
progress_page
=
ProgressPage
(
self
.
browser
,
self
.
course_id
)
self
.
logout_page
=
LogoutPage
(
self
.
browser
)
self
.
course_outline
=
CourseOutlinePage
(
self
.
browser
,
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
]
)
# Install a course with sections/problems, tabs, updates, and handouts
course_fix
=
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
course_fix
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
self
.
SECTION_NAME
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
self
.
SUBSECTION_NAME
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
self
.
UNIT_NAME
)
.
add_children
(
create_multiple_choice_problem
(
self
.
PROBLEM_NAME
)
)
)
)
)
.
install
()
# Auto-auth register for the course.
_auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
def
_answer_problem_correctly
(
self
):
"""
Submit a correct answer to the problem.
"""
self
.
courseware_page
.
go_to_sequential_position
(
1
)
self
.
problem_page
.
click_choice
(
'choice_choice_2'
)
self
.
problem_page
.
click_check
()
def
_get_section_score
(
self
):
"""
Return a list of scores from the progress page.
"""
self
.
progress_page
.
visit
()
return
self
.
progress_page
.
section_score
(
self
.
SECTION_NAME
,
self
.
SUBSECTION_NAME
)
def
_get_scores
(
self
):
"""
Return a list of scores from the progress page.
"""
self
.
progress_page
.
visit
()
return
self
.
progress_page
.
scores
(
self
.
SECTION_NAME
,
self
.
SUBSECTION_NAME
)
@contextmanager
def
_logged_in_session
(
self
,
staff
=
False
):
"""
Ensure that the user is logged in and out appropriately at the beginning
and end of the current test.
"""
self
.
logout_page
.
visit
()
try
:
if
staff
:
_auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
else
:
_auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
yield
finally
:
self
.
logout_page
.
visit
()
class
ProgressPageTest
(
ProgressPageBaseTest
):
"""
Test that the progress page reports scores from completed assessments.
"""
def
test_progress_page_shows_scored_problems
(
self
):
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
[(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
0
,
1
))
self
.
courseware_page
.
visit
()
self
.
_answer_problem_correctly
()
self
.
assertEqual
(
self
.
_get_scores
(),
[(
1
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
1
))
@ddt.ddt
class
PersistentGradesTest
(
ProgressPageBaseTest
):
"""
Test that grades for completed assessments are persisted
when various edits are made.
"""
def
setUp
(
self
):
super
(
PersistentGradesTest
,
self
)
.
setUp
()
self
.
instructor_dashboard_page
=
InstructorDashboardPage
(
self
.
browser
,
self
.
course_id
)
def
_change_subsection_structure
(
self
):
"""
Adds a unit to the subsection, which
should not affect a persisted subsectiong grade.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
subsection
=
self
.
course_outline
.
section
(
self
.
SECTION_NAME
)
.
subsection
(
self
.
SUBSECTION_NAME
)
subsection
.
expand_subsection
()
subsection
.
add_unit
()
def
_set_staff_lock_on_subsection
(
self
,
locked
):
"""
Sets staff lock for a subsection, which should hide the
subsection score from students on the progress page.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
subsection
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
subsection
.
set_staff_lock
(
locked
)
self
.
assertEqual
(
subsection
.
has_staff_lock_warning
,
locked
)
def
_change_weight_for_problem
(
self
):
"""
Changes the weight of the problem, which should not affect
persisted grades.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
expand_subsection
()
unit
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit
(
self
.
UNIT_NAME
)
.
go_to
()
container
=
unit
.
xblocks
[
0
]
.
go_to_container
()
component
=
container
.
xblocks
[
0
]
.
children
[
0
]
component
.
edit
()
component_editor
=
ComponentEditorView
(
self
.
browser
,
component
.
locator
)
component_editor
.
set_field_value_and_save
(
'Problem Weight'
,
5
)
def
_rescore_for_all
(
self
):
"""
Triggers a rescore for all students. Currently unimplemented.
"""
pass
def
_edit_problem_content
(
self
):
"""
Replaces the content of a problem with other html.
Should not affect persisted grades.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
expand_subsection
()
unit
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit
(
self
.
UNIT_NAME
)
.
go_to
()
component
=
unit
.
xblocks
[
1
]
edit_view
=
component
.
edit
()
modified_content
=
"<p>modified content</p>"
# Set content in the CodeMirror editor.
type_in_codemirror
(
self
,
0
,
modified_content
)
edit_view
.
q
(
css
=
'.action-save'
)
.
click
()
@ddt.data
(
_edit_problem_content
,
_change_subsection_structure
,
_change_weight_for_problem
,
_rescore_for_all
)
def
test_content_changes_do_not_change_score
(
self
,
edit
):
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
[(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
0
,
1
))
self
.
courseware_page
.
visit
()
self
.
_answer_problem_correctly
()
self
.
assertEqual
(
self
.
_get_scores
(),
[(
1
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
1
))
edit
(
self
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
[(
1
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
1
))
def
test_visibility_change_does_affect_score
(
self
):
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
[(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
0
,
1
))
self
.
courseware_page
.
visit
()
self
.
_answer_problem_correctly
()
self
.
assertEqual
(
self
.
_get_scores
(),
[(
1
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
1
))
self
.
_set_staff_lock_on_subsection
(
True
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
None
)
self
.
assertEqual
(
self
.
_get_section_score
(),
None
)
self
.
_set_staff_lock_on_subsection
(
False
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_scores
(),
[(
1
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
1
))
common/test/acceptance/tests/lms/test_progress_page.py
0 → 100644
View file @
a98e33af
# -*- coding: utf-8 -*-
"""
End-to-end tests for the LMS that utilize the
progress page.
"""
from
contextlib
import
contextmanager
import
ddt
from
..helpers
import
UniqueCourseTest
,
auto_auth
,
create_multiple_choice_problem
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
...pages.common.logout
import
LogoutPage
from
...pages.lms.courseware
import
CoursewarePage
from
...pages.lms.instructor_dashboard
import
InstructorDashboardPage
from
...pages.lms.problem
import
ProblemPage
from
...pages.lms.progress
import
ProgressPage
from
...pages.studio.component_editor
import
ComponentEditorView
from
...pages.studio.utils
import
type_in_codemirror
from
...pages.studio.overview
import
CourseOutlinePage
class
ProgressPageBaseTest
(
UniqueCourseTest
):
"""
Provides utility methods for tests retrieving
scores from the progress page.
"""
USERNAME
=
"STUDENT_TESTER"
EMAIL
=
"student101@example.com"
SECTION_NAME
=
'Test Section 1'
SUBSECTION_NAME
=
'Test Subsection 1'
UNIT_NAME
=
'Test Unit 1'
PROBLEM_NAME
=
'Test Problem 1'
PROBLEM_NAME_2
=
'Test Problem 2'
def
setUp
(
self
):
super
(
ProgressPageBaseTest
,
self
)
.
setUp
()
self
.
courseware_page
=
CoursewarePage
(
self
.
browser
,
self
.
course_id
)
self
.
problem_page
=
ProblemPage
(
self
.
browser
)
# pylint: disable=attribute-defined-outside-init
self
.
progress_page
=
ProgressPage
(
self
.
browser
,
self
.
course_id
)
self
.
logout_page
=
LogoutPage
(
self
.
browser
)
self
.
course_outline
=
CourseOutlinePage
(
self
.
browser
,
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
]
)
# Install a course with problems
self
.
course_fix
=
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
self
.
course_fix
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
self
.
SECTION_NAME
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
self
.
SUBSECTION_NAME
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
self
.
UNIT_NAME
)
.
add_children
(
create_multiple_choice_problem
(
self
.
PROBLEM_NAME
),
create_multiple_choice_problem
(
self
.
PROBLEM_NAME_2
)
)
)
)
)
.
install
()
# Auto-auth register for the course.
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
def
_answer_problem_correctly
(
self
):
"""
Submit a correct answer to the problem.
"""
self
.
courseware_page
.
go_to_sequential_position
(
1
)
self
.
problem_page
.
click_choice
(
'choice_choice_2'
)
self
.
problem_page
.
click_check
()
def
_get_section_score
(
self
):
"""
Return a list of scores from the progress page.
"""
self
.
progress_page
.
visit
()
return
self
.
progress_page
.
section_score
(
self
.
SECTION_NAME
,
self
.
SUBSECTION_NAME
)
def
_get_problem_scores
(
self
):
"""
Return a list of scores from the progress page.
"""
self
.
progress_page
.
visit
()
return
self
.
progress_page
.
scores
(
self
.
SECTION_NAME
,
self
.
SUBSECTION_NAME
)
def
_check_progress_page_with_scored_problem
(
self
):
"""
Checks the progress page before and after answering
the course's first problem correctly.
"""
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_problem_scores
(),
[(
0
,
1
),
(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
0
,
2
))
self
.
courseware_page
.
visit
()
self
.
_answer_problem_correctly
()
self
.
assertEqual
(
self
.
_get_problem_scores
(),
[(
1
,
1
),
(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
2
))
@contextmanager
def
_logged_in_session
(
self
,
staff
=
False
):
"""
Ensure that the user is logged in and out appropriately at the beginning
and end of the current test.
"""
self
.
logout_page
.
visit
()
try
:
if
staff
:
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
else
:
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
yield
finally
:
self
.
logout_page
.
visit
()
class
ProgressPageTest
(
ProgressPageBaseTest
):
"""
Test that the progress page reports scores from completed assessments.
"""
def
test_progress_page_shows_scored_problems
(
self
):
self
.
_check_progress_page_with_scored_problem
()
@ddt.ddt
class
PersistentGradesTest
(
ProgressPageBaseTest
):
"""
Test that grades for completed assessments are persisted
when various edits are made.
"""
def
setUp
(
self
):
super
(
PersistentGradesTest
,
self
)
.
setUp
()
self
.
instructor_dashboard_page
=
InstructorDashboardPage
(
self
.
browser
,
self
.
course_id
)
def
_change_subsection_structure
(
self
):
"""
Adds a unit to the subsection, which
should not affect a persisted subsection grade.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
subsection
=
self
.
course_outline
.
section
(
self
.
SECTION_NAME
)
.
subsection
(
self
.
SUBSECTION_NAME
)
subsection
.
expand_subsection
()
subsection
.
add_unit
()
def
_set_staff_lock_on_subsection
(
self
,
locked
):
"""
Sets staff lock for a subsection, which should hide the
subsection score from students on the progress page.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
subsection
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
subsection
.
set_staff_lock
(
locked
)
self
.
assertEqual
(
subsection
.
has_staff_lock_warning
,
locked
)
def
_change_weight_for_problem
(
self
):
"""
Changes the weight of the problem, which should not affect
persisted grades.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
expand_subsection
()
unit
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit
(
self
.
UNIT_NAME
)
.
go_to
()
component
=
unit
.
xblocks
[
1
]
component
.
edit
()
component_editor
=
ComponentEditorView
(
self
.
browser
,
component
.
locator
)
component_editor
.
set_field_value_and_save
(
'Problem Weight'
,
5
)
def
_edit_problem_content
(
self
):
"""
Replaces the content of a problem with other html.
Should not affect persisted grades.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
expand_subsection
()
unit
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit
(
self
.
UNIT_NAME
)
.
go_to
()
component
=
unit
.
xblocks
[
1
]
modal
=
component
.
edit
()
# Set content in the CodeMirror editor.
modified_content
=
"<p>modified content</p>"
type_in_codemirror
(
self
,
0
,
modified_content
)
modal
.
q
(
css
=
'.action-save'
)
.
click
()
@ddt.data
(
_edit_problem_content
,
_change_subsection_structure
,
_change_weight_for_problem
)
def
test_content_changes_do_not_change_score
(
self
,
edit
):
with
self
.
_logged_in_session
():
self
.
_check_progress_page_with_scored_problem
()
edit
(
self
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_problem_scores
(),
[(
1
,
1
),
(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
2
))
def
test_visibility_change_does_affect_score
(
self
):
with
self
.
_logged_in_session
():
self
.
_check_progress_page_with_scored_problem
()
self
.
_set_staff_lock_on_subsection
(
True
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_problem_scores
(),
None
)
self
.
assertEqual
(
self
.
_get_section_score
(),
None
)
self
.
_set_staff_lock_on_subsection
(
False
)
with
self
.
_logged_in_session
():
self
.
assertEqual
(
self
.
_get_problem_scores
(),
[(
1
,
1
),
(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
2
))
class
SubsectionGradingPolicyTest
(
ProgressPageBaseTest
):
"""
Tests changing a subsection's 'graded' field
and the effect it has on the progress page.
"""
def
setUp
(
self
):
super
(
SubsectionGradingPolicyTest
,
self
)
.
setUp
()
self
.
_set_policy_for_subsection
(
"Homework"
)
def
_set_policy_for_subsection
(
self
,
policy
):
"""
Set the grading policy for the
subsection in the test.
"""
with
self
.
_logged_in_session
(
staff
=
True
):
self
.
course_outline
.
visit
()
modal
=
self
.
course_outline
.
section_at
(
0
)
.
subsection_at
(
0
)
.
edit
()
modal
.
policy
=
policy
modal
.
save
()
def
_check_scores_and_page_text
(
self
,
problem_scores
,
section_score
,
text
):
"""
Asserts that the given problem and section scores, and text,
appear on the progress page.
"""
self
.
assertEqual
(
self
.
_get_problem_scores
(),
problem_scores
)
self
.
assertEqual
(
self
.
_get_section_score
(),
section_score
)
self
.
assertTrue
(
self
.
progress_page
.
text_on_page
(
text
))
def
test_subsection_grading_policy_on_progress_page
(
self
):
with
self
.
_logged_in_session
():
self
.
_check_scores_and_page_text
([(
0
,
1
),
(
0
,
1
)],
(
0
,
2
),
"Homework 1 - Test Subsection 1 - 0
%
(0/2)"
)
self
.
courseware_page
.
visit
()
self
.
_answer_problem_correctly
()
self
.
_check_scores_and_page_text
([(
1
,
1
),
(
0
,
1
)],
(
1
,
2
),
"Homework 1 - Test Subsection 1 - 50
%
(1/2)"
)
self
.
_set_policy_for_subsection
(
"Not Graded"
)
with
self
.
_logged_in_session
():
self
.
progress_page
.
visit
()
self
.
assertEqual
(
self
.
_get_problem_scores
(),
[(
1
,
1
),
(
0
,
1
)])
self
.
assertEqual
(
self
.
_get_section_score
(),
(
1
,
2
))
self
.
assertFalse
(
self
.
progress_page
.
text_on_page
(
"Homework 1 - Test Subsection 1"
))
self
.
_set_policy_for_subsection
(
"Homework"
)
with
self
.
_logged_in_session
():
self
.
_check_scores_and_page_text
([(
1
,
1
),
(
0
,
1
)],
(
1
,
2
),
"Homework 1 - Test Subsection 1 - 50
%
(1/2)"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment