Fix some of the common test collection issues. (#21340)

* Remove old  performance tests that we haven't been running.

As far as I can tell, these tests to capture HAR files were created 5
years ago and not being run as a part of our suite?  They capture HAR
data that we do nothing with so even if they were running we should
remove them until we're ready to care about consuming this kind of
information.

* Update password test unicode string.
* Add ugettext translation helper function.
* Fix lambda syntax that is not valid in python 3.
* Fix ur raw strings which his not valid in python 3
* Use edx_six.get_gettext instead of ugettext.
* Fix a few other encoding issues.
* Don't use old form of sorted funciton.

This form which uses a 'cmp' method is not available in python 3.
This commit is contained in:
Feanil Patel
2019-08-16 11:31:36 -04:00
committed by GitHub
parent 8cf86012cf
commit f5f875401a
14 changed files with 91 additions and 274 deletions

View File

@@ -48,8 +48,8 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
def test_unicode_password(self):
""" Tests that validate_password enforces unicode """
byte_str = b'𤭮'
unicode_str = u'𤭮'
byte_str = unicode_str.encode('utf-8')
# Sanity checks and demonstration of why this test is useful
self.assertEqual(len(byte_str), 4)

View File

@@ -59,7 +59,9 @@ from six import text_type
from capa.xqueue_interface import XQUEUE_TIMEOUT
from chem import chemcalc
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib import edx_six
from xmodule.stringify import stringify_children
from openedx.core.lib import edx_six
from . import xqueue_interface
from .registry import TagRegistry
@@ -256,6 +258,7 @@ class InputTypeBase(object):
# Something went wrong: add xml to message, but keep the traceback
msg = u"Error in xml '{x}': {err} ".format(
x=etree.tostring(xml), err=text_type(err))
msg = Exception(msg)
six.reraise(Exception, msg, sys.exc_info()[2])
@classmethod
@@ -326,7 +329,7 @@ class InputTypeBase(object):
context = {
'id': self.input_id,
'value': self.value,
'status': Status(self.status, self.capa_system.i18n.ugettext),
'status': Status(self.status, edx_six.get_gettext(self.capa_system.i18n)),
'msg': self.msg,
'response_data': self.response_data,
'STATIC_URL': self.capa_system.STATIC_URL,
@@ -427,14 +430,21 @@ class OptionInput(InputTypeBase):
options = re.sub(r"([a-zA-Z])('|\\')([a-zA-Z])", r"\1'\3", options)
options = re.sub(r"\\'", r"'", options) # replace already escaped single quotes
# parse the set of possible options
lexer = shlex.shlex(options[1:-1].encode('utf8'))
if six.PY3:
lexer = shlex.shlex(options[1:-1])
else:
lexer = shlex.shlex(options[1:-1].encode('utf-8'))
lexer.quotes = "'"
# Allow options to be separated by whitespace as well as commas
lexer.whitespace = ", "
# remove quotes
# convert escaped single quotes (html encoded string) back to single quotes
tokens = [x[1:-1].decode('utf8').replace("'", "'") for x in lexer]
if six.PY3:
tokens = [x[1:-1].replace("'", "'") for x in lexer]
else:
tokens = [x[1:-1].decode('utf-8').replace("'", "'") for x in lexer]
# make list of (option_id, option_description), with description=id
return [(t, t) for t in tokens]
@@ -451,7 +461,7 @@ class OptionInput(InputTypeBase):
"""
Return extra context.
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
return {'default_option_text': _('Select an option')}
#-----------------------------------------------------------------------------
@@ -499,7 +509,7 @@ class ChoiceGroup(InputTypeBase):
self.html_input_type = "checkbox"
self.suffix = '[]'
else:
_ = i18n.ugettext
_ = edx_six.get_gettext(i18n)
# Translators: 'ChoiceGroup' is an input type and should not be translated.
msg = _("ChoiceGroup: unexpected tag {tag_name}").format(tag_name=self.tag)
raise Exception(msg)
@@ -535,7 +545,7 @@ class ChoiceGroup(InputTypeBase):
"""
choices = []
_ = i18n.ugettext
_ = edx_six.get_gettext(i18n)
for choice in element:
if choice.tag == 'choice':
@@ -731,7 +741,7 @@ class FileSubmission(InputTypeBase):
Do some magic to handle queueing status (render as "queued" instead of "incomplete"),
pull queue_len from the msg field. (TODO: get rid of the queue_len hack).
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
submitted_msg = _("Your files have been submitted. As soon as your submission is"
" graded, this message will be replaced with the grader's feedback.")
self.submitted_msg = submitted_msg
@@ -803,7 +813,7 @@ class CodeInput(InputTypeBase):
def setup(self):
""" setup this input type """
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
submitted_msg = _("Your answer has been submitted. As soon as your submission is"
" graded, this message will be replaced with the grader's feedback.")
self.submitted_msg = submitted_msg
@@ -814,7 +824,7 @@ class CodeInput(InputTypeBase):
"""
Define queue_len, arial_label and code mirror exit message context variables
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
return {
'queue_len': self.queue_len,
'aria_label': _('{programming_language} editor').format(
@@ -844,7 +854,7 @@ class MatlabInput(CodeInput):
"""
Handle matlab-specific parsing
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
submitted_msg = _("Submitted. As soon as a response is returned, "
"this message will be replaced by that feedback.")
@@ -927,7 +937,7 @@ class MatlabInput(CodeInput):
def _extra_context(self):
""" Set up additional context variables"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
queue_msg = self.queue_msg
if len(self.queue_msg) > 0: # An empty string cannot be parsed as XML but is okay to include in the template.
@@ -976,7 +986,7 @@ class MatlabInput(CodeInput):
dict - 'success' - whether or not we successfully queued this submission
- 'message' - message to be rendered in case of error
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# only send data if xqueue exists
if self.capa_system.xqueue is None:
return {'success': False, 'message': _('Cannot connect to the queue')}
@@ -1203,7 +1213,7 @@ class ChemicalEquationInput(InputTypeBase):
}
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
result = {'preview': '',
'error': ''}
try:
@@ -1287,7 +1297,7 @@ class FormulaEquationInput(InputTypeBase):
'request_start' : <time sent with request>
}
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
result = {'preview': '',
'error': ''}
@@ -1706,7 +1716,7 @@ class ChoiceTextGroup(InputTypeBase):
elif self.tag == 'checkboxtextgroup':
self.html_input_type = "checkbox"
else:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
msg = _("{input_type}: unexpected tag {tag_name}").format(
input_type="ChoiceTextGroup", tag_name=self.tag
)
@@ -1785,7 +1795,7 @@ class ChoiceTextGroup(InputTypeBase):
]
"""
_ = i18n.ugettext
_ = edx_six.get_gettext(i18n)
choices = []
for choice in element:

View File

@@ -46,6 +46,7 @@ from six.moves import map, range, zip
import capa.safe_exec as safe_exec
import capa.xqueue_interface as xqueue_interface
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib import edx_six
from . import correctmap
from .registry import TagRegistry
@@ -254,7 +255,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
- renderer : procedure which produces HTML given an ElementTree
- response_msg: a message displayed at the end of the Response
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# response_id = problem_id + response index
response_id = self.xml.attrib['id']
@@ -344,7 +345,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
e.g. [{'text': 'a hint', 'trigger':[{'choice': 'choice_0', 'selected': True},
{'choice': 'choice_1', 'selected':True}]}]
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# 1. Establish the hint_texts
# This can lead to early-exit if the hint is blank.
if not hint_log:
@@ -489,7 +490,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
unsafely=self.capa_system.can_execute_unsafe_code(),
)
except Exception as err:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
msg = _('Error {err} in evaluating hint function {hintfn}.').format(err=err, hintfn=hintfn)
sourcenum = getattr(self.xml, 'sourceline', _('(Source code line unavailable)'))
msg += "\n" + _("See XML source line {sourcenum}.").format(sourcenum=sourcenum)
@@ -1184,7 +1185,7 @@ class MultipleChoiceResponse(LoncapaResponse):
Fails with LoncapaProblemError if called on a response that is not masking.
"""
# if not self.has_mask():
# _ = self.capa_system.i18n.ugettext
# _ = edx_six.get_gettext(self.capa_system.i18n)
# # Translators: 'unmask_name' is a method name and should not be translated.
# msg = "unmask_name called on response that is not masked"
# raise LoncapaProblemError(msg)
@@ -1215,7 +1216,7 @@ class MultipleChoiceResponse(LoncapaResponse):
if choicegroups:
choicegroup = choicegroups[0]
if choicegroup.get('answer-pool') is not None:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: 'shuffle' and 'answer-pool' are attribute names and should not be translated.
msg = _("Do not use shuffle and answer-pool at the same time")
raise LoncapaProblemError(msg)
@@ -1298,7 +1299,7 @@ class MultipleChoiceResponse(LoncapaResponse):
try:
num_choices = int(num_str)
except ValueError:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: 'answer-pool' is an attribute name and should not be translated.
msg = _("answer-pool value should be an integer")
raise LoncapaProblemError(msg)
@@ -1365,7 +1366,7 @@ class MultipleChoiceResponse(LoncapaResponse):
# Or perhaps in the overall author workflow, these errors are unhelpful and
# should all be removed.
if len(correct_choices) < 1 or len(incorrect_choices) < 1:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: 'Choicegroup' is an input type and should not be translated.
msg = _("Choicegroup must include at least 1 correct and 1 incorrect choice")
raise LoncapaProblemError(msg)
@@ -1535,7 +1536,7 @@ class NumericalResponse(LoncapaResponse):
self.correct_answer = answer[0] + self.answer_range[0] + ', ' + self.answer_range[1] + answer[-1]
except Exception:
log.debug("Content error--answer '%s' is not a valid range tolerance answer", answer)
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
raise StudentInputError(
_("There was a problem with the staff answer to this problem.")
)
@@ -1567,7 +1568,7 @@ class NumericalResponse(LoncapaResponse):
correct_ans = evaluator({}, {}, answer)
except Exception:
log.debug("Content error--answer '%s' is not a valid number", answer)
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
raise StudentInputError(
_("There was a problem with the staff answer to this problem.")
)
@@ -1591,7 +1592,7 @@ class NumericalResponse(LoncapaResponse):
student_answer = student_answers[self.answer_id]
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
general_exception = StudentInputError(
_(u"Could not interpret '{student_answer}' as a number.").format(student_answer=cgi.escape(student_answer))
)
@@ -1778,7 +1779,7 @@ class NumericalResponse(LoncapaResponse):
return False
def get_answers(self):
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Example: "Answer: Answer_1 or Answer_2 or Answer_3".
separator = Text(' {b_start}{or_separator}{b_end} ').format(
# Translators: Separator used in NumericalResponse to display multiple answers.
@@ -1833,7 +1834,7 @@ class StringResponse(LoncapaResponse):
This response type allows one or more answers.
Additional answers are added by `additional_answer` tag.
If `regexp` is in `type` attribute, than answers and hints are treated as regular expressions.
If `regexp` is in `type` attribute, then answers and hints are treated as regular expressions.
Examples:
<stringresponse answer="Michigan">
@@ -2028,7 +2029,7 @@ class StringResponse(LoncapaResponse):
if not given:
return False
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# backward compatibility, should be removed in future.
if self.backward:
return self.check_string_backward(expected, given)
@@ -2067,7 +2068,7 @@ class StringResponse(LoncapaResponse):
return hints_to_show
def get_answers(self):
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: Separator used in StringResponse to display multiple answers.
# Example: "Answer: Answer_1 or Answer_2 or Answer_3".
separator = HTML(' <b>{}</b> ').format(_('or'))
@@ -2171,7 +2172,7 @@ class CustomResponse(LoncapaResponse):
student_answers is a dict with everything from request.POST, but with the first part
of each key removed (the string before the first "_").
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
log.debug('%s: student_answers=%s', six.text_type(self), student_answers)
@@ -2431,7 +2432,7 @@ class CustomResponse(LoncapaResponse):
# Raise an exception
else:
log.error(traceback.format_exc())
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
raise ResponseError(
_("CustomResponse: check function returned an invalid dictionary!")
)
@@ -2555,7 +2556,7 @@ class SymbolicResponse(CustomResponse):
except Exception as err:
log.error("oops in SymbolicResponse (cfn) error %s", err)
log.error(traceback.format_exc())
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: 'SymbolicResponse' is a problem type and should not be translated.
msg = _(u"An error occurred with SymbolicResponse. The error was: {error_msg}").format(
error_msg=err,
@@ -2651,12 +2652,12 @@ class CodeResponse(LoncapaResponse):
self.initial_display = find_with_default(
codeparam, 'initial_display', '')
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
self.answer = find_with_default(codeparam, 'answer_display',
_(u'No answer provided.'))
def get_score(self, student_answers):
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
try:
# Note that submission can be a file
submission = student_answers[self.answer_id]
@@ -2732,7 +2733,7 @@ class CodeResponse(LoncapaResponse):
cmap = CorrectMap()
if error:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
error_msg = _('Unable to deliver your submission to grader (Reason: {error_msg}).'
' Please try again later.').format(error_msg=msg)
cmap.set(self.answer_id, queuestate=None, msg=error_msg)
@@ -2752,7 +2753,7 @@ class CodeResponse(LoncapaResponse):
"""Updates the user's score based on the returned message from the grader."""
(valid_score_msg, correct, points, msg) = self._parse_score_msg(score_msg)
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
if not valid_score_msg:
# Translators: 'grader' refers to the edX automatic code grader.
@@ -3086,7 +3087,7 @@ class FormulaResponse(LoncapaResponse):
Each dictionary represents a test case for the answer.
Returns a tuple of formula evaluation results.
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
out = []
for var_dict in var_dict_list:
@@ -3283,7 +3284,7 @@ class SchematicResponse(LoncapaResponse):
unsafely=self.capa_system.can_execute_unsafe_code(),
)
except Exception as err:
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
# Translators: 'SchematicResponse' is a problem type and should not be translated.
msg = _('Error in evaluating SchematicResponse. The error was: {error_msg}').format(error_msg=err)
raise ResponseError(msg)
@@ -3339,7 +3340,7 @@ class ImageResponse(LoncapaResponse):
self.answer_ids = [ie.get('id') for ie in self.ielements]
def get_score(self, student_answers):
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
correct_map = CorrectMap()
expectedset = self.get_mapped_answers()
for aid in self.answer_ids: # loop through IDs of <imageinput>
@@ -3601,7 +3602,7 @@ class ChoiceTextResponse(LoncapaResponse):
and `answer_values` is used for displaying correct answers.
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
context = self.context
self.answer_values = {self.answer_id: []}
self.assign_choice_names()
@@ -3849,7 +3850,7 @@ class ChoiceTextResponse(LoncapaResponse):
Returns True if and only if all student inputs are correct.
"""
_ = self.capa_system.i18n.ugettext
_ = edx_six.get_gettext(self.capa_system.i18n)
inputs_correct = True
for answer_name, answer_value in six.iteritems(numtolerance_inputs):
# If `self.corrrect_inputs` does not contain an entry for

View File

@@ -3,6 +3,7 @@
from __future__ import absolute_import
import gettext
import io
import os
import os.path
import xml.sax.saxutils as saxutils
@@ -116,6 +117,6 @@ def load_fixture(relpath):
in the same directory as the test file.
"""
abspath = os.path.join(os.path.dirname(__file__), 'test_files', relpath)
with open(abspath) as fixture_file:
with io.open(abspath, encoding="utf-8") as fixture_file:
contents = fixture_file.read()
return contents.decode('utf8')
return contents

