replaced unittest assertions pytest assertions (19) (#26545)
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
Tests for the EdxNotes app.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime
|
||||
from unittest import skipUnless
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
import jwt
|
||||
@@ -144,10 +144,7 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
|
||||
"eventStringLimit": settings.TRACK_MAX_EVENT / 6,
|
||||
},
|
||||
}
|
||||
self.assertEqual(
|
||||
problem.get_html(),
|
||||
render_to_string("edxnotes_wrapper.html", expected_context),
|
||||
)
|
||||
assert problem.get_html() == render_to_string('edxnotes_wrapper.html', expected_context)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
def test_edxnotes_disabled_if_edxnotes_flag_is_false(self):
|
||||
@@ -156,28 +153,28 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
|
||||
disabled for the course.
|
||||
"""
|
||||
self.course.edxnotes = False
|
||||
self.assertEqual("original_get_html", self.problem.get_html())
|
||||
assert 'original_get_html' == self.problem.get_html()
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": False})
|
||||
def test_edxnotes_disabled(self):
|
||||
"""
|
||||
Tests that get_html is not wrapped when feature flag is off.
|
||||
"""
|
||||
self.assertEqual("original_get_html", self.problem.get_html())
|
||||
assert 'original_get_html' == self.problem.get_html()
|
||||
|
||||
def test_edxnotes_studio(self):
|
||||
"""
|
||||
Tests that get_html is not wrapped when problem is rendered in Studio.
|
||||
"""
|
||||
self.problem.system.is_author_mode = True
|
||||
self.assertEqual("original_get_html", self.problem.get_html())
|
||||
assert 'original_get_html' == self.problem.get_html()
|
||||
|
||||
def test_edxnotes_blockstore_runtime(self):
|
||||
"""
|
||||
Tests that get_html is not wrapped when problem is rendered by Blockstore runtime.
|
||||
"""
|
||||
del self.problem.descriptor.runtime.modulestore
|
||||
self.assertEqual("original_get_html", self.problem.get_html())
|
||||
assert 'original_get_html' == self.problem.get_html()
|
||||
|
||||
def test_edxnotes_harvard_notes_enabled(self):
|
||||
"""
|
||||
@@ -185,7 +182,7 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
|
||||
"""
|
||||
self.course.advanced_modules = ["videoannotation", "imageannotation", "textannotation"]
|
||||
enable_edxnotes_for_the_course(self.course, self.user.id)
|
||||
self.assertEqual("original_get_html", self.problem.get_html())
|
||||
assert 'original_get_html' == self.problem.get_html()
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
def test_anonymous_user(self):
|
||||
@@ -294,23 +291,23 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
# url ends with "/"
|
||||
with patch_edxnotes_api_settings("http://example.com/"):
|
||||
self.assertEqual("http://example.com/", get_endpoint_function())
|
||||
assert 'http://example.com/' == get_endpoint_function()
|
||||
|
||||
# url doesn't have "/" at the end
|
||||
with patch_edxnotes_api_settings("http://example.com"):
|
||||
self.assertEqual("http://example.com/", get_endpoint_function())
|
||||
assert 'http://example.com/' == get_endpoint_function()
|
||||
|
||||
# url with path that starts with "/"
|
||||
with patch_edxnotes_api_settings("http://example.com"):
|
||||
self.assertEqual("http://example.com/some_path/", get_endpoint_function("/some_path"))
|
||||
assert 'http://example.com/some_path/' == get_endpoint_function('/some_path')
|
||||
|
||||
# url with path without "/"
|
||||
with patch_edxnotes_api_settings("http://example.com"):
|
||||
self.assertEqual("http://example.com/some_path/", get_endpoint_function("some_path/"))
|
||||
assert 'http://example.com/some_path/' == get_endpoint_function('some_path/')
|
||||
|
||||
# url is not configured
|
||||
with patch_edxnotes_api_settings(None):
|
||||
self.assertRaises(ImproperlyConfigured, get_endpoint_function)
|
||||
pytest.raises(ImproperlyConfigured, get_endpoint_function)
|
||||
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_get_notes_correct_data(self, mock_get):
|
||||
@@ -851,7 +848,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_course_module = MagicMock()
|
||||
mock_course_module.position = 3
|
||||
mock_course_module.get_display_items.return_value = []
|
||||
self.assertIsNone(helpers.get_course_position(mock_course_module))
|
||||
assert helpers.get_course_position(mock_course_module) is None
|
||||
|
||||
def test_get_course_position_to_chapter(self):
|
||||
"""
|
||||
@@ -866,10 +863,10 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
mock_course_module.get_display_items.return_value = [mock_chapter]
|
||||
|
||||
self.assertEqual(helpers.get_course_position(mock_course_module), {
|
||||
assert helpers.get_course_position(mock_course_module) == {
|
||||
'display_name': 'Test Chapter Display Name',
|
||||
'url': '/courses/{}/courseware/chapter_url_name/'.format(self.course.id),
|
||||
})
|
||||
'url': '/courses/{}/courseware/chapter_url_name/'.format(self.course.id)
|
||||
}
|
||||
|
||||
def test_get_course_position_no_section(self):
|
||||
"""
|
||||
@@ -877,7 +874,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
"""
|
||||
mock_course_module = MagicMock(id=self.course.id, position=None)
|
||||
mock_course_module.get_display_items.return_value = [MagicMock()]
|
||||
self.assertIsNone(helpers.get_course_position(mock_course_module))
|
||||
assert helpers.get_course_position(mock_course_module) is None
|
||||
|
||||
def test_get_course_position_to_section(self):
|
||||
"""
|
||||
@@ -897,18 +894,18 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_chapter.get_display_items.return_value = [mock_section]
|
||||
mock_section.get_display_items.return_value = [MagicMock()]
|
||||
|
||||
self.assertEqual(helpers.get_course_position(mock_course_module), {
|
||||
assert helpers.get_course_position(mock_course_module) == {
|
||||
'display_name': 'Test Section Display Name',
|
||||
'url': '/courses/{}/courseware/chapter_url_name/section_url_name/'.format(self.course.id),
|
||||
})
|
||||
'url': '/courses/{}/courseware/chapter_url_name/section_url_name/'.format(self.course.id)
|
||||
}
|
||||
|
||||
def test_get_index(self):
|
||||
"""
|
||||
Tests `get_index` method returns unit url.
|
||||
"""
|
||||
children = self.sequential.children
|
||||
self.assertEqual(0, helpers.get_index(text_type(self.vertical.location), children))
|
||||
self.assertEqual(1, helpers.get_index(text_type(self.vertical_with_container.location), children))
|
||||
assert 0 == helpers.get_index(text_type(self.vertical.location), children)
|
||||
assert 1 == helpers.get_index(text_type(self.vertical_with_container.location), children)
|
||||
|
||||
@ddt.unpack
|
||||
@ddt.data(
|
||||
@@ -941,13 +938,13 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
"""
|
||||
# if api url is None then constructed url should also be None
|
||||
if expected is None:
|
||||
self.assertEqual(expected, constructed)
|
||||
assert expected == constructed
|
||||
else:
|
||||
# constructed url should startswith notes view url instead of api view url
|
||||
self.assertTrue(constructed.startswith(notes_url))
|
||||
assert constructed.startswith(notes_url)
|
||||
|
||||
# constructed url should not contain extra params
|
||||
self.assertNotIn('user', constructed)
|
||||
assert 'user' not in constructed
|
||||
|
||||
# constructed url should only has these params if present in api url
|
||||
allowed_params = ('page', 'page_size', 'text')
|
||||
@@ -958,8 +955,8 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
# verify that constructed url has only correct params and params have correct values
|
||||
for param, value in params.items():
|
||||
self.assertIn(param, allowed_params)
|
||||
self.assertIn('{}={}'.format(param, value[0]), expected)
|
||||
assert param in allowed_params
|
||||
assert '{}={}'.format(param, value[0]) in expected
|
||||
|
||||
next_url, previous_url = helpers.construct_pagination_urls(
|
||||
self.request,
|
||||
@@ -1006,15 +1003,15 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
tabs = get_course_tab_list(user, course)
|
||||
return len([tab for tab in tabs if tab.type == 'edxnotes']) == 1
|
||||
|
||||
self.assertFalse(has_notes_tab(self.user, self.course))
|
||||
assert not has_notes_tab(self.user, self.course)
|
||||
enable_edxnotes_for_the_course(self.course, self.user.id)
|
||||
# disable course.edxnotes
|
||||
self.course.edxnotes = False
|
||||
self.assertFalse(has_notes_tab(self.user, self.course))
|
||||
assert not has_notes_tab(self.user, self.course)
|
||||
|
||||
# reenable course.edxnotes
|
||||
self.course.edxnotes = True
|
||||
self.assertTrue(has_notes_tab(self.user, self.course))
|
||||
assert has_notes_tab(self.user, self.course)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@@ -1030,7 +1027,10 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
# pylint: disable=unused-argument
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", return_value={'results': []})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_course_position", return_value={'display_name': 'Section 1', 'url': 'test_url'}) # lint-amnesty, pylint: disable=line-too-long
|
||||
@patch("lms.djangoapps.edxnotes.views.get_course_position", return_value={
|
||||
'display_name': 'Section 1',
|
||||
'url': 'test_url'
|
||||
})
|
||||
def test_edxnotes_html_tags_should_not_be_escaped(self, mock_get_notes, mock_position):
|
||||
"""
|
||||
Tests that explicit html tags rendered correctly.
|
||||
@@ -1048,7 +1048,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
Tests that 404 status code is received if EdxNotes feature is disabled.
|
||||
"""
|
||||
response = self.client.get(self.notes_page_url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
|
||||
@@ -1059,8 +1059,8 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
mock_search.return_value = NOTES_VIEW_EMPTY_RESPONSE
|
||||
enable_edxnotes_for_the_course(self.course, self.user.id)
|
||||
response = self.client.get(self.notes_url, {"text": "test"})
|
||||
self.assertEqual(json.loads(response.content.decode('utf-8')), NOTES_VIEW_EMPTY_RESPONSE)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert json.loads(response.content.decode('utf-8')) == NOTES_VIEW_EMPTY_RESPONSE
|
||||
assert response.status_code == 200
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": False})
|
||||
def test_search_notes_is_disabled(self):
|
||||
@@ -1068,7 +1068,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
Tests that 404 status code is received if EdxNotes feature is disabled.
|
||||
"""
|
||||
response = self.client.get(self.notes_url, {"text": "test"})
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
|
||||
@@ -1099,7 +1099,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
Test generation of ID Token.
|
||||
"""
|
||||
response = self.client.get(self.get_token_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
client = Application.objects.get(name='edx-notes')
|
||||
jwt.decode(response.content, client.client_secret, audience=client.client_id)
|
||||
|
||||
@@ -1110,7 +1110,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
"""
|
||||
self.client.logout()
|
||||
response = self.client.get(self.get_token_url)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
assert response.status_code == 302
|
||||
|
||||
def test_edxnotes_visibility(self):
|
||||
"""
|
||||
@@ -1122,9 +1122,9 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
data=json.dumps({"visibility": False}),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
course_module = self._get_course_module()
|
||||
self.assertFalse(course_module.edxnotes_visibility)
|
||||
assert not course_module.edxnotes_visibility
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": False})
|
||||
def test_edxnotes_visibility_if_feature_is_disabled(self):
|
||||
@@ -1132,7 +1132,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
Tests that 404 response is received if EdxNotes feature is disabled.
|
||||
"""
|
||||
response = self.client.post(self.visibility_url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
def test_edxnotes_visibility_invalid_json(self):
|
||||
@@ -1145,7 +1145,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
data="string",
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
assert response.status_code == 400
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
def test_edxnotes_visibility_key_error(self):
|
||||
@@ -1158,7 +1158,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
data=json.dumps({'test_key': 1}),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
@@ -1213,7 +1213,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
content_type='application/json',
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
assert response.status_code == 204
|
||||
|
||||
def test_retire_user_normal_user_not_allowed(self):
|
||||
"""
|
||||
@@ -1226,7 +1226,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
content_type='application/json',
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
assert response.status_code == 403
|
||||
|
||||
def test_retire_user_status_not_found(self):
|
||||
"""
|
||||
@@ -1239,7 +1239,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
content_type='application/json',
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_retire_user_wrong_state(self):
|
||||
"""
|
||||
@@ -1256,7 +1256,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
content_type='application/json',
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, 405)
|
||||
assert response.status_code == 405
|
||||
|
||||
@patch("lms.djangoapps.edxnotes.helpers.delete_all_notes_for_user", autospec=True)
|
||||
def test_retire_user_downstream_unavailable(self, mock_delete_all_notes_for_user):
|
||||
@@ -1271,7 +1271,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
content_type='application/json',
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, 500)
|
||||
assert response.status_code == 500
|
||||
|
||||
|
||||
@skipUnless(settings.FEATURES["ENABLE_EDXNOTES"], "EdxNotes feature needs to be enabled.")
|
||||
|
||||
@@ -131,8 +131,8 @@ class EmailMarketingTests(TestCase):
|
||||
'cookies': {'anonymous_interest': 'cookie_content'},
|
||||
'id': TEST_EMAIL,
|
||||
'vars': {'last_login_date': ANY}})
|
||||
self.assertTrue('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type
|
||||
self.assertEqual(response.cookies['sailthru_hid'].value, "test_cookie")
|
||||
assert 'sailthru_hid' in response.cookies
|
||||
assert response.cookies['sailthru_hid'].value == 'test_cookie'
|
||||
|
||||
@patch('sailthru.sailthru_client.SailthruClient.api_post')
|
||||
def test_get_cookies_via_sailthu(self, mock_sailthru):
|
||||
@@ -154,7 +154,7 @@ class EmailMarketingTests(TestCase):
|
||||
'id': TEST_EMAIL,
|
||||
'vars': {'last_login_date': ANY}})
|
||||
|
||||
self.assertEqual(cookies['cookie'], expected_cookie.result)
|
||||
assert cookies['cookie'] == expected_cookie.result
|
||||
|
||||
@patch('sailthru.sailthru_client.SailthruClient.api_post')
|
||||
def test_drop_cookie_error_path(self, mock_sailthru):
|
||||
@@ -167,15 +167,15 @@ class EmailMarketingTests(TestCase):
|
||||
})
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': {'cookiexx': 'test_cookie'}}))
|
||||
add_email_marketing_cookies(None, response=response, user=self.user)
|
||||
self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type
|
||||
assert 'sailthru_hid' not in response.cookies
|
||||
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': "error", "errormsg": "errormsg"}))
|
||||
add_email_marketing_cookies(None, response=response, user=self.user)
|
||||
self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type
|
||||
assert 'sailthru_hid' not in response.cookies
|
||||
|
||||
mock_sailthru.side_effect = SailthruClientError
|
||||
add_email_marketing_cookies(None, response=response, user=self.user)
|
||||
self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type
|
||||
assert 'sailthru_hid' not in response.cookies
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@@ -190,15 +190,15 @@ class EmailMarketingTests(TestCase):
|
||||
update_user.delay(
|
||||
{'gender': 'm', 'username': 'test', 'activated': 1}, TEST_EMAIL, site_dict, new_user=True
|
||||
)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
self.assertEqual(mock_sailthru_post.call_args[0][0], "user")
|
||||
assert not mock_log_error.called
|
||||
assert mock_sailthru_post.call_args[0][0] == 'user'
|
||||
userparms = mock_sailthru_post.call_args[0][1]
|
||||
self.assertEqual(userparms['key'], "email")
|
||||
self.assertEqual(userparms['id'], TEST_EMAIL)
|
||||
self.assertEqual(userparms['vars']['gender'], "m")
|
||||
self.assertEqual(userparms['vars']['username'], "test")
|
||||
self.assertEqual(userparms['vars']['activated'], 1)
|
||||
self.assertEqual(userparms['lists']['new list'], 1)
|
||||
assert userparms['key'] == 'email'
|
||||
assert userparms['id'] == TEST_EMAIL
|
||||
assert userparms['vars']['gender'] == 'm'
|
||||
assert userparms['vars']['username'] == 'test'
|
||||
assert userparms['vars']['activated'] == 1
|
||||
assert userparms['lists']['new list'] == 1
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.signals.get_email_cookies_via_sailthru.delay')
|
||||
def test_drop_cookie_task_error(self, mock_email_cookies):
|
||||
@@ -228,7 +228,7 @@ class EmailMarketingTests(TestCase):
|
||||
},
|
||||
email=self.user.email
|
||||
)
|
||||
self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send")
|
||||
assert mock_sailthru_post.call_args[0][0] != 'send'
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_add_user_list_not_called_on_white_label_domain(self, mock_sailthru_post):
|
||||
@@ -240,7 +240,7 @@ class EmailMarketingTests(TestCase):
|
||||
update_user.delay(
|
||||
{'gender': 'm', 'username': 'test', 'activated': 1}, TEST_EMAIL, site=site_dict, new_user=True
|
||||
)
|
||||
self.assertFalse(mock_sailthru_post.called)
|
||||
assert not mock_sailthru_post.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@@ -250,26 +250,26 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))
|
||||
update_user.delay({}, self.user.email)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
# force Sailthru API exception
|
||||
mock_log_error.reset_mock()
|
||||
mock_sailthru.side_effect = SailthruClientError
|
||||
update_user.delay({}, self.user.email)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
# force Sailthru API exception on 2nd call
|
||||
mock_log_error.reset_mock()
|
||||
mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruClientError]
|
||||
update_user.delay({}, self.user.email, activation=True)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
# force Sailthru API error return on 2nd call
|
||||
mock_log_error.reset_mock()
|
||||
mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})),
|
||||
SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))]
|
||||
update_user.delay({}, self.user.email, activation=True)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@@ -280,8 +280,8 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'}))
|
||||
update_user.delay({}, self.user.email)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
self.assertTrue(mock_retry.called)
|
||||
assert mock_log_error.called
|
||||
assert mock_retry.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@@ -292,8 +292,8 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 1, 'errormsg': 'Got an error'}))
|
||||
update_user.delay({}, self.user.email)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
self.assertFalse(mock_retry.called)
|
||||
assert mock_log_error.called
|
||||
assert not mock_retry.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@@ -304,12 +304,12 @@ class EmailMarketingTests(TestCase):
|
||||
update_email_marketing_config(enabled=False)
|
||||
|
||||
update_user.delay(self.user.username, self.user.email)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
self.assertFalse(mock_sailthru.called)
|
||||
assert not mock_log_error.called
|
||||
assert not mock_sailthru.called
|
||||
|
||||
update_user_email.delay(self.user.username, "newemail2@test.com")
|
||||
self.assertFalse(mock_log_error.called)
|
||||
self.assertFalse(mock_sailthru.called)
|
||||
assert not mock_log_error.called
|
||||
assert not mock_sailthru.called
|
||||
|
||||
update_email_marketing_config(enabled=True)
|
||||
|
||||
@@ -321,24 +321,24 @@ class EmailMarketingTests(TestCase):
|
||||
update_email_marketing_config(enabled=False)
|
||||
|
||||
add_email_marketing_cookies(None)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
assert not mock_log_error.called
|
||||
|
||||
email_marketing_register_user(None, None, None)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
assert not mock_log_error.called
|
||||
|
||||
update_email_marketing_config(enabled=True)
|
||||
|
||||
# test anonymous users
|
||||
anon = AnonymousUser()
|
||||
email_marketing_register_user(None, anon, None)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
assert not mock_log_error.called
|
||||
|
||||
email_marketing_user_field_changed(None, user=anon)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
assert not mock_log_error.called
|
||||
|
||||
user = User(username='test', email='test@example.com')
|
||||
email_marketing_user_field_changed(None, user=user)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
assert not mock_log_error.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_change_email(self, mock_sailthru):
|
||||
@@ -347,11 +347,11 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True}))
|
||||
update_user_email.delay(TEST_EMAIL, "old@edx.org")
|
||||
self.assertEqual(mock_sailthru.call_args[0][0], "user")
|
||||
assert mock_sailthru.call_args[0][0] == 'user'
|
||||
userparms = mock_sailthru.call_args[0][1]
|
||||
self.assertEqual(userparms['key'], "email")
|
||||
self.assertEqual(userparms['id'], "old@edx.org")
|
||||
self.assertEqual(userparms['keys']['email'], TEST_EMAIL)
|
||||
assert userparms['key'] == 'email'
|
||||
assert userparms['id'] == 'old@edx.org'
|
||||
assert userparms['keys']['email'] == TEST_EMAIL
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_or_create_sailthru_list(self, mock_sailthru_client):
|
||||
@@ -377,21 +377,19 @@ class EmailMarketingTests(TestCase):
|
||||
# test get error from Sailthru
|
||||
mock_sailthru_client.api_get.return_value = \
|
||||
SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'}))
|
||||
self.assertEqual(_get_or_create_user_list(
|
||||
mock_sailthru_client, 'test1_user_list'), None
|
||||
)
|
||||
assert _get_or_create_user_list(mock_sailthru_client, 'test1_user_list') is None
|
||||
|
||||
# test post error from Sailthru
|
||||
mock_sailthru_client.api_post.return_value = \
|
||||
SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'}))
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
|
||||
self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None)
|
||||
assert _get_or_create_user_list(mock_sailthru_client, 'test2_user_list') is None
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list_map_no_list(self, mock_sailthru_client):
|
||||
"""Test when no list returned from sailthru"""
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
assert _get_list_from_email_marketing_provider(mock_sailthru_client) == {}
|
||||
mock_sailthru_client.api_get.assert_called_with("list", {})
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
@@ -400,35 +398,34 @@ class EmailMarketingTests(TestCase):
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(
|
||||
JsonResponse({'error': 43, 'errormsg': 'Got an error'})
|
||||
)
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
assert _get_list_from_email_marketing_provider(mock_sailthru_client) == {}
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list_map_exception(self, mock_sailthru_client):
|
||||
"""Test when exception raised while fetching data from sailthru"""
|
||||
mock_sailthru_client.api_get.side_effect = SailthruClientError
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
assert _get_list_from_email_marketing_provider(mock_sailthru_client) == {}
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list(self, mock_sailthru_client):
|
||||
"""Test fetch list data from sailthru"""
|
||||
mock_sailthru_client.api_get.return_value = \
|
||||
SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]}))
|
||||
self.assertEqual(
|
||||
_get_list_from_email_marketing_provider(mock_sailthru_client),
|
||||
{'test1_user_list': {'name': 'test1_user_list'}}
|
||||
)
|
||||
assert _get_list_from_email_marketing_provider(mock_sailthru_client) == {
|
||||
'test1_user_list': {'name': 'test1_user_list'}
|
||||
}
|
||||
mock_sailthru_client.api_get.assert_called_with("list", {})
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list(self, mock_sailthru_client):
|
||||
"""Test create list in sailthru"""
|
||||
mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True}))
|
||||
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), True)
|
||||
self.assertEqual(mock_sailthru_client.api_post.call_args[0][0], "list")
|
||||
assert _create_user_list(mock_sailthru_client, 'test_list_name') is True
|
||||
assert mock_sailthru_client.api_post.call_args[0][0] == 'list'
|
||||
listparms = mock_sailthru_client.api_post.call_args[0][1]
|
||||
self.assertEqual(listparms['list'], 'test_list_name')
|
||||
self.assertEqual(listparms['primary'], 0)
|
||||
self.assertEqual(listparms['public_name'], 'test_list_name')
|
||||
assert listparms['list'] == 'test_list_name'
|
||||
assert listparms['primary'] == 0
|
||||
assert listparms['public_name'] == 'test_list_name'
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list_error(self, mock_sailthru_client):
|
||||
@@ -436,13 +433,13 @@ class EmailMarketingTests(TestCase):
|
||||
mock_sailthru_client.api_post.return_value = SailthruResponse(
|
||||
JsonResponse({'error': 43, 'errormsg': 'Got an error'})
|
||||
)
|
||||
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
|
||||
assert _create_user_list(mock_sailthru_client, 'test_list_name') is False
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list_exception(self, mock_sailthru_client):
|
||||
"""Test exception raised while creating sailthru list"""
|
||||
mock_sailthru_client.api_post.side_effect = SailthruClientError
|
||||
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
|
||||
assert _create_user_list(mock_sailthru_client, 'test_list_name') is False
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@@ -452,11 +449,11 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))
|
||||
update_user_email.delay(self.user.username, "newemail2@test.com")
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
mock_sailthru.side_effect = SailthruClientError
|
||||
update_user_email.delay(self.user.username, "newemail2@test.com")
|
||||
self.assertTrue(mock_log_error.called)
|
||||
assert mock_log_error.called
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
@@ -466,9 +463,9 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_get_current_request.return_value = self.request
|
||||
email_marketing_register_user(None, user=self.user, registration=self.registration)
|
||||
self.assertTrue(mock_update_user.called)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key)
|
||||
self.assertLessEqual(mock_update_user.call_args[0][0]['signupNumber'], 9)
|
||||
assert mock_update_user.called
|
||||
assert mock_update_user.call_args[0][0]['activation_key'] == self.registration.activation_key
|
||||
assert mock_update_user.call_args[0][0]['signupNumber'] <= 9
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
def test_register_user_no_request(self, mock_update_user):
|
||||
@@ -476,8 +473,8 @@ class EmailMarketingTests(TestCase):
|
||||
make sure register user call invokes update_user and includes activation_key
|
||||
"""
|
||||
email_marketing_register_user(None, user=self.user, registration=self.registration)
|
||||
self.assertTrue(mock_update_user.called)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key)
|
||||
assert mock_update_user.called
|
||||
assert mock_update_user.call_args[0][0]['activation_key'] == self.registration.activation_key
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
def test_register_user_language_preference(self, mock_update_user):
|
||||
@@ -485,14 +482,14 @@ class EmailMarketingTests(TestCase):
|
||||
make sure register user call invokes update_user and includes language preference
|
||||
"""
|
||||
# If the user hasn't set an explicit language preference, we should send the application's default.
|
||||
self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY))
|
||||
assert self.user.preferences.model.get_value(self.user, LANGUAGE_KEY) is None
|
||||
email_marketing_register_user(None, user=self.user, registration=self.registration)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE)
|
||||
assert mock_update_user.call_args[0][0]['ui_lang'] == settings.LANGUAGE_CODE
|
||||
|
||||
# If the user has set an explicit language preference, we should send it.
|
||||
self.user.preferences.create(key=LANGUAGE_KEY, value='es-419')
|
||||
email_marketing_register_user(None, user=self.user, registration=self.registration)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419')
|
||||
assert mock_update_user.call_args[0][0]['ui_lang'] == 'es-419'
|
||||
|
||||
@patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@@ -508,7 +505,7 @@ class EmailMarketingTests(TestCase):
|
||||
"""
|
||||
mock_get_current_request.return_value = self.request
|
||||
email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value)
|
||||
self.assertEqual(mock_update_user.called, result)
|
||||
assert mock_update_user.called == result
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline')
|
||||
@@ -526,9 +523,9 @@ class EmailMarketingTests(TestCase):
|
||||
mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True}))
|
||||
email_marketing_user_field_changed(None, self.user, table='auth_user', setting='is_active', new_value=True)
|
||||
if send_welcome_email:
|
||||
self.assertEqual(mock_sailthru_post.call_args[0][0], "send")
|
||||
assert mock_sailthru_post.call_args[0][0] == 'send'
|
||||
else:
|
||||
self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send")
|
||||
assert mock_sailthru_post.call_args[0][0] != 'send'
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
def test_modify_language_preference(self, mock_update_user):
|
||||
@@ -536,18 +533,18 @@ class EmailMarketingTests(TestCase):
|
||||
Test that update_user is called with new language preference
|
||||
"""
|
||||
# If the user hasn't set an explicit language preference, we should send the application's default.
|
||||
self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY))
|
||||
assert self.user.preferences.model.get_value(self.user, LANGUAGE_KEY) is None
|
||||
email_marketing_user_field_changed(
|
||||
None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value=None
|
||||
)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE)
|
||||
assert mock_update_user.call_args[0][0]['ui_lang'] == settings.LANGUAGE_CODE
|
||||
|
||||
# If the user has set an explicit language preference, we should send it.
|
||||
self.user.preferences.create(key=LANGUAGE_KEY, value='fr')
|
||||
email_marketing_user_field_changed(
|
||||
None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value='fr'
|
||||
)
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'fr')
|
||||
assert mock_update_user.call_args[0][0]['ui_lang'] == 'fr'
|
||||
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user_email.delay')
|
||||
def test_modify_email(self, mock_update_user):
|
||||
@@ -561,7 +558,7 @@ class EmailMarketingTests(TestCase):
|
||||
mock_update_user.reset_mock()
|
||||
update_email_marketing_config(enabled=False)
|
||||
email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='new@a.com')
|
||||
self.assertFalse(mock_update_user.called)
|
||||
assert not mock_update_user.called
|
||||
|
||||
|
||||
class MockSailthruResponse(object):
|
||||
@@ -640,15 +637,15 @@ class SailthruTests(TestCase):
|
||||
with patch('lms.djangoapps.email_marketing.signals._get_current_site') as mock_site_info:
|
||||
mock_site_info.return_value = site_dict
|
||||
update_sailthru(None, self.user, 'audit', str(self.course_id))
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
self.assertFalse(mock_sailthru_api_post.called)
|
||||
self.assertFalse(mock_sailthru_api_get.called)
|
||||
assert not mock_sailthru_purchase.called
|
||||
assert not mock_sailthru_api_post.called
|
||||
assert not mock_sailthru_api_get.called
|
||||
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
def test_switch_is_disabled(self, mock_sailthru_purchase):
|
||||
"""Make sure sailthru purchase is not called when waffle switch is disabled"""
|
||||
update_sailthru(None, self.user, 'verified', self.course_id)
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
assert not mock_sailthru_purchase.called
|
||||
|
||||
@patch('edx_toggles.toggles.LegacyWaffleSwitchNamespace.is_enabled')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
@@ -658,7 +655,7 @@ class SailthruTests(TestCase):
|
||||
"""
|
||||
switch.return_value = True
|
||||
update_sailthru(None, self.user, 'verified', self.course_id)
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
assert not mock_sailthru_purchase.called
|
||||
|
||||
@patch('edx_toggles.toggles.LegacyWaffleSwitchNamespace.is_enabled')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
@@ -669,4 +666,4 @@ class SailthruTests(TestCase):
|
||||
switch.return_value = True
|
||||
self.user.email = u'tèst@edx.org'
|
||||
update_sailthru(None, self.user, 'audit', str(self.course_id))
|
||||
self.assertTrue(mock_sailthru_purchase.called)
|
||||
assert mock_sailthru_purchase.called
|
||||
|
||||
@@ -53,14 +53,14 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
return self.flag.get_bucket(course_key=self.key, track=track)
|
||||
|
||||
def test_basic_happy_path(self):
|
||||
self.assertEqual(self.get_bucket(), 1)
|
||||
assert self.get_bucket() == 1
|
||||
|
||||
def test_no_request(self):
|
||||
set_current_request(None)
|
||||
self.assertEqual(self.get_bucket(), 0)
|
||||
assert self.get_bucket() == 0
|
||||
|
||||
def test_not_enabled(self):
|
||||
self.assertEqual(self.get_bucket(active=False), 0)
|
||||
assert self.get_bucket(active=False) == 0
|
||||
|
||||
@ddt.data(
|
||||
('2012-01-06', None, 1), # no enrollment, but start is in past (we allow normal bucketing in this case)
|
||||
@@ -78,7 +78,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
enrollment.save()
|
||||
if experiment_start:
|
||||
ExperimentKeyValueFactory(experiment_id=0, key='enrollment_start', value=experiment_start)
|
||||
self.assertEqual(self.get_bucket(), expected_bucket)
|
||||
assert self.get_bucket() == expected_bucket
|
||||
|
||||
@ddt.data(
|
||||
('2012-01-06', None, 0), # no enrollment, but end is in past (we give bucket 0 in that case)
|
||||
@@ -96,7 +96,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
enrollment.save()
|
||||
if experiment_end:
|
||||
ExperimentKeyValueFactory(experiment_id=0, key='enrollment_end', value=experiment_end)
|
||||
self.assertEqual(self.get_bucket(), expected_bucket)
|
||||
assert self.get_bucket() == expected_bucket
|
||||
|
||||
@ddt.data(
|
||||
(True, 0),
|
||||
@@ -106,18 +106,18 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
def test_forcing_bucket(self, active, expected_bucket):
|
||||
bucket_flag = CourseWaffleFlag('experiments', 'test.0', __name__)
|
||||
with override_waffle_flag(bucket_flag, active=active):
|
||||
self.assertEqual(self.get_bucket(), expected_bucket)
|
||||
assert self.get_bucket() == expected_bucket
|
||||
|
||||
def test_tracking(self):
|
||||
# Run twice, with same request
|
||||
with patch('lms.djangoapps.experiments.flags.segment') as segment_mock:
|
||||
self.assertEqual(self.get_bucket(track=True), 1)
|
||||
assert self.get_bucket(track=True) == 1
|
||||
RequestCache.clear_all_namespaces() # we want to force get_bucket to check session, not early exit
|
||||
self.assertEqual(self.get_bucket(track=True), 1)
|
||||
assert self.get_bucket(track=True) == 1
|
||||
|
||||
# Now test that we only sent the signal once, and with the correct properties
|
||||
self.assertEqual(segment_mock.track.call_count, 1)
|
||||
self.assertEqual(segment_mock.track.call_args, ((), {
|
||||
assert segment_mock.track.call_count == 1
|
||||
assert segment_mock.track.call_args == ((), {
|
||||
'user_id': self.user.id,
|
||||
'event_name': 'edx.bi.experiment.user.bucketed',
|
||||
'properties': {
|
||||
@@ -127,21 +127,22 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
'bucket': 1,
|
||||
'course_id': 'a/b/c',
|
||||
'is_staff': self.user.is_staff,
|
||||
'nonInteraction': 1,
|
||||
},
|
||||
}))
|
||||
'nonInteraction': 1
|
||||
}
|
||||
})
|
||||
|
||||
def test_caching(self):
|
||||
self.assertEqual(self.get_bucket(active=True), 1)
|
||||
self.assertEqual(self.get_bucket(active=False), 1) # still returns 1!
|
||||
assert self.get_bucket(active=True) == 1
|
||||
assert self.get_bucket(active=False) == 1
|
||||
# still returns 1!
|
||||
|
||||
def test_is_enabled(self):
|
||||
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=1):
|
||||
self.assertEqual(self.flag.is_enabled(self.key), True)
|
||||
self.assertEqual(self.flag.is_enabled(), True)
|
||||
assert self.flag.is_enabled(self.key) is True
|
||||
assert self.flag.is_enabled() is True
|
||||
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=0):
|
||||
self.assertEqual(self.flag.is_enabled(self.key), False)
|
||||
self.assertEqual(self.flag.is_enabled(), False)
|
||||
assert self.flag.is_enabled(self.key) is False
|
||||
assert self.flag.is_enabled() is False
|
||||
|
||||
@ddt.data(
|
||||
(True, 1, 1),
|
||||
@@ -153,17 +154,17 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
# Test the override method
|
||||
def test_override_method(self, active, bucket_override, expected_bucket):
|
||||
with override_experiment_waffle_flag(self.flag, active=active, bucket=bucket_override):
|
||||
self.assertEqual(self.flag.get_bucket(), expected_bucket)
|
||||
self.assertEqual(self.flag.is_experiment_on(), active)
|
||||
assert self.flag.get_bucket() == expected_bucket
|
||||
assert self.flag.is_experiment_on() == active
|
||||
|
||||
def test_app_label_experiment_name(self):
|
||||
# pylint: disable=protected-access
|
||||
self.assertEqual("experiments", self.flag._app_label)
|
||||
self.assertEqual("test", self.flag._experiment_name)
|
||||
assert 'experiments' == self.flag._app_label
|
||||
assert 'test' == self.flag._experiment_name
|
||||
|
||||
flag = ExperimentWaffleFlag("namespace", "flag.name", __name__)
|
||||
self.assertEqual("namespace", flag._app_label)
|
||||
self.assertEqual("flag.name", flag._experiment_name)
|
||||
assert 'namespace' == flag._app_label
|
||||
assert 'flag.name' == flag._experiment_name
|
||||
|
||||
|
||||
class ExperimentWaffleFlagCourseAwarenessTest(SharedModuleStoreTestCase):
|
||||
|
||||
@@ -46,23 +46,23 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
'key': 'course-v1:DelftX+NGIx+RA0',
|
||||
}
|
||||
enrollment_ids = {CourseKey.from_string('course-v1:DelftX+NGIx+RA0')}
|
||||
self.assertTrue(is_enrolled_in_course_run(course_run, enrollment_ids))
|
||||
assert is_enrolled_in_course_run(course_run, enrollment_ids)
|
||||
|
||||
def test_invalid_course_run_key_enrollment(self):
|
||||
course_run = {
|
||||
'key': 'cr_key',
|
||||
}
|
||||
enrollment_ids = {CourseKey.from_string('course-v1:DelftX+NGIx+RA0')}
|
||||
self.assertFalse(is_enrolled_in_course_run(course_run, enrollment_ids))
|
||||
assert not is_enrolled_in_course_run(course_run, enrollment_ids)
|
||||
|
||||
def test_program_price_and_skus_for_empty_courses(self):
|
||||
price, skus = get_program_price_and_skus([])
|
||||
self.assertEqual(None, price)
|
||||
self.assertEqual(None, skus)
|
||||
assert price is None
|
||||
assert skus is None
|
||||
|
||||
def test_unenrolled_courses_for_empty_courses(self):
|
||||
unenrolled_courses = get_unenrolled_courses([], [])
|
||||
self.assertEqual([], unenrolled_courses)
|
||||
assert [] == unenrolled_courses
|
||||
|
||||
def test_unenrolled_courses_for_single_course(self):
|
||||
course = {'key': 'UQx+ENGY1x'}
|
||||
@@ -71,22 +71,22 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
|
||||
unenrolled_courses = get_unenrolled_courses(courses_in_program, user_enrollments)
|
||||
expected_unenrolled_courses = [course]
|
||||
self.assertEqual(expected_unenrolled_courses, unenrolled_courses)
|
||||
assert expected_unenrolled_courses == unenrolled_courses
|
||||
|
||||
def test_price_and_sku_from_empty_course(self):
|
||||
course = {}
|
||||
|
||||
price, sku = get_course_entitlement_price_and_sku(course)
|
||||
self.assertEqual(None, price)
|
||||
self.assertEqual(None, sku)
|
||||
assert price is None
|
||||
assert sku is None
|
||||
|
||||
def test_price_and_sku_from_entitlement(self):
|
||||
entitlements = [self.entitlement_a]
|
||||
course = {'key': 'UQx+ENGY1x', 'entitlements': entitlements}
|
||||
|
||||
price, sku = get_course_entitlement_price_and_sku(course)
|
||||
self.assertEqual(self.entitlement_a_price, price)
|
||||
self.assertEqual(self.entitlement_a_sku, sku)
|
||||
assert self.entitlement_a_price == price
|
||||
assert self.entitlement_a_sku == sku
|
||||
|
||||
def test_price_and_sku_from_course_run(self):
|
||||
course_runs = [self.course_run_a]
|
||||
@@ -94,8 +94,8 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
|
||||
price, sku = get_course_entitlement_price_and_sku(course)
|
||||
expected_price = Decimal(self.run_a_price)
|
||||
self.assertEqual(expected_price, price)
|
||||
self.assertEqual(self.run_a_sku, sku)
|
||||
assert expected_price == price
|
||||
assert self.run_a_sku == sku
|
||||
|
||||
def test_price_and_sku_from_course(self):
|
||||
entitlements = [self.entitlement_a]
|
||||
@@ -104,9 +104,9 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
|
||||
price, skus = get_program_price_and_skus(courses)
|
||||
expected_price = u'$199.23'
|
||||
self.assertEqual(expected_price, price)
|
||||
self.assertEqual(1, len(skus))
|
||||
self.assertIn(self.entitlement_a_sku, skus)
|
||||
assert expected_price == price
|
||||
assert 1 == len(skus)
|
||||
assert self.entitlement_a_sku in skus
|
||||
|
||||
def test_price_and_sku_from_multiple_courses(self):
|
||||
entitlements = [self.entitlement_a]
|
||||
@@ -117,10 +117,10 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
|
||||
price, skus = get_program_price_and_skus(courses)
|
||||
expected_price = u'$285.23'
|
||||
self.assertEqual(expected_price, price)
|
||||
self.assertEqual(2, len(skus))
|
||||
self.assertIn(self.run_a_sku, skus)
|
||||
self.assertIn(self.entitlement_a_sku, skus)
|
||||
assert expected_price == price
|
||||
assert 2 == len(skus)
|
||||
assert self.run_a_sku in skus
|
||||
assert self.entitlement_a_sku in skus
|
||||
|
||||
def test_get_experiment_user_metadata_context(self):
|
||||
course = CourseFactory.create(start=now() - timedelta(days=30), pacing_type="instructor_paced", course_duration=None, upgrade_price='Free', # lint-amnesty, pylint: disable=line-too-long
|
||||
@@ -155,4 +155,4 @@ class ExperimentUtilsTests(ModuleStoreTestCase, TestCase):
|
||||
|
||||
user_metadata = context.get('user_metadata')
|
||||
|
||||
self.assertTrue(user_metadata, user_metadata_expected_result)
|
||||
assert user_metadata, user_metadata_expected_result
|
||||
|
||||
@@ -39,7 +39,7 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
}
|
||||
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
response = getattr(self.client, method)(url, data)
|
||||
self.assertEqual(response.status_code, status)
|
||||
assert response.status_code == status
|
||||
|
||||
# This will raise an exception if no data exists
|
||||
ExperimentData.objects.get(user=user)
|
||||
@@ -53,15 +53,15 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
user = UserFactory()
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
ExperimentDataFactory()
|
||||
datum = ExperimentDataFactory(user=user)
|
||||
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data['results'], ExperimentDataSerializer([datum], many=True).data)
|
||||
assert response.status_code == 200
|
||||
assert response.data['results'] == ExperimentDataSerializer([datum], many=True).data
|
||||
|
||||
def test_list_filtering(self):
|
||||
""" Users should be able to filter by the experiment_id and key fields. """
|
||||
@@ -76,19 +76,19 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
|
||||
qs = six.moves.urllib.parse.urlencode({'experiment_id': experiment_id})
|
||||
response = self.client.get('{url}?{qs}'.format(url=url, qs=qs))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data['results'], ExperimentDataSerializer(data, many=True).data)
|
||||
assert response.status_code == 200
|
||||
assert response.data['results'] == ExperimentDataSerializer(data, many=True).data
|
||||
|
||||
datum = data[0]
|
||||
qs = six.moves.urllib.parse.urlencode({'key': datum.key})
|
||||
response = self.client.get('{url}?{qs}'.format(url=url, qs=qs))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data['results'], ExperimentDataSerializer([datum], many=True).data)
|
||||
assert response.status_code == 200
|
||||
assert response.data['results'] == ExperimentDataSerializer([datum], many=True).data
|
||||
|
||||
qs = six.moves.urllib.parse.urlencode({'experiment_id': experiment_id, 'key': datum.key})
|
||||
response = self.client.get('{url}?{qs}'.format(url=url, qs=qs))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data['results'], ExperimentDataSerializer([datum], many=True).data)
|
||||
assert response.status_code == 200
|
||||
assert response.data['results'] == ExperimentDataSerializer([datum], many=True).data
|
||||
|
||||
def test_read_permissions(self):
|
||||
""" Users should only be allowed to read their own data. """
|
||||
@@ -97,16 +97,16 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
url = reverse('api_experiments:v0:data-detail', kwargs={'pk': datum.id})
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
other_user = UserFactory()
|
||||
self.client.login(username=other_user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_permissions(self):
|
||||
""" Users should only be allowed to create data for themselves. """
|
||||
@@ -114,7 +114,7 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
|
||||
# Authentication is required
|
||||
response = self.client.post(url, {})
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
user = UserFactory()
|
||||
data = {
|
||||
@@ -126,21 +126,21 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
|
||||
# Users can create data for themselves
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
assert response.status_code == 201
|
||||
ExperimentData.objects.get(user=user)
|
||||
|
||||
# A non-staff user cannot create data for another user
|
||||
other_user = UserFactory()
|
||||
data['user'] = other_user.username
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertFalse(ExperimentData.objects.filter(user=other_user).exists())
|
||||
assert response.status_code == 403
|
||||
assert not ExperimentData.objects.filter(user=other_user).exists()
|
||||
|
||||
# A staff user can create data for other users
|
||||
user.is_staff = True
|
||||
user.save()
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
assert response.status_code == 201
|
||||
ExperimentData.objects.get(user=other_user)
|
||||
|
||||
def test_put_as_create(self):
|
||||
@@ -160,15 +160,15 @@ class ExperimentDataViewSetTests(APITestCase, ModuleStoreTestCase): # lint-amne
|
||||
data = {}
|
||||
|
||||
response = self.client.patch(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
response = self.client.patch(url, data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
self.client.login(username=other_user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
response = self.client.patch(url, data)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def cross_domain_config(func):
|
||||
@@ -214,7 +214,7 @@ class ExperimentCrossDomainTests(APITestCase):
|
||||
|
||||
# Expect that the request gets through successfully,
|
||||
# passing the CSRF checks (including the referer check).
|
||||
self.assertEqual(resp.status_code, 201)
|
||||
assert resp.status_code == 201
|
||||
|
||||
@cross_domain_config
|
||||
def test_cross_domain_invalid_csrf_header(self, *args): # pylint: disable=unused-argument
|
||||
@@ -227,7 +227,7 @@ class ExperimentCrossDomainTests(APITestCase):
|
||||
'value': 'bar',
|
||||
}
|
||||
resp = self._cross_domain_post('invalid_csrf_token', data)
|
||||
self.assertEqual(resp.status_code, 403)
|
||||
assert resp.status_code == 403
|
||||
|
||||
@cross_domain_config
|
||||
def test_cross_domain_not_in_whitelist(self, *args): # pylint: disable=unused-argument
|
||||
@@ -240,14 +240,14 @@ class ExperimentCrossDomainTests(APITestCase):
|
||||
'value': 'bar',
|
||||
}
|
||||
resp = self._cross_domain_post(csrf_cookie, data, referer='www.example.com')
|
||||
self.assertEqual(resp.status_code, 403)
|
||||
assert resp.status_code == 403
|
||||
|
||||
def _get_csrf_cookie(self):
|
||||
"""Retrieve the cross-domain CSRF cookie. """
|
||||
url = reverse('courseenrollments')
|
||||
resp = self.client.get(url, HTTP_REFERER=CROSS_DOMAIN_REFERER)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn(settings.CSRF_COOKIE_NAME, resp.cookies)
|
||||
assert resp.status_code == 200
|
||||
assert settings.CSRF_COOKIE_NAME in resp.cookies
|
||||
return resp.cookies[settings.CSRF_COOKIE_NAME].value
|
||||
|
||||
def _cross_domain_post(self, csrf_token, data, referer=CROSS_DOMAIN_REFERER):
|
||||
@@ -271,28 +271,28 @@ class ExperimentKeyValueViewSetTests(APITestCase): # lint-amnesty, pylint: disa
|
||||
url = reverse('api_experiments:v0:key_value-list')
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = self.client.post(url, {})
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
instance = ExperimentKeyValueFactory()
|
||||
url = reverse('api_experiments:v0:key_value-detail', kwargs={'pk': instance.id})
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
user = UserFactory(is_staff=False)
|
||||
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
response = self.client.put(url, {})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
assert response.status_code == 403
|
||||
|
||||
response = self.client.patch(url, {})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
assert response.status_code == 403
|
||||
|
||||
response = self.client.delete(url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
class ExperimentUserMetaDataViewTests(APITestCase, ModuleStoreTestCase):
|
||||
@@ -306,7 +306,7 @@ class ExperimentUserMetaDataViewTests(APITestCase, ModuleStoreTestCase):
|
||||
self.client.login(username=lookup_user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
response = self.client.get(reverse('api_experiments:user_metadata', args=call_args))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_UserMetaDataView_get_success_staff_user(self):
|
||||
""" Request succeeds when logged-in staff user makes request for different user """
|
||||
@@ -318,11 +318,11 @@ class ExperimentUserMetaDataViewTests(APITestCase, ModuleStoreTestCase):
|
||||
self.client.login(username=staff_user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
response = self.client.get(reverse('api_experiments:user_metadata', args=call_args))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(response.json()['course_id'])
|
||||
self.assertTrue(response.json()['user_id'])
|
||||
self.assertEqual(response.json()['username'], lookup_user.username)
|
||||
self.assertEqual(response.json()['email'], lookup_user.email)
|
||||
assert response.status_code == 200
|
||||
assert response.json()['course_id']
|
||||
assert response.json()['user_id']
|
||||
assert response.json()['username'] == lookup_user.username
|
||||
assert response.json()['email'] == lookup_user.email
|
||||
|
||||
def test_UserMetaDataView_get_different_user(self):
|
||||
""" Request fails when not logged in for requested user or staff """
|
||||
@@ -331,7 +331,7 @@ class ExperimentUserMetaDataViewTests(APITestCase, ModuleStoreTestCase):
|
||||
call_args = [lookup_user.username, lookup_course.id]
|
||||
|
||||
response = self.client.get(reverse('api_experiments:user_metadata', args=call_args))
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_UserMetaDataView_get_missing_course(self):
|
||||
""" Request fails when not course not found """
|
||||
@@ -343,5 +343,5 @@ class ExperimentUserMetaDataViewTests(APITestCase, ModuleStoreTestCase):
|
||||
|
||||
call_args_with_bogus_course = [lookup_user.username, bogus_course_name]
|
||||
response = self.client.get(reverse('api_experiments:user_metadata', args=call_args_with_bogus_course))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.json()['message'], 'Provided course is not found')
|
||||
assert response.status_code == 404
|
||||
assert response.json()['message'] == 'Provided course is not found'
|
||||
|
||||
@@ -29,7 +29,7 @@ class Rev934LoggedOutTests(APITestCase): # lint-amnesty, pylint: disable=missin
|
||||
|
||||
# Not-logged-in returns 401
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
@@ -50,28 +50,28 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=False)
|
||||
def test_flag_off(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': False,
|
||||
}
|
||||
self.assertEqual(response.data, expected)
|
||||
assert response.data == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_no_course_id(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
assert response.status_code == 400
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_bad_course_id(self):
|
||||
response = self.client.get(self.url, {'course_id': 'junk'})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
assert response.status_code == 400
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_simple_course(self):
|
||||
course = CourseFactory.create(start=now() - timedelta(days=30))
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': True,
|
||||
@@ -79,7 +79,7 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
'user_upsell': True,
|
||||
'basket_url': None, # No verified mode means no basket link
|
||||
}
|
||||
self.assertEqual(response.data, expected)
|
||||
assert response.data == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_verified_course(self):
|
||||
@@ -96,17 +96,17 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
result = response.data
|
||||
self.assertIn('basket_url', result)
|
||||
self.assertTrue(bool(result['basket_url']))
|
||||
assert 'basket_url' in result
|
||||
assert bool(result['basket_url'])
|
||||
expected = {
|
||||
'show_upsell': True,
|
||||
'price': u'$10',
|
||||
'basket_url': result['basket_url'],
|
||||
# Example basket_url: u'/verify_student/upgrade/org.0/course_0/test/'
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
assert result == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_expired_verified_mode(self):
|
||||
@@ -124,7 +124,7 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': True,
|
||||
@@ -132,7 +132,7 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
'user_upsell': True,
|
||||
'basket_url': None, # Expired verified mode means no basket link
|
||||
}
|
||||
self.assertEqual(response.data, expected)
|
||||
assert response.data == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_not_started_course(self):
|
||||
@@ -150,13 +150,13 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': True,
|
||||
'course_running': False,
|
||||
}
|
||||
self.assertEqual(response.data, expected)
|
||||
assert response.data == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_ended_course(self):
|
||||
@@ -174,13 +174,13 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': True,
|
||||
'course_running': False,
|
||||
}
|
||||
self.assertEqual(response.data, expected)
|
||||
assert response.data == expected
|
||||
|
||||
@override_waffle_flag(MOBILE_UPSELL_FLAG, active=True)
|
||||
def test_already_upgraded(self):
|
||||
@@ -203,10 +203,10 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
response = self.client.get(self.url, {'course_id': str(course.id)})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
result = response.data
|
||||
self.assertIn('basket_url', result)
|
||||
self.assertTrue(bool(result['basket_url']))
|
||||
assert 'basket_url' in result
|
||||
assert bool(result['basket_url'])
|
||||
expected = {
|
||||
'show_upsell': False,
|
||||
'upsell_flag': True,
|
||||
@@ -215,4 +215,4 @@ class Rev934Tests(APITestCase, ModuleStoreTestCase):
|
||||
'basket_url': result['basket_url'],
|
||||
# Example basket_url: u'/verify_student/upgrade/org.0/course_0/test/'
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
assert result == expected
|
||||
|
||||
@@ -99,7 +99,7 @@ class TestEvaluatePrerequisite(GatingTestCase, MilestonesTestCaseMixin):
|
||||
self.subsection_grade.percent_graded = module_score / 100.0
|
||||
|
||||
evaluate_prerequisite(self.course, self.subsection_grade, self.user)
|
||||
self.assertEqual(milestones_api.user_has_milestone(self.user_dict, self.prereq_milestone), result)
|
||||
assert milestones_api.user_has_milestone(self.user_dict, self.prereq_milestone) == result
|
||||
|
||||
@patch('openedx.core.lib.gating.api.get_subsection_completion_percentage')
|
||||
@patch('openedx.core.lib.gating.api._get_minimum_required_percentage')
|
||||
@@ -112,16 +112,16 @@ class TestEvaluatePrerequisite(GatingTestCase, MilestonesTestCaseMixin):
|
||||
mock_min_score.return_value = 100, 100
|
||||
|
||||
evaluate_prerequisite(self.course, self.subsection_grade, self.user)
|
||||
self.assertEqual(milestones_api.user_has_milestone(self.user_dict, self.prereq_milestone), result)
|
||||
assert milestones_api.user_has_milestone(self.user_dict, self.prereq_milestone) == result
|
||||
|
||||
@patch('openedx.core.lib.gating.api.get_subsection_grade_percentage')
|
||||
def test_no_prerequisites(self, mock_score):
|
||||
evaluate_prerequisite(self.course, self.subsection_grade, self.user)
|
||||
self.assertFalse(mock_score.called)
|
||||
assert not mock_score.called
|
||||
|
||||
@patch('openedx.core.lib.gating.api.get_subsection_grade_percentage')
|
||||
def test_no_gated_content(self, mock_score):
|
||||
gating_api.add_prerequisite(self.course.id, self.seq1.location)
|
||||
|
||||
evaluate_prerequisite(self.course, self.subsection_grade, self.user)
|
||||
self.assertFalse(mock_score.called)
|
||||
assert not mock_score.called
|
||||
|
||||
@@ -146,19 +146,16 @@ class TestGatedContent(MilestonesTestCaseMixin, SharedModuleStoreTestCase):
|
||||
RequestCache.clear_all_namespaces()
|
||||
|
||||
# access to gating content (seq1) remains constant
|
||||
self.assertTrue(bool(has_access(user, 'load', self.seq1, self.course.id)))
|
||||
assert bool(has_access(user, 'load', self.seq1, self.course.id))
|
||||
|
||||
# access to gated content (seq2) remains constant, access is prevented in SeqModule loading
|
||||
self.assertTrue(bool(has_access(user, 'load', self.seq2, self.course.id)))
|
||||
assert bool(has_access(user, 'load', self.seq2, self.course.id))
|
||||
|
||||
def assert_user_has_prereq_milestone(self, user, expected_has_milestone):
|
||||
"""
|
||||
Verifies whether or not the user has the prereq milestone
|
||||
"""
|
||||
self.assertEqual(
|
||||
milestones_api.user_has_milestone({'id': user.id}, self.prereq_milestone),
|
||||
expected_has_milestone,
|
||||
)
|
||||
assert milestones_api.user_has_milestone({'id': user.id}, self.prereq_milestone) == expected_has_milestone
|
||||
|
||||
def assert_course_grade(self, user, expected_percent):
|
||||
"""
|
||||
@@ -169,9 +166,9 @@ class TestGatedContent(MilestonesTestCaseMixin, SharedModuleStoreTestCase):
|
||||
"""
|
||||
course_grade = CourseGradeFactory().read(user, self.course)
|
||||
for prob in [self.gating_prob1, self.gated_prob2, self.prob3]:
|
||||
self.assertIn(prob.location, course_grade.problem_scores)
|
||||
assert prob.location in course_grade.problem_scores
|
||||
|
||||
self.assertEqual(course_grade.percent, expected_percent)
|
||||
assert course_grade.percent == expected_percent
|
||||
|
||||
def test_gated_for_nonstaff(self):
|
||||
self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestHandleScoreChanged(ModuleStoreTestCase):
|
||||
course=self.course,
|
||||
subsection_grade=self.subsection_grade,
|
||||
)
|
||||
self.assertTrue(mock_gating_milestone.called)
|
||||
assert mock_gating_milestone.called
|
||||
|
||||
@patch('lms.djangoapps.gating.api.gating_api.get_gating_milestone')
|
||||
def test_gating_disabled(self, mock_gating_milestone):
|
||||
@@ -43,4 +43,4 @@ class TestHandleScoreChanged(ModuleStoreTestCase):
|
||||
course=self.course,
|
||||
subsection_grade=self.subsection_grade,
|
||||
)
|
||||
self.assertFalse(mock_gating_milestone.called)
|
||||
assert not mock_gating_milestone.called
|
||||
|
||||
@@ -42,15 +42,13 @@ class PersistentGradesFeatureFlagTests(TestCase):
|
||||
course_id=self.course_id_1,
|
||||
enabled_for_course=enabled_for_course_1
|
||||
):
|
||||
self.assertEqual(PersistentGradesEnabledFlag.feature_enabled(), global_flag)
|
||||
self.assertEqual(
|
||||
PersistentGradesEnabledFlag.feature_enabled(self.course_id_1),
|
||||
global_flag and (enabled_for_all_courses or enabled_for_course_1)
|
||||
)
|
||||
self.assertEqual(
|
||||
PersistentGradesEnabledFlag.feature_enabled(self.course_id_2),
|
||||
global_flag and enabled_for_all_courses
|
||||
)
|
||||
assert PersistentGradesEnabledFlag.feature_enabled() == global_flag
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(
|
||||
self.course_id_1
|
||||
) == (global_flag and (enabled_for_all_courses or enabled_for_course_1))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(
|
||||
self.course_id_2
|
||||
) == (global_flag and enabled_for_all_courses)
|
||||
|
||||
def test_enable_disable_course_flag(self):
|
||||
"""
|
||||
@@ -62,7 +60,7 @@ class PersistentGradesFeatureFlagTests(TestCase):
|
||||
course_id=self.course_id_1,
|
||||
enabled_for_course=True
|
||||
):
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course_id_1))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(self.course_id_1)
|
||||
# Prior to TNL-5698, creating a second object would fail due to db constraints
|
||||
with persistent_grades_feature_flags(
|
||||
global_flag=True,
|
||||
@@ -70,7 +68,7 @@ class PersistentGradesFeatureFlagTests(TestCase):
|
||||
course_id=self.course_id_1,
|
||||
enabled_for_course=False
|
||||
):
|
||||
self.assertFalse(PersistentGradesEnabledFlag.feature_enabled(self.course_id_1))
|
||||
assert not PersistentGradesEnabledFlag.feature_enabled(self.course_id_1)
|
||||
|
||||
def test_enable_disable_globally(self):
|
||||
"""
|
||||
@@ -80,16 +78,16 @@ class PersistentGradesFeatureFlagTests(TestCase):
|
||||
global_flag=True,
|
||||
enabled_for_all_courses=True,
|
||||
):
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled())
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course_id_1))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled()
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(self.course_id_1)
|
||||
with persistent_grades_feature_flags(
|
||||
global_flag=True,
|
||||
enabled_for_all_courses=False,
|
||||
):
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled())
|
||||
self.assertFalse(PersistentGradesEnabledFlag.feature_enabled(self.course_id_1))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled()
|
||||
assert not PersistentGradesEnabledFlag.feature_enabled(self.course_id_1)
|
||||
with persistent_grades_feature_flags(
|
||||
global_flag=False,
|
||||
):
|
||||
self.assertFalse(PersistentGradesEnabledFlag.feature_enabled())
|
||||
self.assertFalse(PersistentGradesEnabledFlag.feature_enabled(self.course_id_1))
|
||||
assert not PersistentGradesEnabledFlag.feature_enabled()
|
||||
assert not PersistentGradesEnabledFlag.feature_enabled(self.course_id_1)
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests for compute_grades management command.
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
import six
|
||||
from six.moves import range
|
||||
@@ -46,13 +46,10 @@ class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
|
||||
def test_specify_courses(self):
|
||||
courses = self.command._get_course_keys({'courses': [self.course_keys[0], self.course_keys[1], 'd/n/e']})
|
||||
self.assertEqual(
|
||||
[six.text_type(course) for course in courses],
|
||||
[self.course_keys[0], self.course_keys[1], 'd/n/e'],
|
||||
)
|
||||
assert [six.text_type(course) for course in courses] == [self.course_keys[0], self.course_keys[1], 'd/n/e']
|
||||
|
||||
def test_selecting_invalid_course(self):
|
||||
with self.assertRaises(CommandError):
|
||||
with pytest.raises(CommandError):
|
||||
self.command._get_course_keys({'courses': [self.course_keys[0], self.course_keys[1], 'badcoursekey']})
|
||||
|
||||
def test_from_settings(self):
|
||||
@@ -61,7 +58,7 @@ class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
assert set(six.text_type(course) for course in courses) == set(self.course_keys)
|
||||
# test that --from_settings always uses the latest setting
|
||||
ComputeGradesSetting.objects.create(course_ids='badcoursekey')
|
||||
with self.assertRaises(CommandError):
|
||||
with pytest.raises(CommandError):
|
||||
self.command._get_course_keys({'from_settings': True})
|
||||
|
||||
@ddt.data(True, False)
|
||||
|
||||
@@ -6,6 +6,7 @@ Tests for the course grading API view
|
||||
import json
|
||||
from collections import OrderedDict, namedtuple
|
||||
from datetime import datetime
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
from django.urls import reverse
|
||||
@@ -208,32 +209,32 @@ class CourseGradingViewTest(SharedModuleStoreTestCase, APITestCase):
|
||||
def test_student_fails(self):
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(self.course_key))
|
||||
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
assert resp.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
def test_staff_succeeds(self):
|
||||
self.client.login(username=self.staff.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(self.course_key))
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = self._get_expected_data()
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
def test_staff_succeeds_graded_only(self):
|
||||
self.client.login(username=self.staff.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(self.course_key), {'graded_only': True})
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = self._get_expected_data()
|
||||
expected_data['subsections'] = [sub for sub in expected_data['subsections'] if sub['graded']]
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
def test_course_grade_frozen(self):
|
||||
with patch('lms.djangoapps.grades.rest_api.v1.gradebook_views.are_grades_frozen') as mock_frozen_grades:
|
||||
mock_frozen_grades.return_value = True
|
||||
self.client.login(username=self.staff.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(self.course_key))
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = self._get_expected_data()
|
||||
expected_data['grades_frozen'] = True
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
|
||||
class GradebookViewTestBase(GradeViewTestMixin, APITestCase):
|
||||
@@ -500,27 +501,27 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
])
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, response.status_code)
|
||||
assert status.HTTP_200_OK == response.status_code
|
||||
actual_data = dict(response.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
# assert that the hidden subsection data is not represented in the response
|
||||
for actual_user_data in actual_data['results']:
|
||||
actual_subsection_display_names = [
|
||||
item['subsection_name'] for item in actual_user_data['section_breakdown']
|
||||
]
|
||||
self.assertNotIn(self.hidden_subsection.display_name, actual_subsection_display_names)
|
||||
assert self.hidden_subsection.display_name not in actual_subsection_display_names
|
||||
|
||||
def _assert_empty_response(self, response):
|
||||
"""
|
||||
Helper method for assertions about OK, empty responses.
|
||||
"""
|
||||
self.assertEqual(status.HTTP_200_OK, response.status_code)
|
||||
assert status.HTTP_200_OK == response.status_code
|
||||
actual_data = dict(response.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual([], actual_data['results'])
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert [] == actual_data['results']
|
||||
|
||||
def test_feature_not_enabled(self):
|
||||
self.client.login(username=self.global_staff.username, password=self.password)
|
||||
@@ -528,18 +529,18 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key=self.empty_course.id)
|
||||
)
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
def test_anonymous(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
resp = self.client.get(self.get_url())
|
||||
self.assertEqual(status.HTTP_401_UNAUTHORIZED, resp.status_code)
|
||||
assert status.HTTP_401_UNAUTHORIZED == resp.status_code
|
||||
|
||||
def test_student(self):
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
resp = self.client.get(self.get_url())
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
def test_course_does_not_exist(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
@@ -547,7 +548,7 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key='course-v1:MITx+8.MechCX+2014_T1')
|
||||
)
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
def test_user_does_not_exist(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
@@ -555,7 +556,7 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key=self.course.id, username='not-a-real-user')
|
||||
)
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
def test_user_not_enrolled(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
@@ -563,7 +564,7 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key=self.empty_course.id, username=self.student.username)
|
||||
)
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
def test_course_no_enrollments(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
@@ -615,14 +616,14 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
('section_breakdown', self.expected_subsection_grades()),
|
||||
])
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data)
|
||||
assert expected_results == actual_data
|
||||
# assert that the hidden subsection data is not represented in the response
|
||||
actual_subsection_display_names = [
|
||||
item['subsection_name'] for item in actual_data['section_breakdown']
|
||||
]
|
||||
self.assertNotIn(self.hidden_subsection.display_name, actual_subsection_display_names)
|
||||
assert self.hidden_subsection.display_name not in actual_subsection_display_names
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -698,9 +699,9 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
('section_breakdown', self.expected_subsection_grades()),
|
||||
])
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data)
|
||||
assert expected_results == actual_data
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -740,14 +741,14 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 2)
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 2
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -788,14 +789,14 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 2)
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 2
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -826,14 +827,14 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 1)
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 1
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -874,13 +875,13 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 2)
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 2
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -930,13 +931,13 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertIsNone(actual_data['next'])
|
||||
self.assertIsNone(actual_data['previous'])
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 1)
|
||||
assert actual_data['next'] is None
|
||||
assert actual_data['previous'] is None
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 1
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -986,8 +987,8 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
self._assert_data_all_users(resp)
|
||||
actual_data = dict(resp.data)
|
||||
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], num_filtered_enrollments)
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == num_filtered_enrollments
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1031,12 +1032,12 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key=self.course.id) + query
|
||||
)
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
expected_page_size = page_size or CourseEnrollmentPagination.page_size
|
||||
if expected_page_size > user_size:
|
||||
expected_page_size = user_size
|
||||
self.assertEqual(len(actual_data['results']), expected_page_size)
|
||||
assert len(actual_data['results']) == expected_page_size
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -1093,11 +1094,11 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
])
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 2)
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 2
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -1146,11 +1147,11 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
]),
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], 1)
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == 1
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -1210,11 +1211,11 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
])
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], num_enrollments)
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == num_enrollments
|
||||
|
||||
@ddt.data(
|
||||
['login_staff', 4],
|
||||
@@ -1274,11 +1275,11 @@ class GradebookViewTest(GradebookViewTestBase):
|
||||
])
|
||||
]
|
||||
|
||||
self.assertEqual(status.HTTP_200_OK, resp.status_code)
|
||||
assert status.HTTP_200_OK == resp.status_code
|
||||
actual_data = dict(resp.data)
|
||||
self.assertEqual(expected_results, actual_data['results'])
|
||||
self.assertEqual(actual_data['total_users_count'], num_enrollments)
|
||||
self.assertEqual(actual_data['filtered_users_count'], num_enrollments)
|
||||
assert expected_results == actual_data['results']
|
||||
assert actual_data['total_users_count'] == num_enrollments
|
||||
assert actual_data['filtered_users_count'] == num_enrollments
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -1297,18 +1298,18 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
resp = self.client.post(
|
||||
self.get_url(course_key=self.empty_course.id)
|
||||
)
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
def test_anonymous(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
resp = self.client.post(self.get_url())
|
||||
self.assertEqual(status.HTTP_401_UNAUTHORIZED, resp.status_code)
|
||||
assert status.HTTP_401_UNAUTHORIZED == resp.status_code
|
||||
|
||||
def test_student(self):
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
resp = self.client.post(self.get_url())
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
def test_course_does_not_exist(self):
|
||||
with override_waffle_flag(self.waffle_flag, active=True):
|
||||
@@ -1316,7 +1317,7 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
resp = self.client.post(
|
||||
self.get_url(course_key='course-v1:MITx+8.MechCX+2014_T1')
|
||||
)
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1343,7 +1344,7 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
data=json.dumps(post_data),
|
||||
content_type='application/json',
|
||||
)
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1376,8 +1377,8 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
'reason': 'CourseEnrollment matching query does not exist.',
|
||||
},
|
||||
]
|
||||
self.assertEqual(status.HTTP_422_UNPROCESSABLE_ENTITY, resp.status_code)
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert status.HTTP_422_UNPROCESSABLE_ENTITY == resp.status_code
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1409,8 +1410,8 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
'reason': 'User matching query does not exist.',
|
||||
},
|
||||
]
|
||||
self.assertEqual(status.HTTP_422_UNPROCESSABLE_ENTITY, resp.status_code)
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert status.HTTP_422_UNPROCESSABLE_ENTITY == resp.status_code
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1442,8 +1443,8 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
'reason': "<class 'opaque_keys.edx.locator.BlockUsageLocator'>: not-a-valid-usage-key",
|
||||
},
|
||||
]
|
||||
self.assertEqual(status.HTTP_422_UNPROCESSABLE_ENTITY, resp.status_code)
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert status.HTTP_422_UNPROCESSABLE_ENTITY == resp.status_code
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1480,8 +1481,8 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
'reason': 'usage_key {} does not exist in this course.'.format(usage_id),
|
||||
},
|
||||
]
|
||||
self.assertEqual(status.HTTP_422_UNPROCESSABLE_ENTITY, resp.status_code)
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert status.HTTP_422_UNPROCESSABLE_ENTITY == resp.status_code
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data('login_staff', 'login_course_staff', 'login_course_admin')
|
||||
def test_override_is_created(self, login_method):
|
||||
@@ -1534,8 +1535,8 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
'reason': None,
|
||||
},
|
||||
]
|
||||
self.assertEqual(status.HTTP_202_ACCEPTED, resp.status_code)
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert status.HTTP_202_ACCEPTED == resp.status_code
|
||||
assert expected_data == resp.data
|
||||
|
||||
second_post_data = [
|
||||
{
|
||||
@@ -1581,10 +1582,10 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
)
|
||||
for field_name in expected_grade_overrides._fields:
|
||||
expected_value = getattr(expected_grade_overrides, field_name)
|
||||
self.assertEqual(expected_value, getattr(grade.override, field_name + '_override'))
|
||||
assert expected_value == getattr(grade.override, (field_name + '_override'))
|
||||
for field_name in expected_grades._fields:
|
||||
expected_value = getattr(expected_grades, field_name)
|
||||
self.assertEqual(expected_value, getattr(grade, field_name))
|
||||
assert expected_value == getattr(grade, field_name)
|
||||
|
||||
def test_update_failing_grade(self):
|
||||
"""
|
||||
@@ -1624,9 +1625,9 @@ class GradebookBulkUpdateViewTest(GradebookViewTestBase):
|
||||
data=json.dumps(post_data),
|
||||
content_type='application/json',
|
||||
)
|
||||
self.assertEqual(status.HTTP_202_ACCEPTED, resp.status_code)
|
||||
assert status.HTTP_202_ACCEPTED == resp.status_code
|
||||
cert = GeneratedCertificate.certificate_for_student(self.student, self.course.id)
|
||||
self.assertEqual(cert.status, CertificateStatuses.notpassing)
|
||||
assert cert.status == CertificateStatuses.notpassing
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -1700,7 +1701,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
graded_total=graded_total_mock
|
||||
)
|
||||
mocked_factory.return_value = mock_return_value
|
||||
with self.assertRaises(PersistentSubsectionGrade.DoesNotExist):
|
||||
with pytest.raises(PersistentSubsectionGrade.DoesNotExist):
|
||||
PersistentSubsectionGrade.objects.get(
|
||||
user_id=user_no_grade.id,
|
||||
course_id=self.usage_key.course_key,
|
||||
@@ -1725,7 +1726,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
'subsection_id': text_type(self.usage_key),
|
||||
'history': []
|
||||
}
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1754,7 +1755,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
'history': []
|
||||
}
|
||||
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1903,7 +1904,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
self.get_url(subsection_id='notAValidSubectionId')
|
||||
)
|
||||
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1915,7 +1916,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
self.get_url(subsection_id=self.usage_key, user_id='notAnIntegerUserId')
|
||||
)
|
||||
|
||||
self.assertEqual(status.HTTP_404_NOT_FOUND, resp.status_code)
|
||||
assert status.HTTP_404_NOT_FOUND == resp.status_code
|
||||
|
||||
@ddt.data(
|
||||
'login_staff',
|
||||
@@ -1952,7 +1953,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
'history': []
|
||||
}
|
||||
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
def test_with_unauthorized_user(self):
|
||||
student = UserFactory(username='dummy', password='test')
|
||||
@@ -1962,7 +1963,7 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
self.get_url(subsection_id=self.usage_key)
|
||||
)
|
||||
|
||||
self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
|
||||
assert status.HTTP_403_FORBIDDEN == resp.status_code
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
def test_get_override_for_unreleased_block(self):
|
||||
@@ -1994,4 +1995,4 @@ class SubsectionGradeViewTest(GradebookViewTestBase):
|
||||
'subsection_id': text_type(unreleased_subsection.location),
|
||||
'history': []
|
||||
}
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
@@ -95,7 +95,7 @@ class GradingPolicyTestMixin(object):
|
||||
reverse(self.view_name, kwargs={'course_id': course_id or self.course_id}),
|
||||
**headers
|
||||
)
|
||||
self.assertEqual(response.status_code, expected_status_code)
|
||||
assert response.status_code == expected_status_code
|
||||
return response
|
||||
|
||||
def get_auth_header(self, user):
|
||||
|
||||
@@ -52,7 +52,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
'course_id': str(self.course_key),
|
||||
'passed': False
|
||||
}]
|
||||
self.assertEqual(response.data, expected_data)
|
||||
assert response.data == expected_data
|
||||
|
||||
def test_nonexistent_user(self):
|
||||
"""
|
||||
@@ -60,7 +60,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
"""
|
||||
self.client.login(username=self.global_staff.username, password=self.password)
|
||||
resp = self.client.get(self.get_url('IDoNotExist'))
|
||||
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
|
||||
assert resp.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
def test_self_get_grade_not_enrolled(self):
|
||||
"""
|
||||
@@ -71,12 +71,9 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
unenrolled_user = UserFactory(password=self.password)
|
||||
self.client.login(username=unenrolled_user.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(unenrolled_user.username))
|
||||
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertIn('error_code', resp.data)
|
||||
self.assertEqual(
|
||||
resp.data['error_code'],
|
||||
'user_not_enrolled'
|
||||
)
|
||||
assert resp.status_code == status.HTTP_404_NOT_FOUND
|
||||
assert 'error_code' in resp.data
|
||||
assert resp.data['error_code'] == 'user_not_enrolled'
|
||||
|
||||
def test_no_grade(self):
|
||||
"""
|
||||
@@ -84,7 +81,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
"""
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
resp = self.client.get(self.get_url(self.student.username))
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = [{
|
||||
'username': self.student.username,
|
||||
'email': '',
|
||||
@@ -94,7 +91,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
'letter_grade': None
|
||||
}]
|
||||
|
||||
self.assertEqual(resp.data, expected_data)
|
||||
assert resp.data == expected_data
|
||||
|
||||
def test_wrong_course_key(self):
|
||||
"""
|
||||
@@ -108,12 +105,9 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
with patch('opaque_keys.edx.keys.CourseKey.from_string', side_effect=mock_from_string):
|
||||
resp = self.client.get(self.get_url(self.student.username))
|
||||
|
||||
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertIn('error_code', resp.data)
|
||||
self.assertEqual(
|
||||
resp.data['error_code'],
|
||||
'invalid_course_key'
|
||||
)
|
||||
assert resp.status_code == status.HTTP_404_NOT_FOUND
|
||||
assert 'error_code' in resp.data
|
||||
assert resp.data['error_code'] == 'invalid_course_key'
|
||||
|
||||
def test_course_does_not_exist(self):
|
||||
"""
|
||||
@@ -128,12 +122,9 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
)
|
||||
url = "{0}?username={1}".format(base_url, self.student.username)
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertIn('error_code', resp.data)
|
||||
self.assertEqual(
|
||||
resp.data['error_code'],
|
||||
'course_does_not_exist'
|
||||
)
|
||||
assert resp.status_code == status.HTTP_404_NOT_FOUND
|
||||
assert 'error_code' in resp.data
|
||||
assert resp.data['error_code'] == 'course_does_not_exist'
|
||||
|
||||
@ddt.data(
|
||||
({'letter_grade': None, 'percent': 0.4, 'passed': False}),
|
||||
@@ -154,7 +145,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
mock_grade.return_value = MagicMock(**grade_fields)
|
||||
resp = self.client.get(self.get_url(self.student.username))
|
||||
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = {
|
||||
'username': self.student.username,
|
||||
'email': '',
|
||||
@@ -162,7 +153,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC
|
||||
}
|
||||
|
||||
expected_data.update(grade)
|
||||
self.assertEqual(resp.data, [expected_data])
|
||||
assert resp.data == [expected_data]
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -193,39 +184,39 @@ class CourseGradesViewTest(GradeViewTestMixin, APITestCase):
|
||||
|
||||
def test_anonymous(self):
|
||||
resp = self.client.get(self.get_url())
|
||||
self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
def test_student(self):
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
resp = self.client.get(self.get_url())
|
||||
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
assert resp.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
def test_course_does_not_exist(self):
|
||||
self.client.login(username=self.global_staff.username, password=self.password)
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key='course-v1:MITx+8.MechCX+2014_T1')
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
|
||||
assert resp.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
def test_course_no_enrollments(self):
|
||||
self.client.login(username=self.global_staff.username, password=self.password)
|
||||
resp = self.client.get(
|
||||
self.get_url(course_key=self.empty_course.id)
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = OrderedDict([
|
||||
('next', None),
|
||||
('previous', None),
|
||||
('results', []),
|
||||
])
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
def test_staff_can_get_all_grades(self):
|
||||
self.client.login(username=self.global_staff.username, password=self.password)
|
||||
resp = self.client.get(self.get_url())
|
||||
|
||||
# this should have permission to access this API endpoint
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
assert resp.status_code == status.HTTP_200_OK
|
||||
expected_data = OrderedDict([
|
||||
('next', None),
|
||||
('previous', None),
|
||||
@@ -265,4 +256,4 @@ class CourseGradesViewTest(GradeViewTestMixin, APITestCase):
|
||||
]),
|
||||
])
|
||||
|
||||
self.assertEqual(expected_data, resp.data)
|
||||
assert expected_data == resp.data
|
||||
|
||||
@@ -91,8 +91,8 @@ class GradesAccessIntegrationTest(ProblemSubmissionTestMixin, SharedModuleStoreT
|
||||
course_structure = get_course_blocks(self.request.user, self.course.location)
|
||||
subsection_grade_factory = SubsectionGradeFactory(self.request.user, self.course, course_structure)
|
||||
grade = subsection_grade_factory.create(self.sequence, read_only=True)
|
||||
self.assertEqual(grade.graded_total.earned, 4.0)
|
||||
self.assertEqual(grade.graded_total.possible, 4.0)
|
||||
assert grade.graded_total.earned == 4.0
|
||||
assert grade.graded_total.possible == 4.0
|
||||
|
||||
# set a block in the subsection to be visible to staff only
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
@@ -103,10 +103,10 @@ class GradesAccessIntegrationTest(ProblemSubmissionTestMixin, SharedModuleStoreT
|
||||
course_structure = get_course_blocks(self.student, self.course.location)
|
||||
|
||||
# ensure that problem_2 is not accessible for the student
|
||||
self.assertNotIn(problem_2.location, course_structure)
|
||||
assert problem_2.location not in course_structure
|
||||
|
||||
# make sure we can still get the subsection grade
|
||||
subsection_grade_factory = SubsectionGradeFactory(self.student, self.course, course_structure)
|
||||
grade = subsection_grade_factory.create(self.sequence, read_only=True)
|
||||
self.assertEqual(grade.graded_total.earned, 4.0)
|
||||
self.assertEqual(grade.graded_total.possible, 4.0)
|
||||
assert grade.graded_total.earned == 4.0
|
||||
assert grade.graded_total.possible == 4.0
|
||||
|
||||
@@ -176,10 +176,7 @@ class GradesEventIntegrationTest(ProblemSubmissionTestMixin, SharedModuleStoreTe
|
||||
|
||||
# make sure the tracker's context is updated with course info
|
||||
for args in events_tracker.get_tracker().context.call_args_list:
|
||||
self.assertEqual(
|
||||
args[0][1],
|
||||
{'course_id': six.text_type(self.course.id), 'org_id': six.text_type(self.course.org)}
|
||||
)
|
||||
assert args[0][1] == {'course_id': six.text_type(self.course.id), 'org_id': six.text_type(self.course.org)}
|
||||
|
||||
event_transaction_id = events_tracker.emit.mock_calls[0][1][1]['event_transaction_id']
|
||||
events_tracker.emit.assert_has_calls(
|
||||
|
||||
@@ -41,7 +41,7 @@ class TestMultipleProblemTypesSubsectionScores(SharedModuleStoreTestCase):
|
||||
cls.seq1 = chapter1.get_children()[0]
|
||||
|
||||
def setUp(self):
|
||||
super(TestMultipleProblemTypesSubsectionScores, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
password = u'test'
|
||||
self.student = UserFactory.create(is_staff=False, username=u'test_student', password=password)
|
||||
self.client.login(username=self.student.username, password=password)
|
||||
@@ -79,8 +79,8 @@ class TestMultipleProblemTypesSubsectionScores(SharedModuleStoreTestCase):
|
||||
)
|
||||
score = subsection_factory.create(self.seq1)
|
||||
|
||||
self.assertEqual(score.all_total.earned, 0.0)
|
||||
self.assertEqual(score.all_total.possible, self.ACTUAL_TOTAL_POSSIBLE)
|
||||
assert score.all_total.earned == 0.0
|
||||
assert score.all_total.possible == self.ACTUAL_TOTAL_POSSIBLE
|
||||
|
||||
# Choose arbitrary, non-default values for earned and possible.
|
||||
earned_per_block = 3.0
|
||||
@@ -93,8 +93,8 @@ class TestMultipleProblemTypesSubsectionScores(SharedModuleStoreTestCase):
|
||||
itertools.repeat(mock_score.return_value)
|
||||
)
|
||||
score = subsection_factory.update(self.seq1)
|
||||
self.assertEqual(score.all_total.earned, earned_per_block * block_count)
|
||||
self.assertEqual(score.all_total.possible, possible_per_block * block_count)
|
||||
assert score.all_total.earned == (earned_per_block * block_count)
|
||||
assert score.all_total.possible == (possible_per_block * block_count)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -191,8 +191,8 @@ class TestVariedMetadata(ProblemSubmissionTestMixin, ModuleStoreTestCase):
|
||||
def test_weight_metadata_alterations(self, alterations, expected_earned, expected_possible):
|
||||
self._add_problem_with_alterations(alterations)
|
||||
score = self._get_score()
|
||||
self.assertEqual(score.all_total.earned, expected_earned)
|
||||
self.assertEqual(score.all_total.possible, expected_possible)
|
||||
assert score.all_total.earned == expected_earned
|
||||
assert score.all_total.possible == expected_possible
|
||||
|
||||
@ddt.data(
|
||||
({u'graded': True}, 1.25, 2.5),
|
||||
@@ -202,8 +202,8 @@ class TestVariedMetadata(ProblemSubmissionTestMixin, ModuleStoreTestCase):
|
||||
def test_graded_metadata_alterations(self, alterations, expected_earned, expected_possible):
|
||||
self._add_problem_with_alterations(alterations)
|
||||
score = self._get_score()
|
||||
self.assertEqual(score.graded_total.earned, expected_earned)
|
||||
self.assertEqual(score.graded_total.possible, expected_possible)
|
||||
assert score.graded_total.earned == expected_earned
|
||||
assert score.graded_total.possible == expected_possible
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -273,13 +273,13 @@ class TestWeightedProblems(SharedModuleStoreTestCase):
|
||||
# verify all problem grades
|
||||
for problem in self.problems:
|
||||
problem_score = subsection_grade.problem_scores[problem.location]
|
||||
self.assertEqual(type(expected_score.first_attempted), type(problem_score.first_attempted))
|
||||
assert isinstance(expected_score.first_attempted, type(problem_score.first_attempted))
|
||||
expected_score.first_attempted = problem_score.first_attempted
|
||||
self.assertEqual(problem_score, expected_score)
|
||||
assert problem_score == expected_score
|
||||
|
||||
# verify subsection grades
|
||||
self.assertEqual(subsection_grade.all_total.earned, expected_score.earned * len(self.problems))
|
||||
self.assertEqual(subsection_grade.all_total.possible, expected_score.possible * len(self.problems))
|
||||
assert subsection_grade.all_total.earned == (expected_score.earned * len(self.problems))
|
||||
assert subsection_grade.all_total.possible == (expected_score.possible * len(self.problems))
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product(
|
||||
|
||||
@@ -75,9 +75,9 @@ class OverrideSubsectionGradeTests(ModuleStoreTestCase):
|
||||
self.course.id,
|
||||
self.subsection.location
|
||||
)
|
||||
self.assertIsNotNone(override_obj)
|
||||
self.assertEqual(override_obj.earned_graded_override, earned_graded)
|
||||
self.assertEqual(override_obj.override_reason, 'Test Override Comment')
|
||||
assert override_obj is not None
|
||||
assert override_obj.earned_graded_override == earned_graded
|
||||
assert override_obj.override_reason == 'Test Override Comment'
|
||||
|
||||
for i in range(3):
|
||||
override_obj.override_reason = 'this field purposefully left blank'
|
||||
@@ -98,15 +98,15 @@ class OverrideSubsectionGradeTests(ModuleStoreTestCase):
|
||||
self.subsection.location
|
||||
)
|
||||
|
||||
self.assertIsNotNone(override_obj)
|
||||
self.assertEqual(override_obj.earned_graded_override, earned_graded)
|
||||
self.assertEqual(override_obj.override_reason, 'Test Override Comment 2')
|
||||
assert override_obj is not None
|
||||
assert override_obj.earned_graded_override == earned_graded
|
||||
assert override_obj.override_reason == 'Test Override Comment 2'
|
||||
|
||||
self.assertEqual(5, len(override_obj.history.all()))
|
||||
assert 5 == len(override_obj.history.all())
|
||||
for history_entry in override_obj.history.all():
|
||||
if history_entry.override_reason.startswith('Test Override Comment'):
|
||||
self.assertEqual(self.overriding_user, history_entry.history_user)
|
||||
self.assertEqual(self.overriding_user.id, history_entry.history_user_id)
|
||||
assert self.overriding_user == history_entry.history_user
|
||||
assert self.overriding_user.id == history_entry.history_user_id
|
||||
else:
|
||||
self.assertIsNone(history_entry.history_user)
|
||||
self.assertIsNone(history_entry.history_user_id)
|
||||
assert history_entry.history_user is None
|
||||
assert history_entry.history_user_id is None
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Tests for CourseData utility class.
|
||||
"""
|
||||
|
||||
|
||||
import pytest
|
||||
import six
|
||||
from mock import patch
|
||||
|
||||
@@ -56,7 +56,7 @@ class CourseDataTest(ModuleStoreTestCase):
|
||||
if arg != kwarg and arg != "collected_block_structure": # lint-amnesty, pylint: disable=consider-using-in
|
||||
expected = self.expected_results[arg]
|
||||
actual = getattr(course_data, arg)
|
||||
self.assertEqual(expected, actual)
|
||||
assert expected == actual
|
||||
|
||||
def test_properties(self):
|
||||
expected_edited_on = getattr( # lint-amnesty, pylint: disable=literal-used-as-attribute
|
||||
@@ -71,30 +71,30 @@ class CourseDataTest(ModuleStoreTestCase):
|
||||
dict(course_key=self.course.id),
|
||||
]:
|
||||
course_data = CourseData(self.user, **kwargs)
|
||||
self.assertEqual(course_data.course_key, self.course.id)
|
||||
self.assertEqual(course_data.location, self.course.location)
|
||||
self.assertEqual(course_data.structure.root_block_usage_key, self.one_true_structure.root_block_usage_key)
|
||||
self.assertEqual(course_data.course.id, self.course.id)
|
||||
self.assertEqual(course_data.version, self.course.course_version)
|
||||
self.assertEqual(course_data.edited_on, expected_edited_on)
|
||||
self.assertIn(u'Course: course_key', six.text_type(course_data))
|
||||
self.assertIn(u'Course: course_key', course_data.full_string())
|
||||
assert course_data.course_key == self.course.id
|
||||
assert course_data.location == self.course.location
|
||||
assert course_data.structure.root_block_usage_key == self.one_true_structure.root_block_usage_key
|
||||
assert course_data.course.id == self.course.id
|
||||
assert course_data.version == self.course.course_version
|
||||
assert course_data.edited_on == expected_edited_on
|
||||
assert u'Course: course_key' in six.text_type(course_data)
|
||||
assert u'Course: course_key' in course_data.full_string()
|
||||
|
||||
def test_no_data(self):
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
_ = CourseData(self.user)
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
def test_full_string(self):
|
||||
empty_structure = get_course_blocks(self.user, self.course.location)
|
||||
self.assertFalse(empty_structure)
|
||||
assert not empty_structure
|
||||
|
||||
# full_string retrieves value from collected_structure when structure is empty.
|
||||
course_data = CourseData(
|
||||
self.user, structure=empty_structure, collected_block_structure=self.collected_structure,
|
||||
)
|
||||
self.assertIn(u'Course: course_key: {}, version:'.format(self.course.id), course_data.full_string())
|
||||
assert u'Course: course_key: {}, version:'.format(self.course.id) in course_data.full_string()
|
||||
|
||||
# full_string returns minimal value when structures aren't readily available.
|
||||
course_data = CourseData(self.user, course_key=self.course.id)
|
||||
self.assertIn(u'empty course structure', course_data.full_string())
|
||||
assert u'empty course structure' in course_data.full_string()
|
||||
|
||||
@@ -39,9 +39,9 @@ class ZeroGradeTest(GradeTestBase):
|
||||
for chapter in chapter_grades:
|
||||
for section in chapter_grades[chapter]['sections']:
|
||||
for score in six.itervalues(section.problem_scores):
|
||||
self.assertEqual(score.earned, 0)
|
||||
self.assertEqual(score.first_attempted, None)
|
||||
self.assertEqual(section.all_total.earned, 0)
|
||||
assert score.earned == 0
|
||||
assert score.first_attempted is None
|
||||
assert section.all_total.earned == 0
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_zero_null_scores(self, assume_zero_enabled):
|
||||
@@ -53,9 +53,9 @@ class ZeroGradeTest(GradeTestBase):
|
||||
course_data = CourseData(self.request.user, structure=self.course_structure)
|
||||
chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
|
||||
for chapter in chapter_grades:
|
||||
self.assertNotEqual({}, chapter_grades[chapter]['sections'])
|
||||
assert {} != chapter_grades[chapter]['sections']
|
||||
for section in chapter_grades[chapter]['sections']:
|
||||
self.assertEqual({}, section.problem_scores)
|
||||
assert {} == section.problem_scores
|
||||
|
||||
|
||||
class TestScoreForModule(SharedModuleStoreTestCase):
|
||||
@@ -112,45 +112,45 @@ class TestScoreForModule(SharedModuleStoreTestCase):
|
||||
|
||||
def test_score_chapter(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.a.location)
|
||||
self.assertEqual(earned, 9)
|
||||
self.assertEqual(possible, 24)
|
||||
assert earned == 9
|
||||
assert possible == 24
|
||||
|
||||
def test_score_section_many_leaves(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.b.location)
|
||||
self.assertEqual(earned, 6)
|
||||
self.assertEqual(possible, 14)
|
||||
assert earned == 6
|
||||
assert possible == 14
|
||||
|
||||
def test_score_section_one_leaf(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.c.location)
|
||||
self.assertEqual(earned, 3)
|
||||
self.assertEqual(possible, 10)
|
||||
assert earned == 3
|
||||
assert possible == 10
|
||||
|
||||
def test_score_vertical_two_leaves(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.d.location)
|
||||
self.assertEqual(earned, 5)
|
||||
self.assertEqual(possible, 10)
|
||||
assert earned == 5
|
||||
assert possible == 10
|
||||
|
||||
def test_score_vertical_two_leaves_one_unscored(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.e.location)
|
||||
self.assertEqual(earned, 1)
|
||||
self.assertEqual(possible, 4)
|
||||
assert earned == 1
|
||||
assert possible == 4
|
||||
|
||||
def test_score_vertical_no_score(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.f.location)
|
||||
self.assertEqual(earned, 0)
|
||||
self.assertEqual(possible, 0)
|
||||
assert earned == 0
|
||||
assert possible == 0
|
||||
|
||||
def test_score_vertical_one_leaf(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.g.location)
|
||||
self.assertEqual(earned, 3)
|
||||
self.assertEqual(possible, 10)
|
||||
assert earned == 3
|
||||
assert possible == 10
|
||||
|
||||
def test_score_leaf(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.h.location)
|
||||
self.assertEqual(earned, 2)
|
||||
self.assertEqual(possible, 5)
|
||||
assert earned == 2
|
||||
assert possible == 5
|
||||
|
||||
def test_score_leaf_no_score(self):
|
||||
earned, possible = self.course_grade.score_for_module(self.m.location)
|
||||
self.assertEqual(earned, 0)
|
||||
self.assertEqual(possible, 0)
|
||||
assert earned == 0
|
||||
assert possible == 0
|
||||
|
||||
@@ -35,10 +35,10 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
Asserts whether the given course_grade is as expected with
|
||||
zero values.
|
||||
"""
|
||||
self.assertIsInstance(course_grade, expected_grade_class)
|
||||
self.assertIsNone(course_grade.letter_grade)
|
||||
self.assertEqual(course_grade.percent, 0.0)
|
||||
self.assertIsNotNone(course_grade.chapter_grades)
|
||||
assert isinstance(course_grade, expected_grade_class)
|
||||
assert course_grade.letter_grade is None
|
||||
assert course_grade.percent == 0.0
|
||||
assert course_grade.chapter_grades is not None
|
||||
|
||||
def test_course_grade_no_access(self):
|
||||
"""
|
||||
@@ -46,12 +46,12 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
"""
|
||||
invisible_course = CourseFactory.create(visible_to_staff_only=True)
|
||||
access = has_access(self.request.user, 'load', invisible_course)
|
||||
self.assertEqual(access.has_access, False)
|
||||
self.assertEqual(access.error_code, 'not_visible_to_user')
|
||||
assert access.has_access is False
|
||||
assert access.error_code == 'not_visible_to_user'
|
||||
|
||||
# with self.assertNoExceptionRaised: <- this isn't a real method, it's an implicit assumption
|
||||
grade = CourseGradeFactory().read(self.request.user, invisible_course)
|
||||
self.assertEqual(grade.percent, 0)
|
||||
assert grade.percent == 0
|
||||
|
||||
@patch.dict(settings.FEATURES, {'PERSISTENT_GRADES_ENABLED_FOR_ALL_TESTS': False})
|
||||
@ddt.data(
|
||||
@@ -73,7 +73,7 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
):
|
||||
with patch('lms.djangoapps.grades.models.PersistentCourseGrade.read') as mock_read_grade:
|
||||
grade_factory.read(self.request.user, self.course)
|
||||
self.assertEqual(mock_read_grade.called, feature_flag and course_setting)
|
||||
assert mock_read_grade.called == (feature_flag and course_setting)
|
||||
|
||||
def test_read_and_update(self):
|
||||
grade_factory = CourseGradeFactory()
|
||||
@@ -87,15 +87,15 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
_assert_section_order(course_grade)
|
||||
|
||||
def _assert_grade_values(course_grade, expected_pass, expected_percent):
|
||||
self.assertEqual(course_grade.letter_grade, u'Pass' if expected_pass else None)
|
||||
self.assertEqual(course_grade.percent, expected_percent)
|
||||
assert course_grade.letter_grade == (u'Pass' if expected_pass else None)
|
||||
assert course_grade.percent == expected_percent
|
||||
|
||||
def _assert_section_order(course_grade):
|
||||
sections = course_grade.chapter_grades[self.chapter.location]['sections']
|
||||
self.assertEqual(
|
||||
[section.display_name for section in sections],
|
||||
[self.sequence.display_name, self.sequence2.display_name]
|
||||
)
|
||||
assert [section.display_name for section in sections] == [
|
||||
self.sequence.display_name,
|
||||
self.sequence2.display_name
|
||||
]
|
||||
|
||||
with self.assertNumQueries(3), mock_get_score(1, 2):
|
||||
_assert_read(expected_pass=False, expected_percent=0) # start off with grade of 0
|
||||
@@ -138,7 +138,7 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
if create_if_needed or assume_zero_enabled:
|
||||
self._assert_zero_grade(course_grade, ZeroCourseGrade if assume_zero_enabled else CourseGrade)
|
||||
else:
|
||||
self.assertIsNone(course_grade)
|
||||
assert course_grade is None
|
||||
|
||||
def test_read_optimization(self):
|
||||
grade_factory = CourseGradeFactory()
|
||||
@@ -146,14 +146,17 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
mocked_course_blocks.return_value = self.course_structure
|
||||
with mock_get_score(1, 2):
|
||||
grade_factory.update(self.request.user, self.course, force_update_subsections=True)
|
||||
self.assertEqual(mocked_course_blocks.call_count, 1)
|
||||
assert mocked_course_blocks.call_count == 1
|
||||
|
||||
with patch('lms.djangoapps.grades.course_data.get_course_blocks') as mocked_course_blocks:
|
||||
with patch('lms.djangoapps.grades.subsection_grade.get_score') as mocked_get_score:
|
||||
course_grade = grade_factory.read(self.request.user, self.course)
|
||||
self.assertEqual(course_grade.percent, 0.5) # make sure it's not a zero-valued course grade
|
||||
self.assertFalse(mocked_get_score.called) # no calls to CSM/submissions tables
|
||||
self.assertFalse(mocked_course_blocks.called) # no user-specific transformer calculation
|
||||
assert course_grade.percent == 0.5
|
||||
# make sure it's not a zero-valued course grade
|
||||
assert not mocked_get_score.called
|
||||
# no calls to CSM/submissions tables
|
||||
assert not mocked_course_blocks.called
|
||||
# no user-specific transformer calculation
|
||||
|
||||
def test_subsection_grade(self):
|
||||
grade_factory = CourseGradeFactory()
|
||||
@@ -161,13 +164,13 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
grade_factory.update(self.request.user, self.course, force_update_subsections=True)
|
||||
course_grade = grade_factory.read(self.request.user, course_structure=self.course_structure)
|
||||
subsection_grade = course_grade.subsection_grade(self.sequence.location)
|
||||
self.assertEqual(subsection_grade.percent_graded, 0.5)
|
||||
assert subsection_grade.percent_graded == 0.5
|
||||
|
||||
def test_subsection_type_graders(self):
|
||||
graders = CourseGrade.get_subsection_type_graders(self.course)
|
||||
self.assertEqual(len(graders), 2)
|
||||
self.assertEqual(graders["Homework"].type, "Homework")
|
||||
self.assertEqual(graders["NoCredit"].min_count, 0)
|
||||
assert len(graders) == 2
|
||||
assert graders['Homework'].type == 'Homework'
|
||||
assert graders['NoCredit'].min_count == 0
|
||||
|
||||
def test_create_zero_subs_grade_for_nonzero_course_grade(self):
|
||||
subsection = self.course_structure[self.sequence.location]
|
||||
@@ -176,8 +179,8 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
course_grade = CourseGradeFactory().update(self.request.user, self.course)
|
||||
subsection1_grade = course_grade.subsection_grades[self.sequence.location]
|
||||
subsection2_grade = course_grade.subsection_grades[self.sequence2.location]
|
||||
self.assertIsInstance(subsection1_grade, ReadSubsectionGrade)
|
||||
self.assertIsInstance(subsection2_grade, ZeroSubsectionGrade)
|
||||
assert isinstance(subsection1_grade, ReadSubsectionGrade)
|
||||
assert isinstance(subsection2_grade, ZeroSubsectionGrade)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_iter_force_update(self, force_update):
|
||||
@@ -185,7 +188,7 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
set(CourseGradeFactory().iter(
|
||||
users=[self.request.user], course=self.course, force_update=force_update,
|
||||
))
|
||||
self.assertEqual(mock_update.called, force_update)
|
||||
assert mock_update.called == force_update
|
||||
|
||||
def test_course_grade_summary(self):
|
||||
with mock_get_score(1, 2):
|
||||
@@ -240,7 +243,7 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
},
|
||||
]
|
||||
}
|
||||
self.assertEqual(expected_summary, actual_summary)
|
||||
assert expected_summary == actual_summary
|
||||
|
||||
|
||||
class TestGradeIteration(SharedModuleStoreTestCase):
|
||||
@@ -278,7 +281,7 @@ class TestGradeIteration(SharedModuleStoreTestCase):
|
||||
iterator, but it shouldn't error.
|
||||
"""
|
||||
grade_results = list(CourseGradeFactory().iter([], self.course))
|
||||
self.assertEqual(grade_results, [])
|
||||
assert grade_results == []
|
||||
|
||||
def test_all_empty_grades(self):
|
||||
"""
|
||||
@@ -290,12 +293,12 @@ class TestGradeIteration(SharedModuleStoreTestCase):
|
||||
wraps=BlockStructureFactory.create_from_store
|
||||
) as mock_create_from_store:
|
||||
all_course_grades, all_errors = self._course_grades_and_errors_for(self.course, self.students)
|
||||
self.assertEqual(mock_create_from_store.call_count, 1)
|
||||
assert mock_create_from_store.call_count == 1
|
||||
|
||||
self.assertEqual(len(all_errors), 0)
|
||||
assert len(all_errors) == 0
|
||||
for course_grade in all_course_grades.values():
|
||||
self.assertIsNone(course_grade.letter_grade)
|
||||
self.assertEqual(course_grade.percent, 0.0)
|
||||
assert course_grade.letter_grade is None
|
||||
assert course_grade.percent == 0.0
|
||||
|
||||
@patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read')
|
||||
def test_grading_exception(self, mock_course_grade):
|
||||
@@ -317,25 +320,22 @@ class TestGradeIteration(SharedModuleStoreTestCase):
|
||||
]
|
||||
with self.assertNumQueries(8):
|
||||
all_course_grades, all_errors = self._course_grades_and_errors_for(self.course, self.students)
|
||||
self.assertEqual(
|
||||
{student: text_type(all_errors[student]) for student in all_errors},
|
||||
{
|
||||
student3: "Error for student3.",
|
||||
student4: "Error for student4.",
|
||||
}
|
||||
)
|
||||
assert {student: text_type(all_errors[student]) for student in all_errors} == {
|
||||
student3: 'Error for student3.',
|
||||
student4: 'Error for student4.'
|
||||
}
|
||||
|
||||
# But we should still have five gradesets
|
||||
self.assertEqual(len(all_course_grades), 5)
|
||||
assert len(all_course_grades) == 5
|
||||
|
||||
# Even though two will simply be empty
|
||||
self.assertIsNone(all_course_grades[student3])
|
||||
self.assertIsNone(all_course_grades[student4])
|
||||
assert all_course_grades[student3] is None
|
||||
assert all_course_grades[student4] is None
|
||||
|
||||
# The rest will have grade information in them
|
||||
self.assertIsNotNone(all_course_grades[student1])
|
||||
self.assertIsNotNone(all_course_grades[student2])
|
||||
self.assertIsNotNone(all_course_grades[student5])
|
||||
assert all_course_grades[student1] is not None
|
||||
assert all_course_grades[student2] is not None
|
||||
assert all_course_grades[student5] is not None
|
||||
|
||||
def _course_grades_and_errors_for(self, course, students):
|
||||
"""
|
||||
|
||||
@@ -8,6 +8,7 @@ from base64 import b64encode
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from hashlib import sha1
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
@@ -54,15 +55,9 @@ class BlockRecordListTestCase(TestCase):
|
||||
)
|
||||
|
||||
brs = BlockRecordList((), self.course_key)
|
||||
self.assertFalse(brs)
|
||||
self.assertEqual(
|
||||
brs.json_value,
|
||||
empty_json
|
||||
)
|
||||
self.assertEqual(
|
||||
BlockRecordList.from_json(empty_json),
|
||||
brs
|
||||
)
|
||||
assert not brs
|
||||
assert brs.json_value == empty_json
|
||||
assert BlockRecordList.from_json(empty_json) == brs
|
||||
|
||||
|
||||
class GradesModelTestCase(TestCase):
|
||||
@@ -108,7 +103,7 @@ class BlockRecordTest(GradesModelTestCase):
|
||||
raw_possible,
|
||||
graded=False,
|
||||
)
|
||||
self.assertEqual(record.locator, self.locator_a)
|
||||
assert record.locator == self.locator_a
|
||||
|
||||
@ddt.data(
|
||||
(0, 0, "0123456789abcdef", True),
|
||||
@@ -127,7 +122,7 @@ class BlockRecordTest(GradesModelTestCase):
|
||||
("raw_possible", raw_possible),
|
||||
("graded", graded),
|
||||
])
|
||||
self.assertEqual(expected, record._asdict())
|
||||
assert expected == record._asdict()
|
||||
|
||||
|
||||
class VisibleBlocksTest(GradesModelTestCase):
|
||||
@@ -166,9 +161,9 @@ class VisibleBlocksTest(GradesModelTestCase):
|
||||
}
|
||||
expected_json = json.dumps(expected_data, separators=(',', ':'), sort_keys=True)
|
||||
expected_hash = b64encode(sha1(expected_json.encode('utf-8')).digest()).decode('utf-8')
|
||||
self.assertEqual(expected_data, json.loads(vblocks.blocks_json))
|
||||
self.assertEqual(expected_json, vblocks.blocks_json)
|
||||
self.assertEqual(expected_hash, vblocks.hashed)
|
||||
assert expected_data == json.loads(vblocks.blocks_json)
|
||||
assert expected_json == vblocks.blocks_json
|
||||
assert expected_hash == vblocks.hashed
|
||||
|
||||
def test_ordering_matters(self):
|
||||
"""
|
||||
@@ -180,14 +175,14 @@ class VisibleBlocksTest(GradesModelTestCase):
|
||||
same_order_vblocks = self._create_block_record_list([self.record_a, self.record_b])
|
||||
new_vblocks = self._create_block_record_list([self.record_b])
|
||||
|
||||
self.assertNotEqual(stored_vblocks.pk, repeat_vblocks.pk)
|
||||
self.assertNotEqual(stored_vblocks.hashed, repeat_vblocks.hashed)
|
||||
assert stored_vblocks.pk != repeat_vblocks.pk
|
||||
assert stored_vblocks.hashed != repeat_vblocks.hashed
|
||||
|
||||
self.assertEqual(stored_vblocks.pk, same_order_vblocks.pk)
|
||||
self.assertEqual(stored_vblocks.hashed, same_order_vblocks.hashed)
|
||||
assert stored_vblocks.pk == same_order_vblocks.pk
|
||||
assert stored_vblocks.hashed == same_order_vblocks.hashed
|
||||
|
||||
self.assertNotEqual(stored_vblocks.pk, new_vblocks.pk)
|
||||
self.assertNotEqual(stored_vblocks.hashed, new_vblocks.hashed)
|
||||
assert stored_vblocks.pk != new_vblocks.pk
|
||||
assert stored_vblocks.hashed != new_vblocks.hashed
|
||||
|
||||
def test_blocks_property(self):
|
||||
"""
|
||||
@@ -197,8 +192,8 @@ class VisibleBlocksTest(GradesModelTestCase):
|
||||
"""
|
||||
expected_blocks = BlockRecordList.from_list([self.record_a, self.record_b], self.course_key)
|
||||
visible_blocks = self._create_block_record_list(expected_blocks)
|
||||
self.assertEqual(expected_blocks, visible_blocks.blocks)
|
||||
with self.assertRaises(AttributeError):
|
||||
assert expected_blocks == visible_blocks.blocks
|
||||
with pytest.raises(AttributeError):
|
||||
visible_blocks.blocks = expected_blocks
|
||||
|
||||
|
||||
@@ -248,7 +243,7 @@ class PersistentSubsectionGradeTest(GradesModelTestCase):
|
||||
@ddt.unpack
|
||||
def test_non_optional_fields(self, field, error):
|
||||
del self.params[field]
|
||||
with self.assertRaises(error):
|
||||
with pytest.raises(error):
|
||||
PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
|
||||
@ddt.data(True, False)
|
||||
@@ -257,40 +252,40 @@ class PersistentSubsectionGradeTest(GradesModelTestCase):
|
||||
|
||||
self.params["earned_all"] = 7
|
||||
updated_grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.assertEqual(updated_grade.earned_all, 7)
|
||||
assert updated_grade.earned_all == 7
|
||||
if already_created:
|
||||
self.assertEqual(created_grade.id, updated_grade.id)
|
||||
self.assertEqual(created_grade.earned_all, 6)
|
||||
assert created_grade.id == updated_grade.id
|
||||
assert created_grade.earned_all == 6
|
||||
|
||||
with self.assertNumQueries(1):
|
||||
read_grade = PersistentSubsectionGrade.read_grade(
|
||||
user_id=self.params["user_id"],
|
||||
usage_key=self.params["usage_key"],
|
||||
)
|
||||
self.assertEqual(updated_grade, read_grade)
|
||||
self.assertEqual(read_grade.visible_blocks.blocks, self.block_records)
|
||||
assert updated_grade == read_grade
|
||||
assert read_grade.visible_blocks.blocks == self.block_records
|
||||
|
||||
def test_unattempted(self):
|
||||
self.params['first_attempted'] = None
|
||||
self.params['earned_all'] = 0.0
|
||||
self.params['earned_graded'] = 0.0
|
||||
grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.assertIsNone(grade.first_attempted)
|
||||
self.assertEqual(grade.earned_all, 0.0)
|
||||
self.assertEqual(grade.earned_graded, 0.0)
|
||||
assert grade.first_attempted is None
|
||||
assert grade.earned_all == 0.0
|
||||
assert grade.earned_graded == 0.0
|
||||
|
||||
def test_first_attempted_not_changed_on_update(self):
|
||||
PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
moment = now()
|
||||
grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.assertLess(grade.first_attempted, moment)
|
||||
assert grade.first_attempted < moment
|
||||
|
||||
def test_unattempted_save_does_not_remove_attempt(self):
|
||||
PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.params['first_attempted'] = None
|
||||
grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.assertIsInstance(grade.first_attempted, datetime)
|
||||
self.assertEqual(grade.earned_all, 6.0)
|
||||
assert isinstance(grade.first_attempted, datetime)
|
||||
assert grade.earned_all == 6.0
|
||||
|
||||
def test_update_or_create_event(self):
|
||||
with patch('lms.djangoapps.grades.events.tracker') as tracker_mock:
|
||||
@@ -317,16 +312,16 @@ class PersistentSubsectionGradeTest(GradesModelTestCase):
|
||||
)
|
||||
|
||||
grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
|
||||
self.assertEqual(self.params['earned_all'], grade.earned_all)
|
||||
self.assertEqual(self.params['earned_graded'], grade.earned_graded)
|
||||
assert self.params['earned_all'] == grade.earned_all
|
||||
assert self.params['earned_graded'] == grade.earned_graded
|
||||
history = override.get_history()
|
||||
self.assertEqual(1, len(list(history)))
|
||||
self.assertEqual('+', list(history)[0].history_type)
|
||||
assert 1 == len(list(history))
|
||||
assert '+' == list(history)[0].history_type
|
||||
# Any score values that aren't specified should use the values from grade as defaults
|
||||
self.assertEqual(0, override.earned_all_override)
|
||||
self.assertEqual(0, override.earned_graded_override)
|
||||
self.assertEqual(grade.possible_all, override.possible_all_override)
|
||||
self.assertEqual(grade.possible_graded, override.possible_graded_override)
|
||||
assert 0 == override.earned_all_override
|
||||
assert 0 == override.earned_graded_override
|
||||
assert grade.possible_all == override.possible_all_override
|
||||
assert grade.possible_graded == override.possible_graded_override
|
||||
|
||||
def _assert_tracker_emitted_event(self, tracker_mock, grade):
|
||||
"""
|
||||
@@ -385,9 +380,9 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
self.params["percent_grade"] = 88.8
|
||||
self.params["letter_grade"] = "Better job"
|
||||
updated_grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertEqual(updated_grade.percent_grade, 88.8)
|
||||
self.assertEqual(updated_grade.letter_grade, "Better job")
|
||||
self.assertEqual(created_grade.id, updated_grade.id)
|
||||
assert updated_grade.percent_grade == 88.8
|
||||
assert updated_grade.letter_grade == 'Better job'
|
||||
assert created_grade.id == updated_grade.id
|
||||
|
||||
def test_passed_timestamp(self):
|
||||
# When the user has not passed, passed_timestamp is None
|
||||
@@ -397,7 +392,7 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
u'passed': False,
|
||||
})
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertIsNone(grade.passed_timestamp)
|
||||
assert grade.passed_timestamp is None
|
||||
|
||||
# After the user earns a passing grade, the passed_timestamp is set
|
||||
self.params.update({
|
||||
@@ -407,8 +402,8 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
})
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
passed_timestamp = grade.passed_timestamp
|
||||
self.assertEqual(grade.letter_grade, u'C')
|
||||
self.assertIsInstance(passed_timestamp, datetime)
|
||||
assert grade.letter_grade == u'C'
|
||||
assert isinstance(passed_timestamp, datetime)
|
||||
|
||||
# After the user improves their score, the new grade is reflected, but
|
||||
# the passed_timestamp remains the same.
|
||||
@@ -418,8 +413,8 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
u'passed': True,
|
||||
})
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertEqual(grade.letter_grade, u'A')
|
||||
self.assertEqual(grade.passed_timestamp, passed_timestamp)
|
||||
assert grade.letter_grade == u'A'
|
||||
assert grade.passed_timestamp == passed_timestamp
|
||||
|
||||
# If the grade later reverts to a failing grade, passed_timestamp remains the same.
|
||||
self.params.update({
|
||||
@@ -428,13 +423,13 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
u'passed': False,
|
||||
})
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertEqual(grade.letter_grade, u'')
|
||||
self.assertEqual(grade.passed_timestamp, passed_timestamp)
|
||||
assert grade.letter_grade == u''
|
||||
assert grade.passed_timestamp == passed_timestamp
|
||||
|
||||
def test_passed_timestamp_is_now(self):
|
||||
with freeze_time(now()):
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertEqual(now(), grade.passed_timestamp)
|
||||
assert now() == grade.passed_timestamp
|
||||
|
||||
def test_create_and_read_grade(self):
|
||||
created_grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
@@ -442,15 +437,15 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
for param in self.params:
|
||||
if param == u'passed':
|
||||
continue # passed/passed_timestamp takes special handling, and is tested separately
|
||||
self.assertEqual(self.params[param], getattr(created_grade, param))
|
||||
self.assertIsInstance(created_grade.passed_timestamp, datetime)
|
||||
self.assertEqual(created_grade, read_grade)
|
||||
assert self.params[param] == getattr(created_grade, param)
|
||||
assert isinstance(created_grade.passed_timestamp, datetime)
|
||||
assert created_grade == read_grade
|
||||
|
||||
@ddt.data('course_version', 'course_edited_timestamp')
|
||||
def test_optional_fields(self, field):
|
||||
del self.params[field]
|
||||
grade = PersistentCourseGrade.update_or_create(**self.params)
|
||||
self.assertFalse(getattr(grade, field))
|
||||
assert not getattr(grade, field)
|
||||
|
||||
@ddt.data(
|
||||
("percent_grade", "Not a float at all", ValueError),
|
||||
@@ -463,11 +458,11 @@ class PersistentCourseGradesTest(GradesModelTestCase):
|
||||
@ddt.unpack
|
||||
def test_update_or_create_with_bad_params(self, param, val, error):
|
||||
self.params[param] = val
|
||||
with self.assertRaises(error):
|
||||
with pytest.raises(error):
|
||||
PersistentCourseGrade.update_or_create(**self.params)
|
||||
|
||||
def test_grade_does_not_exist(self):
|
||||
with self.assertRaises(PersistentCourseGrade.DoesNotExist):
|
||||
with pytest.raises(PersistentCourseGrade.DoesNotExist):
|
||||
PersistentCourseGrade.read(self.params["user_id"], self.params["course_id"])
|
||||
|
||||
def test_update_or_create_event(self):
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
Tests for grades.scores module.
|
||||
"""
|
||||
|
||||
|
||||
import itertools
|
||||
# pylint: disable=protected-access
|
||||
import itertools
|
||||
from collections import namedtuple
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
from django.test import TestCase
|
||||
@@ -62,13 +62,13 @@ class TestScoredBlockTypes(TestCase):
|
||||
}
|
||||
|
||||
def test_block_types_possibly_scored(self):
|
||||
self.assertTrue(self.possibly_scored_block_types.issubset(scores._block_types_possibly_scored()))
|
||||
assert self.possibly_scored_block_types.issubset(scores._block_types_possibly_scored())
|
||||
|
||||
def test_possibly_scored(self):
|
||||
course_key = CourseLocator(u'org', u'course', u'run')
|
||||
for block_type in self.possibly_scored_block_types:
|
||||
usage_key = BlockUsageLocator(course_key, block_type, 'mock_block_id')
|
||||
self.assertTrue(scores.possibly_scored(usage_key))
|
||||
assert scores.possibly_scored(usage_key)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -221,7 +221,7 @@ class TestGetScore(TestCase):
|
||||
self._create_block(block_value),
|
||||
)
|
||||
expected_score = ProblemScore(**expected_result._asdict())
|
||||
self.assertEqual(score, expected_score)
|
||||
assert score == expected_score
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -240,10 +240,7 @@ class TestWeightedScore(TestCase):
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_cannot_compute(self, raw_earned, raw_possible, weight):
|
||||
self.assertEqual(
|
||||
scores.weighted_score(raw_earned, raw_possible, weight),
|
||||
(raw_earned, raw_possible),
|
||||
)
|
||||
assert scores.weighted_score(raw_earned, raw_possible, weight) == (raw_earned, raw_possible)
|
||||
|
||||
@ddt.data(
|
||||
(0, 5, 0, (0, 0)),
|
||||
@@ -255,13 +252,10 @@ class TestWeightedScore(TestCase):
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_computed(self, raw_earned, raw_possible, weight, expected_score):
|
||||
self.assertEqual(
|
||||
scores.weighted_score(raw_earned, raw_possible, weight),
|
||||
expected_score,
|
||||
)
|
||||
assert scores.weighted_score(raw_earned, raw_possible, weight) == expected_score
|
||||
|
||||
def test_assert_on_invalid_r_possible(self):
|
||||
with self.assertRaises(AssertionError):
|
||||
with pytest.raises(AssertionError):
|
||||
scores.weighted_score(raw_earned=1, raw_possible=None, weight=1)
|
||||
|
||||
|
||||
@@ -287,10 +281,7 @@ class TestInternalGetGraded(TestCase):
|
||||
@ddt.data(None, True, False)
|
||||
def test_with_no_persisted_block(self, explicitly_graded_value):
|
||||
block = self._create_block(explicitly_graded_value)
|
||||
self.assertEqual(
|
||||
scores._get_graded_from_block(None, block),
|
||||
explicitly_graded_value is not False, # defaults to True unless explicitly False
|
||||
)
|
||||
assert scores._get_graded_from_block(None, block) == (explicitly_graded_value is not False)
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product((True, False), (True, False, None))
|
||||
@@ -299,10 +290,7 @@ class TestInternalGetGraded(TestCase):
|
||||
def test_with_persisted_block(self, persisted_block_value, block_value):
|
||||
block = self._create_block(block_value)
|
||||
block_record = BlockRecord(block.location, 0, 0, persisted_block_value)
|
||||
self.assertEqual(
|
||||
scores._get_graded_from_block(block_record, block),
|
||||
block_record.graded, # persisted value takes precedence
|
||||
)
|
||||
assert scores._get_graded_from_block(block_record, block) == block_record.graded
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -330,14 +318,14 @@ class TestInternalGetScoreFromBlock(TestCase):
|
||||
raw_earned, raw_possible, weighted_earned, weighted_possible, first_attempted
|
||||
) = scores._get_score_from_persisted_or_latest_block(persisted_block, block, weight)
|
||||
|
||||
self.assertEqual(raw_earned, 0.0)
|
||||
self.assertEqual(raw_possible, expected_r_possible)
|
||||
self.assertEqual(weighted_earned, 0.0)
|
||||
assert raw_earned == 0.0
|
||||
assert raw_possible == expected_r_possible
|
||||
assert weighted_earned == 0.0
|
||||
if weight is None or expected_r_possible == 0:
|
||||
self.assertEqual(weighted_possible, expected_r_possible)
|
||||
assert weighted_possible == expected_r_possible
|
||||
else:
|
||||
self.assertEqual(weighted_possible, weight)
|
||||
self.assertIsNone(first_attempted)
|
||||
assert weighted_possible == weight
|
||||
assert first_attempted is None
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product((0, 1, 5), (None, 0, 1, 5))
|
||||
|
||||
@@ -179,22 +179,19 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
self.course.id,
|
||||
self.subsection.location
|
||||
)
|
||||
self.assertIsNotNone(override_obj)
|
||||
self.assertEqual(override_obj.earned_all_override, override['earned_all'])
|
||||
self.assertEqual(override_obj.earned_graded_override, override['earned_graded'])
|
||||
assert override_obj is not None
|
||||
assert override_obj.earned_all_override == override['earned_all']
|
||||
assert override_obj.earned_graded_override == override['earned_graded']
|
||||
|
||||
self.assertEqual(
|
||||
self.mock_signal.call_args,
|
||||
call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection.location),
|
||||
only_if_higher=False,
|
||||
modified=override_obj.modified,
|
||||
score_deleted=False,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
assert self.mock_signal.call_args == call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection.location),
|
||||
only_if_higher=False,
|
||||
modified=override_obj.modified,
|
||||
score_deleted=False,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
|
||||
def test_override_subsection_grade_no_psg(self):
|
||||
@@ -218,9 +215,9 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
self.course.id,
|
||||
self.subsection_without_grade.location
|
||||
)
|
||||
self.assertIsNotNone(subsection_grade)
|
||||
self.assertEqual(0, subsection_grade.earned_all)
|
||||
self.assertEqual(0, subsection_grade.earned_graded)
|
||||
assert subsection_grade is not None
|
||||
assert 0 == subsection_grade.earned_all
|
||||
assert 0 == subsection_grade.earned_graded
|
||||
|
||||
# Now assert things about the grade override
|
||||
override_obj = self.service.get_subsection_grade_override(
|
||||
@@ -228,22 +225,19 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
self.course.id,
|
||||
self.subsection_without_grade.location
|
||||
)
|
||||
self.assertIsNotNone(override_obj)
|
||||
self.assertEqual(override_obj.earned_all_override, earned_all_override)
|
||||
self.assertEqual(override_obj.earned_graded_override, earned_graded_override)
|
||||
assert override_obj is not None
|
||||
assert override_obj.earned_all_override == earned_all_override
|
||||
assert override_obj.earned_graded_override == earned_graded_override
|
||||
|
||||
self.assertEqual(
|
||||
self.mock_signal.call_args,
|
||||
call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection_without_grade.location),
|
||||
only_if_higher=False,
|
||||
modified=override_obj.modified,
|
||||
score_deleted=False,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
assert self.mock_signal.call_args == call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection_without_grade.location),
|
||||
only_if_higher=False,
|
||||
modified=override_obj.modified,
|
||||
score_deleted=False,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
|
||||
@freeze_time('2017-01-01')
|
||||
@@ -260,20 +254,17 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
override = self.service.get_subsection_grade_override(self.user.id, self.course.id, self.subsection.location)
|
||||
self.assertIsNone(override)
|
||||
assert override is None
|
||||
|
||||
self.assertEqual(
|
||||
self.mock_signal.call_args,
|
||||
call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection.location),
|
||||
only_if_higher=False,
|
||||
modified=datetime.now().replace(tzinfo=pytz.UTC),
|
||||
score_deleted=True,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
assert self.mock_signal.call_args == call(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id),
|
||||
usage_id=six.text_type(self.subsection.location),
|
||||
only_if_higher=False,
|
||||
modified=datetime.now().replace(tzinfo=pytz.UTC),
|
||||
score_deleted=True,
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
|
||||
def test_undo_override_subsection_grade_across_features(self):
|
||||
@@ -294,7 +285,7 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
override = self.service.get_subsection_grade_override(self.user.id, self.course.id, self.subsection.location)
|
||||
self.assertIsNotNone(override)
|
||||
assert override is not None
|
||||
|
||||
@freeze_time('2018-01-01')
|
||||
def test_undo_override_subsection_grade_without_grade(self):
|
||||
@@ -313,11 +304,11 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
except PersistentSubsectionGrade.DoesNotExist:
|
||||
assert False, 'Exception raised unexpectedly'
|
||||
|
||||
self.assertFalse(self.mock_signal.called)
|
||||
assert not self.mock_signal.called
|
||||
|
||||
def test_should_override_grade_on_rejected_exam(self):
|
||||
self.assertTrue(self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course'))
|
||||
assert self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course')
|
||||
self.mock_waffle_flags.return_value = {
|
||||
REJECTED_EXAM_OVERRIDES_GRADE: MockWaffleFlag(False)
|
||||
}
|
||||
self.assertFalse(self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course'))
|
||||
assert not self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course')
|
||||
|
||||
@@ -5,6 +5,7 @@ Tests for the score change signals defined in the courseware models module.
|
||||
|
||||
import re
|
||||
from datetime import datetime
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
@@ -184,7 +185,7 @@ class ScoreChangedSignalRelayTest(TestCase):
|
||||
local_kwargs = SUBMISSION_KWARGS[kwargs].copy()
|
||||
del local_kwargs[missing]
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
with pytest.raises(KeyError):
|
||||
handler(None, **local_kwargs)
|
||||
self.signal_mock.assert_not_called()
|
||||
|
||||
@@ -255,6 +256,6 @@ class ScoreChangedSignalRelayTest(TestCase):
|
||||
"""
|
||||
Tests that the disconnect context manager errors when given an invalid signal.
|
||||
"""
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
with disconnect_submissions_signal_receiver(PROBLEM_RAW_SCORE_CHANGED):
|
||||
pass
|
||||
|
||||
@@ -25,12 +25,12 @@ class SubsectionGradeTest(GradeTestBase): # lint-amnesty, pylint: disable=missi
|
||||
self.subsection_grade_factory._submissions_scores, # lint-amnesty, pylint: disable=protected-access
|
||||
self.subsection_grade_factory._csm_scores, # lint-amnesty, pylint: disable=protected-access
|
||||
)
|
||||
self.assertEqual(PersistentSubsectionGrade.objects.count(), 0)
|
||||
self.assertEqual(created_grade.percent_graded, expected_result)
|
||||
assert PersistentSubsectionGrade.objects.count() == 0
|
||||
assert created_grade.percent_graded == expected_result
|
||||
|
||||
# save to db, and verify object is in database
|
||||
created_grade.update_or_create_model(self.request.user)
|
||||
self.assertEqual(PersistentSubsectionGrade.objects.count(), 1)
|
||||
assert PersistentSubsectionGrade.objects.count() == 1
|
||||
|
||||
# read from db, and ensure output matches input
|
||||
saved_model = PersistentSubsectionGrade.read_grade(
|
||||
@@ -43,10 +43,10 @@ class SubsectionGradeTest(GradeTestBase): # lint-amnesty, pylint: disable=missi
|
||||
self.subsection_grade_factory
|
||||
)
|
||||
|
||||
self.assertEqual(created_grade.url_name, read_grade.url_name)
|
||||
assert created_grade.url_name == read_grade.url_name
|
||||
read_grade.all_total.first_attempted = created_grade.all_total.first_attempted = None
|
||||
self.assertEqual(created_grade.all_total, read_grade.all_total)
|
||||
self.assertEqual(created_grade.percent_graded, expected_result)
|
||||
assert created_grade.all_total == read_grade.all_total
|
||||
assert created_grade.percent_graded == expected_result
|
||||
|
||||
def test_zero(self):
|
||||
with mock_get_score(1, 0):
|
||||
@@ -56,4 +56,4 @@ class SubsectionGradeTest(GradeTestBase): # lint-amnesty, pylint: disable=missi
|
||||
self.subsection_grade_factory._submissions_scores, # lint-amnesty, pylint: disable=protected-access
|
||||
self.subsection_grade_factory._csm_scores, # lint-amnesty, pylint: disable=protected-access
|
||||
)
|
||||
self.assertEqual(grade.percent_graded, 0.0)
|
||||
assert grade.percent_graded == 0.0
|
||||
|
||||
@@ -32,21 +32,15 @@ class TestSubsectionGradeFactory(ProblemSubmissionTestMixin, GradeTestBase):
|
||||
"""
|
||||
Asserts that the given grade object has the expected score.
|
||||
"""
|
||||
self.assertEqual(
|
||||
(grade.all_total.earned, grade.all_total.possible),
|
||||
(expected_earned, expected_possible),
|
||||
)
|
||||
self.assertEqual(
|
||||
(grade.graded_total.earned, grade.graded_total.possible),
|
||||
(expected_earned, expected_possible),
|
||||
)
|
||||
assert (grade.all_total.earned, grade.all_total.possible) == (expected_earned, expected_possible)
|
||||
assert (grade.graded_total.earned, grade.graded_total.possible) == (expected_earned, expected_possible)
|
||||
|
||||
def test_create_zero(self):
|
||||
"""
|
||||
Test that a zero grade is returned.
|
||||
"""
|
||||
grade = self.subsection_grade_factory.create(self.sequence)
|
||||
self.assertIsInstance(grade, ZeroSubsectionGrade)
|
||||
assert isinstance(grade, ZeroSubsectionGrade)
|
||||
self.assert_grade(grade, 0.0, 1.0)
|
||||
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_COURSE_ASSESSMENT_GRADE_CHANGE_SIGNAL': True})
|
||||
@@ -72,12 +66,12 @@ class TestSubsectionGradeFactory(ProblemSubmissionTestMixin, GradeTestBase):
|
||||
with mock_get_score(0, 0, None):
|
||||
self.subsection_grade_factory.update(self.sequence)
|
||||
# ensure no grades have been persisted
|
||||
self.assertEqual(0, len(PersistentSubsectionGrade.objects.all()))
|
||||
assert 0 == len(PersistentSubsectionGrade.objects.all())
|
||||
|
||||
with mock_get_score(0, 0, None):
|
||||
self.subsection_grade_factory.update(self.sequence, score_deleted=True)
|
||||
# ensure a grade has been persisted
|
||||
self.assertEqual(1, len(PersistentSubsectionGrade.objects.all()))
|
||||
assert 1 == len(PersistentSubsectionGrade.objects.all())
|
||||
|
||||
def test_update_if_higher_zero_denominator(self):
|
||||
"""
|
||||
@@ -131,7 +125,7 @@ class TestSubsectionGradeFactory(ProblemSubmissionTestMixin, GradeTestBase):
|
||||
enabled_for_course=course_setting
|
||||
):
|
||||
self.subsection_grade_factory.create(self.sequence)
|
||||
self.assertEqual(mock_read_saved_grade.called, feature_flag and course_setting)
|
||||
assert mock_read_saved_grade.called == (feature_flag and course_setting)
|
||||
|
||||
@ddt.data(
|
||||
(0, None),
|
||||
@@ -153,8 +147,8 @@ class TestSubsectionGradeFactory(ProblemSubmissionTestMixin, GradeTestBase):
|
||||
|
||||
# there should only be one persistent grade
|
||||
persistent_grade = PersistentSubsectionGrade.objects.first()
|
||||
self.assertEqual(2, persistent_grade.earned_graded)
|
||||
self.assertEqual(3, persistent_grade.possible_graded)
|
||||
assert 2 == persistent_grade.earned_graded
|
||||
assert 3 == persistent_grade.possible_graded
|
||||
|
||||
# Now create the override
|
||||
PersistentSubsectionGradeOverride.update_or_create_override(
|
||||
|
||||
@@ -7,6 +7,7 @@ import itertools
|
||||
from collections import OrderedDict
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime, timedelta
|
||||
import pytest
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
@@ -151,17 +152,17 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
"""
|
||||
self.set_up_course()
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertTrue(mock_subsection_signal.called)
|
||||
assert mock_subsection_signal.called
|
||||
|
||||
def test_block_structure_created_only_once(self):
|
||||
self.set_up_course()
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course.id))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(self.course.id)
|
||||
with patch(
|
||||
'openedx.core.djangoapps.content.block_structure.factory.BlockStructureFactory.create_from_store',
|
||||
side_effect=BlockStructureNotFound(self.course.location),
|
||||
) as mock_block_structure_create:
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertEqual(mock_block_structure_create.call_count, 1)
|
||||
assert mock_block_structure_create.call_count == 1
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 1, 38, True),
|
||||
@@ -173,7 +174,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
def test_query_counts(self, default_store, num_mongo_calls, num_sql_calls, create_multiple_subsections):
|
||||
with self.store.default_store(default_store):
|
||||
self.set_up_course(create_multiple_subsections=create_multiple_subsections)
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course.id))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(self.course.id)
|
||||
with check_mongo_calls(num_mongo_calls):
|
||||
with self.assertNumQueries(num_sql_calls):
|
||||
self._apply_recalculate_subsection_grade()
|
||||
@@ -186,7 +187,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
def test_query_counts_dont_change_with_more_content(self, default_store, num_mongo_calls, num_sql_calls):
|
||||
with self.store.default_store(default_store):
|
||||
self.set_up_course(create_multiple_subsections=True)
|
||||
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course.id))
|
||||
assert PersistentGradesEnabledFlag.feature_enabled(self.course.id)
|
||||
|
||||
num_problems = 10
|
||||
for _ in range(num_problems):
|
||||
@@ -214,7 +215,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
|
||||
# Make sure the signal is sent for only the 2 accessible sequentials.
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertEqual(mock_subsection_signal.call_count, 2)
|
||||
assert mock_subsection_signal.call_count == 2
|
||||
sequentials_signalled = {
|
||||
args[1]['subsection_grade'].location
|
||||
for args in mock_subsection_signal.call_args_list
|
||||
@@ -235,9 +236,9 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
with check_mongo_calls(num_mongo_queries):
|
||||
with self.assertNumQueries(num_sql_queries):
|
||||
self._apply_recalculate_subsection_grade()
|
||||
with self.assertRaises(PersistentCourseGrade.DoesNotExist):
|
||||
with pytest.raises(PersistentCourseGrade.DoesNotExist):
|
||||
PersistentCourseGrade.read(self.user.id, self.course.id)
|
||||
self.assertEqual(len(PersistentSubsectionGrade.bulk_read_grades(self.user.id, self.course.id)), 0)
|
||||
assert len(PersistentSubsectionGrade.bulk_read_grades(self.user.id, self.course.id)) == 0
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 1, 39),
|
||||
@@ -250,8 +251,8 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
with check_mongo_calls(num_mongo_queries):
|
||||
with self.assertNumQueries(num_sql_queries):
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertIsNotNone(PersistentCourseGrade.read(self.user.id, self.course.id))
|
||||
self.assertGreater(len(PersistentSubsectionGrade.bulk_read_grades(self.user.id, self.course.id)), 0)
|
||||
assert PersistentCourseGrade.read(self.user.id, self.course.id) is not None
|
||||
assert len(PersistentSubsectionGrade.bulk_read_grades(self.user.id, self.course.id)) > 0
|
||||
|
||||
@patch('lms.djangoapps.grades.signals.signals.SUBSECTION_SCORE_CHANGED.send')
|
||||
@patch('lms.djangoapps.grades.subsection_grade_factory.SubsectionGradeFactory.update')
|
||||
@@ -262,7 +263,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
self.set_up_course()
|
||||
mock_update.side_effect = [IntegrityError("WHAMMY"), None]
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertEqual(mock_course_signal.call_count, 1)
|
||||
assert mock_course_signal.call_count == 1
|
||||
|
||||
@patch('lms.djangoapps.grades.tasks.recalculate_subsection_grade_v3.retry')
|
||||
@patch('lms.djangoapps.grades.subsection_grade_factory.SubsectionGradeFactory.update')
|
||||
@@ -303,10 +304,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
recalculate_subsection_grade_v3.apply(kwargs=self.recalculate_subsection_grade_kwargs)
|
||||
|
||||
self._assert_retry_called(mock_retry)
|
||||
self.assertIn(
|
||||
u"Grades: tasks._has_database_updated_with_new_score is False.",
|
||||
mock_log.info.call_args_list[0][0][0]
|
||||
)
|
||||
assert u'Grades: tasks._has_database_updated_with_new_score is False.' in mock_log.info.call_args_list[0][0][0]
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product(
|
||||
@@ -340,10 +338,8 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
self._assert_retry_not_called(mock_retry)
|
||||
else:
|
||||
self._assert_retry_called(mock_retry)
|
||||
self.assertIn(
|
||||
u"Grades: tasks._has_database_updated_with_new_score is False.",
|
||||
mock_log.info.call_args_list[0][0][0]
|
||||
)
|
||||
assert u'Grades: tasks._has_database_updated_with_new_score is False.'\
|
||||
in mock_log.info.call_args_list[0][0][0]
|
||||
|
||||
@patch('lms.djangoapps.grades.tasks.log')
|
||||
@patch('lms.djangoapps.grades.tasks.recalculate_subsection_grade_v3.retry')
|
||||
@@ -355,7 +351,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
self.set_up_course()
|
||||
mock_update.side_effect = Exception("General exception with no further detail!")
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertIn("General exception with no further detail!", mock_log.info.call_args[0][0])
|
||||
assert 'General exception with no further detail!' in mock_log.info.call_args[0][0]
|
||||
self._assert_retry_called(mock_retry)
|
||||
|
||||
@patch('lms.djangoapps.grades.tasks.log')
|
||||
@@ -368,7 +364,7 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
self.set_up_course()
|
||||
mock_update.side_effect = IntegrityError("race condition oh noes")
|
||||
self._apply_recalculate_subsection_grade()
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self._assert_retry_called(mock_retry)
|
||||
|
||||
def _apply_recalculate_subsection_grade(
|
||||
@@ -392,14 +388,14 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
Verifies the task was retried and with the correct
|
||||
number of arguments.
|
||||
"""
|
||||
self.assertTrue(mock_retry.called)
|
||||
self.assertEqual(len(mock_retry.call_args[1]['kwargs']), len(self.recalculate_subsection_grade_kwargs))
|
||||
assert mock_retry.called
|
||||
assert len(mock_retry.call_args[1]['kwargs']) == len(self.recalculate_subsection_grade_kwargs)
|
||||
|
||||
def _assert_retry_not_called(self, mock_retry):
|
||||
"""
|
||||
Verifies the task was not retried.
|
||||
"""
|
||||
self.assertFalse(mock_retry.called)
|
||||
assert not mock_retry.called
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -425,15 +421,9 @@ class ComputeGradesForCourseTest(HasCourseWithProblemsMixin, ModuleStoreTestCase
|
||||
batch_size=batch_size,
|
||||
offset=4,
|
||||
)
|
||||
self.assertTrue(result.successful)
|
||||
self.assertEqual(
|
||||
PersistentCourseGrade.objects.filter(course_id=self.course.id).count(),
|
||||
min(batch_size, 8) # No more than 8 due to offset
|
||||
)
|
||||
self.assertEqual(
|
||||
PersistentSubsectionGrade.objects.filter(course_id=self.course.id).count(),
|
||||
min(batch_size, 8) # No more than 8 due to offset
|
||||
)
|
||||
assert result.successful
|
||||
assert PersistentCourseGrade.objects.filter(course_id=self.course.id).count() == min(batch_size, 8)
|
||||
assert PersistentSubsectionGrade.objects.filter(course_id=self.course.id).count() == min(batch_size, 8)
|
||||
|
||||
@ddt.data(*range(1, 12, 3))
|
||||
def test_course_task_args(self, test_batch_size):
|
||||
@@ -441,9 +431,9 @@ class ComputeGradesForCourseTest(HasCourseWithProblemsMixin, ModuleStoreTestCase
|
||||
for course_key, offset, batch_size in _course_task_args(
|
||||
batch_size=test_batch_size, course_key=self.course.id, from_settings=False
|
||||
):
|
||||
self.assertEqual(course_key, six.text_type(self.course.id))
|
||||
self.assertEqual(batch_size, test_batch_size)
|
||||
self.assertEqual(offset, offset_expected)
|
||||
assert course_key == six.text_type(self.course.id)
|
||||
assert batch_size == test_batch_size
|
||||
assert offset == offset_expected
|
||||
offset_expected += test_batch_size
|
||||
|
||||
|
||||
@@ -491,7 +481,7 @@ class RecalculateGradesForUserTest(HasCourseWithProblemsMixin, ModuleStoreTestCa
|
||||
task_result.get()
|
||||
|
||||
factory.read.assert_called_once_with(self.user, course_key=self.course.id)
|
||||
self.assertFalse(factory.update.called)
|
||||
assert not factory.update.called
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -506,12 +496,9 @@ class FreezeGradingAfterCourseEndTest(HasCourseWithProblemsMixin, ModuleStoreTes
|
||||
self.freeze_grade_flag = waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END]
|
||||
|
||||
def _assert_log(self, mock_log, method_name):
|
||||
self.assertTrue(mock_log.info.called)
|
||||
assert mock_log.info.called
|
||||
log_message = u"Attempted {} for course '%s', but grades are frozen.".format(method_name)
|
||||
self.assertIn(
|
||||
log_message,
|
||||
mock_log.info.call_args_list[0][0][0]
|
||||
)
|
||||
assert log_message in mock_log.info.call_args_list[0][0][0]
|
||||
|
||||
def _assert_for_freeze_grade_flag( # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
self,
|
||||
@@ -522,7 +509,7 @@ class FreezeGradingAfterCourseEndTest(HasCourseWithProblemsMixin, ModuleStoreTes
|
||||
mock_call,
|
||||
task_name
|
||||
):
|
||||
self.assertTrue(result.successful)
|
||||
assert result.successful
|
||||
if freeze_flag_value and end_date_adjustment > 30:
|
||||
mock_call.assert_not_called()
|
||||
self._assert_log(mock_log, task_name)
|
||||
|
||||
@@ -73,18 +73,13 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
arguments representing XBlock fields, verify that the block structure
|
||||
has the specified values for each XBlock field.
|
||||
"""
|
||||
self.assertGreater(len(expectations), 0)
|
||||
assert len(expectations) > 0
|
||||
for field in expectations:
|
||||
# Append our custom message to the default assertEqual error message
|
||||
self.longMessage = True # pylint: disable=invalid-name
|
||||
self.assertEqual(
|
||||
expectations[field],
|
||||
block_structure.get_xblock_field(usage_key, field),
|
||||
msg=u'in field {},'.format(repr(field)),
|
||||
)
|
||||
self.assertIsNotNone(
|
||||
block_structure.get_xblock_field(usage_key, u'subtree_edited_on'),
|
||||
)
|
||||
assert expectations[field] == block_structure.get_xblock_field(usage_key, field),\
|
||||
u'in field {},'.format(repr(field))
|
||||
assert block_structure.get_xblock_field(usage_key, u'subtree_edited_on') is not None
|
||||
|
||||
def assert_collected_transformer_block_fields(self, block_structure, usage_key, transformer_class, **expectations):
|
||||
"""
|
||||
@@ -93,15 +88,13 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
the block structure has the specified values for each transformer block
|
||||
field.
|
||||
"""
|
||||
self.assertGreater(len(expectations), 0)
|
||||
assert len(expectations) > 0
|
||||
# Append our custom message to the default assertEqual error message
|
||||
self.longMessage = True
|
||||
for field in expectations:
|
||||
self.assertEqual(
|
||||
expectations[field],
|
||||
block_structure.get_transformer_block_field(usage_key, transformer_class, field),
|
||||
msg=u'in {} and field {}'.format(transformer_class, repr(field)),
|
||||
)
|
||||
assert expectations[field] == block_structure.get_transformer_block_field(
|
||||
usage_key, transformer_class, field
|
||||
), u'in {} and field {}'.format(transformer_class, repr(field))
|
||||
|
||||
def build_course_with_problems(self, data='<problem></problem>', metadata=None):
|
||||
"""
|
||||
@@ -223,7 +216,7 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
self.TRANSFORMER_CLASS_TO_TEST,
|
||||
'subsections',
|
||||
)
|
||||
self.assertEqual(actual_subsections, {blocks[sub].location for sub in expected_subsections})
|
||||
assert actual_subsections == {blocks[sub].location for sub in expected_subsections}
|
||||
|
||||
def test_unscored_block_collection(self):
|
||||
blocks = self.build_course_with_problems()
|
||||
@@ -354,7 +347,8 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
problem_data = u'''
|
||||
<problem>
|
||||
<optionresponse>
|
||||
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown problems. Edit this component to replace this template with your own assessment.</p>
|
||||
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown
|
||||
problems. Edit this component to replace this template with your own assessment.</p>
|
||||
<label>Add the question text, or prompt, here. This text is required.</label>
|
||||
<description>You can add an optional tip or note related to the prompt like this. </description>
|
||||
<optioninput>
|
||||
@@ -379,17 +373,16 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
def test_course_version_not_collected_in_old_mongo(self):
|
||||
blocks = self.build_course_with_problems()
|
||||
block_structure = get_course_blocks(self.student, blocks[u'course'].location, self.transformers)
|
||||
self.assertIsNone(block_structure.get_xblock_field(blocks[u'course'].location, u'course_version'))
|
||||
assert block_structure.get_xblock_field(blocks[u'course'].location, u'course_version') is None
|
||||
|
||||
def test_course_version_collected_in_split(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
blocks = self.build_course_with_problems()
|
||||
block_structure = get_course_blocks(self.student, blocks[u'course'].location, self.transformers)
|
||||
self.assertIsNotNone(block_structure.get_xblock_field(blocks[u'course'].location, u'course_version'))
|
||||
self.assertEqual(
|
||||
block_structure.get_xblock_field(blocks[u'problem'].location, u'course_version'),
|
||||
block_structure.get_xblock_field(blocks[u'course'].location, u'course_version')
|
||||
)
|
||||
assert block_structure.get_xblock_field(blocks[u'course'].location, u'course_version') is not None
|
||||
assert block_structure.get_xblock_field(
|
||||
blocks[u'problem'].location, u'course_version'
|
||||
) == block_structure.get_xblock_field(blocks[u'course'].location, u'course_version')
|
||||
|
||||
def test_grading_policy_collected(self):
|
||||
# the calculated hash of the original and updated grading policies of the test course
|
||||
@@ -407,7 +400,7 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
grading_policy_with_updates = course_block.grading_policy
|
||||
original_grading_policy = deepcopy(grading_policy_with_updates)
|
||||
for section in grading_policy_with_updates['GRADER']:
|
||||
self.assertNotEqual(section['weight'], 0.25)
|
||||
assert section['weight'] != 0.25
|
||||
section['weight'] = 0.25
|
||||
|
||||
self._update_course_grading_policy(course_block, grading_policy_with_updates)
|
||||
|
||||
Reference in New Issue
Block a user