View File

@@ -699,18 +699,18 @@ class StringResponseTest(ResponseTest): # pylint: disable=missing-docstring
b) regexp is saved to xml and is read in python as repr of that string
So a\d in front-end editor will become a\\\\d in xml, so it will match a1 as student answer.
"""
problem = self.build_problem(answer=ur"5\\æ", case_sensitive=False, regexp=True)
self.assert_grade(problem, ur"5\æ", "correct")
problem = self.build_problem(answer=u"5\\\\æ", case_sensitive=False, regexp=True)
self.assert_grade(problem, u"5\\æ", "correct")
problem = self.build_problem(answer=u"5\\\\æ", case_sensitive=False, regexp=True)
self.assert_grade(problem, ur"5\æ", "correct")
self.assert_grade(problem, u"5\\æ", "correct")
def test_backslash(self):
problem = self.build_problem(answer=u"a\\\\c1", case_sensitive=False, regexp=True)
self.assert_grade(problem, ur"a\c1", "correct")
self.assert_grade(problem, u"a\\c1", "correct")
def test_special_chars(self):
problem = self.build_problem(answer=ur"a \s1", case_sensitive=False, regexp=True)
problem = self.build_problem(answer=u"a \\s1", case_sensitive=False, regexp=True)
self.assert_grade(problem, u"a 1", "correct")
def test_case_sensitive(self):

View File

@@ -102,7 +102,7 @@ def contextualize_text(text, context): # private
"""
if not text:
return text
for key in sorted(context, lambda x, y: cmp(len(y), len(x))):
for key in sorted(context, key=len, reverse=True):
# TODO (vshnayder): This whole replacement thing is a big hack
# right now--context contains not just the vars defined in the
# program, but also e.g. a reference to the numpy module.

View File

@@ -7,6 +7,7 @@ import json
import re
import requests
import six
from lazy import lazy
from common.test.acceptance.fixtures import LMS_BASE_URL, STUDIO_BASE_URL
@@ -88,8 +89,9 @@ class ConfigModelFixture(object):
if response.ok:
# auto_auth returns information about the newly created user
# capture this so it can be used by by the testcases.
user_pattern = re.compile(ur'Logged in user {0} \({1}\) with password {2} and user_id {3}'.format(
r'(?P<username>\S+)', r'(?P<email>[^\)]+)', r'(?P<password>\S+)', r'(?P<user_id>\d+)'))
user_pattern = re.compile(
six.text_type(r'Logged in user {0} \({1}\) with password {2} and user_id {3}').format( # pylint: disable=unicode-format-string
r'(?P<username>\S+)', r'(?P<email>[^\)]+)', r'(?P<password>\S+)', r'(?P<user_id>\d+)'))
user_matches = re.match(user_pattern, response.text)
if user_matches:
self.user = user_matches.groupdict() # pylint: disable=attribute-defined-outside-init

View File

@@ -68,7 +68,7 @@ class ImportExportMixin(object):
"""
string = self.q(css='.item-progresspoint-success-date').text[0]
return re.match(ur'\(([^ ]+).+?(\d{2}:\d{2})', string).groups()
return re.match(six.text_type(r'\(([^ ]+).+?(\d{2}:\d{2})'), string).groups() # pylint: disable=unicode-format-string
def wait_for_tasks(self, completed=False, fail_on=None):
"""

View File

@@ -1,116 +0,0 @@
"""
Single page performance tests for LMS.
"""
from __future__ import absolute_import
from bok_choy.web_app_test import with_cache
from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.dashboard import DashboardPage
from common.test.acceptance.pages.lms.login import LoginPage
from common.test.acceptance.pages.lms.progress import ProgressPage
from common.test.acceptance.tests.helpers import UniqueCourseTest, load_data_str
class LmsPerformanceTest(UniqueCourseTest):
"""
Base class to capture LMS performance with HTTP Archives.
"""
username = 'test_student'
email = 'student101@example.com'
har_mode = 'explicit'
def setUp(self):
"""
Setup course
"""
super(LmsPerformanceTest, self).setUp()
# 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_update(CourseUpdateDesc(date='January 29, 2014', content='Test course update1'))
course_fix.add_update(CourseUpdateDesc(date='January 30, 2014', content='Test course update2'))
course_fix.add_update(CourseUpdateDesc(date='January 31, 2014', content='Test course update3'))
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1', data=load_data_str('multiple_choice.xml')),
XBlockFixtureDesc('problem', 'Test Problem 2', data=load_data_str('formula_problem.xml')),
XBlockFixtureDesc('html', 'Test HTML', data="<html>Html child text</html>"),
)
),
XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 2').add_children(
XBlockFixtureDesc('html', 'Html Child', data="<html>Html child text</html>")
)
),
XBlockFixtureDesc('chapter', 'Test Section 3').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 3').add_children(
XBlockFixtureDesc('problem', 'Test Problem 3')
)
)
).install()
AutoAuthPage(self.browser, username=self.username, email=self.email, course_id=self.course_id).visit()
def _make_har_file(self, page):
"""
Visit page and make HAR file.
"""
har_name = '{page}_{course}'.format(page=type(page).__name__, course=self.course_info['number'])
self.har_capturer.add_page(self.browser, har_name)
page.visit()
self.har_capturer.save_har(self.browser, har_name)
@with_cache
def test_visit_coursware(self):
"""
Produce a HAR for loading the Coursware page.
"""
courseware_page = CoursewarePage(self.browser, self.course_id)
self._make_har_file(courseware_page)
@with_cache
def test_visit_dashboard(self):
"""
Produce a HAR for loading the Dashboard page.
"""
dashboard_page = DashboardPage(self.browser)
self._make_har_file(dashboard_page)
@with_cache
def test_visit_course_info(self):
"""
Produce a HAR for loading the Course Info page.
"""
course_info_page = CourseInfoPage(self.browser, self.course_id)
self._make_har_file(course_info_page)
@with_cache
def test_visit_login_page(self):
"""
Produce a HAR for loading the Login page.
"""
login_page = LoginPage(self.browser)
# Logout previously logged in user to be able to see Login page.
LogoutPage(self.browser).visit()
self._make_har_file(login_page)
@with_cache
def test_visit_progress_page(self):
"""
Produce a HAR for loading the Progress page.
"""
progress_page = ProgressPage(self.browser, self.course_id)
self._make_har_file(progress_page)

View File

@@ -1,100 +0,0 @@
"""
Single page performance tests for Studio.
"""
from __future__ import absolute_import
from bok_choy.web_app_test import with_cache
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from ..tests.helpers import AcceptanceTest
class StudioPagePerformanceTest(AcceptanceTest):
"""
Base class to capture studio performance with HTTP Archives.
To import courses for the bok choy tests, pass the --imports_dir=<course directory> argument to the paver command
where <course directory> contains the (un-archived) courses to be imported.
"""
course_org = 'edX'
course_num = 'Open_DemoX'
course_run = 'edx_demo_course'
har_mode = 'explicit'
def setUp(self):
"""
Authenticate as staff so we can view and edit courses.
"""
super(StudioPagePerformanceTest, self).setUp()
AutoAuthPage(self.browser, staff=True).visit()
def record_visit_outline(self):
"""
Produce a HAR for loading the course outline page.
"""
course_outline_page = CourseOutlinePage(self.browser, self.course_org, self.course_num, self.course_run)
har_name = 'OutlinePage_{org}_{course}'.format(
org=self.course_org,
course=self.course_num
)
self.har_capturer.add_page(self.browser, har_name)
course_outline_page.visit()
self.har_capturer.save_har(self.browser, har_name)
def record_visit_unit(self, section_title, subsection_title, unit_title):
"""
Produce a HAR for loading a unit page.
"""
course_outline_page = CourseOutlinePage(self.browser, self.course_org, self.course_num, self.course_run).visit()
course_outline_unit = course_outline_page.section(section_title).subsection(subsection_title).expand_subsection().unit(unit_title)
har_name = 'UnitPage_{org}_{course}'.format(
org=self.course_org,
course=self.course_num
)
self.har_capturer.add_page(self.browser, har_name)
course_outline_unit.go_to()
self.har_capturer.save_har(self.browser, har_name)
class StudioJusticePerformanceTest(StudioPagePerformanceTest):
"""
Test performance on the HarvardX Justice course.
"""
course_org = 'HarvardX'
course_num = 'ER22x'
course_run = '2013_Spring'
@with_cache
def test_visit_outline(self):
"""Record visiting the Justice course outline page"""
self.record_visit_outline()
@with_cache
def test_visit_unit(self):
"""Record visiting a Justice unit page"""
self.record_visit_unit(
'Lecture 1 - Doing the Right Thing',
'Discussion Prompt: Ethics of Torture',
'Discussion Prompt: Ethics of Torture'
)
class StudioPub101PerformanceTest(StudioPagePerformanceTest):
"""
Test performance on Andy's PUB101 outline page.
"""
course_org = 'AndyA'
course_num = 'PUB101'
course_run = 'PUB101'
@with_cache
def test_visit_outline(self):
"""Record visiting the PUB101 course outline page"""
self.record_visit_outline()
@with_cache
def test_visit_unit(self):
"""Record visiting the PUB101 unit page"""
self.record_visit_unit('Released', 'Released', 'Released')

View File

@@ -11,6 +11,7 @@ from uuid import uuid4
import pytest
from pytz import UTC
import six
from six.moves import map
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
@@ -1040,9 +1041,11 @@ class DiscussionEditorPreviewTest(UniqueCourseTest):
appear in the preview box
"""
self.page.set_new_post_editor_value(
ur'\begin{equation}'
ur'\tau_g(\omega) = - \frac{d}{d\omega}\phi(\omega) \hspace{2em} (1) '
ur'\end{equation}'
six.text_type(
r'\begin{equation}'
r'\tau_g(\omega) = - \frac{d}{d\omega}\phi(\omega) \hspace{2em} (1) ' # pylint: disable=unicode-format-string
r'\end{equation}'
)
)
self.assertIsNotNone(self.page.get_new_post_preview_text())
self.page.click_element(".cancel")

View File

@@ -504,7 +504,7 @@ def _section_course_info(course, access):
try:
sorted_cutoffs = sorted(list(course.grade_cutoffs.items()), key=lambda i: i[1], reverse=True)
advance = lambda memo, (letter, score): u"{}: {}, ".format(letter, score) + memo
advance = lambda memo, letter_score_tuple: u"{}: {}, ".format(letter_score_tuple[0], letter_score_tuple[1]) + memo # pylint: disable=line-too-long
section_data['grade_cutoffs'] = reduce(advance, sorted_cutoffs, "")[:-2]
except Exception: # pylint: disable=broad-except
section_data['grade_cutoffs'] = "Not Available"

View File

@@ -0,0 +1,16 @@
"""
Extra methods to do some python 2 to 3 things we need to do in edx-platform.
This is internal and should not be referenced outside of the edx-platform repo.
"""
import six
def get_gettext(o):
"""
In python 2 return the ugettext attribute. In python 3 return gettext.
"""
if six.PY3:
return o.gettext
else:
return o.ugettext