From e1ed5c3d2de9d79db9491276df56704af2a5a987 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Mon, 1 Jul 2013 16:47:09 -0400 Subject: [PATCH] docstrings --- .../contentstore/tests/test_textbooks.py | 39 +++++++++++++++++++ cms/djangoapps/contentstore/views/assets.py | 4 ++ cms/djangoapps/contentstore/views/course.py | 7 ++++ cms/djangoapps/contentstore/views/tabs.py | 12 +++--- .../xmodule/modulestore/tests/django_utils.py | 12 ++++++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_textbooks.py b/cms/djangoapps/contentstore/tests/test_textbooks.py index 0e55d0b395..02c64e9413 100644 --- a/cms/djangoapps/contentstore/tests/test_textbooks.py +++ b/cms/djangoapps/contentstore/tests/test_textbooks.py @@ -10,7 +10,9 @@ from contentstore.views.course import ( class TextbookIndexTestCase(CourseTestCase): + "Test cases for the textbook index page" def setUp(self): + "Set the URL for tests" super(TextbookIndexTestCase, self).setUp() self.url = reverse('textbook_index', kwargs={ 'org': self.course.location.org, @@ -19,6 +21,7 @@ class TextbookIndexTestCase(CourseTestCase): }) def test_view_index(self): + "Basic check that the textbook index page responds correctly" resp = self.client.get(self.url) self.assert2XX(resp.status_code) # we don't have resp.context right now, @@ -27,6 +30,7 @@ class TextbookIndexTestCase(CourseTestCase): self.assertEqual(resp.context['course'], self.course) def test_view_index_xhr(self): + "Check that we get a JSON response when requested via AJAX" resp = self.client.get( self.url, HTTP_ACCEPT="application/json", @@ -37,6 +41,7 @@ class TextbookIndexTestCase(CourseTestCase): self.assertEqual(self.course.pdf_textbooks, obj) def test_view_index_xhr_content(self): + "Check that the response maps to the content of the modulestore" content = [ { "tab_title": "my textbook", @@ -70,6 +75,7 @@ class TextbookIndexTestCase(CourseTestCase): self.assertEqual(content, obj) def test_view_index_xhr_post(self): + "Check that you can save information to the server" textbooks = [ {"tab_title": "Hi, mom!"}, {"tab_title": "Textbook 2"}, @@ -94,6 +100,7 @@ class TextbookIndexTestCase(CourseTestCase): self.assertEqual(no_ids, textbooks) def test_view_index_xhr_post_invalid(self): + "Check that you can't save invalid JSON" resp = self.client.post( self.url, data="invalid", @@ -107,7 +114,10 @@ class TextbookIndexTestCase(CourseTestCase): class TextbookCreateTestCase(CourseTestCase): + "Test cases for creating a new PDF textbook" + def setUp(self): + "Set up a url and some textbook content for tests" super(TextbookCreateTestCase, self).setUp() self.url = reverse('create_textbook', kwargs={ 'org': self.course.location.org, @@ -123,6 +133,7 @@ class TextbookCreateTestCase(CourseTestCase): } def test_happy_path(self): + "Test that you can create a textbook" resp = self.client.post( self.url, data=json.dumps(self.textbook), @@ -138,6 +149,7 @@ class TextbookCreateTestCase(CourseTestCase): self.assertEqual(self.textbook, textbook) def test_get(self): + "Test that GET is not allowed" resp = self.client.get( self.url, HTTP_ACCEPT="application/json", @@ -146,6 +158,7 @@ class TextbookCreateTestCase(CourseTestCase): self.assertEqual(resp.status_code, 405) def test_valid_id(self): + "Textbook IDs must begin with a number; try a valid one" self.textbook["id"] = "7x5" resp = self.client.post( self.url, @@ -159,6 +172,7 @@ class TextbookCreateTestCase(CourseTestCase): self.assertEqual(self.textbook, textbook) def test_invalid_id(self): + "Textbook IDs must begin with a number; try an invalid one" self.textbook["id"] = "xxx" resp = self.client.post( self.url, @@ -172,7 +186,10 @@ class TextbookCreateTestCase(CourseTestCase): class TextbookByIdTestCase(CourseTestCase): + "Test cases for the `textbook_by_id` view" + def setUp(self): + "Set some useful content and URLs for tests" super(TextbookByIdTestCase, self).setUp() self.textbook1 = { "tab_title": "Economics", @@ -213,34 +230,40 @@ class TextbookByIdTestCase(CourseTestCase): }) def test_get_1(self): + "Get the first textbook" resp = self.client.get(self.url1) self.assert2XX(resp.status_code) compare = json.loads(resp.content) self.assertEqual(compare, self.textbook1) def test_get_2(self): + "Get the second textbook" resp = self.client.get(self.url2) self.assert2XX(resp.status_code) compare = json.loads(resp.content) self.assertEqual(compare, self.textbook2) def test_get_nonexistant(self): + "Get a nonexistent textbook" resp = self.client.get(self.url_nonexist) self.assertEqual(resp.status_code, 404) def test_delete(self): + "Delete a textbook by ID" resp = self.client.delete(self.url1) self.assert2XX(resp.status_code) course = self.store.get_item(self.course.location) self.assertEqual(course.pdf_textbooks, [self.textbook2]) def test_delete_nonexistant(self): + "Delete a textbook by ID, when the ID doesn't match an existing textbook" resp = self.client.delete(self.url_nonexist) self.assertEqual(resp.status_code, 404) course = self.store.get_item(self.course.location) self.assertEqual(course.pdf_textbooks, [self.textbook1, self.textbook2]) def test_create_new_by_id(self): + "Create a textbook by ID" textbook = { "tab_title": "a new textbook", "url": "supercool.pdf", @@ -269,6 +292,7 @@ class TextbookByIdTestCase(CourseTestCase): ) def test_replace_by_id(self): + "Create a textbook by ID, overwriting an existing textbook ID" replacement = { "tab_title": "You've been replaced!", "url": "supercool.pdf", @@ -292,7 +316,10 @@ class TextbookByIdTestCase(CourseTestCase): class TextbookValidationTestCase(TestCase): + "Tests for the code to validate the structure of a PDF textbook" + def setUp(self): + "Set some useful content for tests" self.tb1 = { "tab_title": "Hi, mom!", "url": "/mom.pdf" @@ -312,52 +339,64 @@ class TextbookValidationTestCase(TestCase): self.textbooks = [self.tb1, self.tb2] def test_happy_path_plural(self): + "Test that the plural validator works properly" result = validate_textbooks_json(json.dumps(self.textbooks)) self.assertEqual(self.textbooks, result) def test_happy_path_singular_1(self): + "Test that the singular validator works properly" result = validate_textbook_json(json.dumps(self.tb1)) self.assertEqual(self.tb1, result) def test_happy_path_singular_2(self): + "Test that the singular validator works properly, with different data" result = validate_textbook_json(json.dumps(self.tb2)) self.assertEqual(self.tb2, result) def test_valid_id(self): + "Test that a valid ID doesn't trip the validator, and comes out unchanged" self.tb1["id"] = 1 result = validate_textbook_json(json.dumps(self.tb1)) self.assertEqual(self.tb1, result) def test_invalid_id(self): + "Test that an invalid ID trips the validator" self.tb1["id"] = "abc" with self.assertRaises(TextbookValidationError): validate_textbook_json(json.dumps(self.tb1)) def test_invalid_json_plural(self): + "Test that invalid JSON trips the plural validator" with self.assertRaises(TextbookValidationError): validate_textbooks_json("[{'abc'}]") def test_invalid_json_singular(self): + "Test that invalid JSON trips the singluar validator" with self.assertRaises(TextbookValidationError): validate_textbook_json("[{1]}") def test_wrong_json_plural(self): + "Test that a JSON object trips the plural validators (requires a list)" with self.assertRaises(TextbookValidationError): validate_textbooks_json('{"tab_title": "Hi, mom!"}') def test_wrong_json_singular(self): + "Test that a JSON list trips the plural validators (requires an object)" with self.assertRaises(TextbookValidationError): validate_textbook_json('[{"tab_title": "Hi, mom!"}, {"tab_title": "Hi, dad!"}]') def test_no_tab_title_plural(self): + "Test that `tab_title` is required for the plural validator" with self.assertRaises(TextbookValidationError): validate_textbooks_json('[{"url": "/textbook.pdf"}]') def test_no_tab_title_singular(self): + "Test that `tab_title` is required for the singular validator" with self.assertRaises(TextbookValidationError): validate_textbook_json('{"url": "/textbook.pdf"}') def test_duplicate_ids(self): + "Test that duplicate IDs in the plural validator trips the validator" textbooks = [{ "tab_title": "name one", "url": "one.pdf", diff --git a/cms/djangoapps/contentstore/views/assets.py b/cms/djangoapps/contentstore/views/assets.py index 664532c037..d3249ea0b2 100644 --- a/cms/djangoapps/contentstore/views/assets.py +++ b/cms/djangoapps/contentstore/views/assets.py @@ -38,6 +38,10 @@ __all__ = ['asset_index', 'upload_asset', 'import_course', 'generate_export_cour def assets_to_json_dict(assets): + """ + Transform the results of a contentstore query into something appropriate + for output via JSON. + """ ret = [] for asset in assets: obj = { diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 3d0d9ad250..99f77b6c77 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -509,6 +509,9 @@ def textbook_index(request, org, course, name): @login_required @ensure_csrf_cookie def create_textbook(request, org, course, name): + """ + JSON API endpoint for creating a textbook. Used by the Backbone application. + """ location = get_location_and_verify_access(request, org, course, name) store = get_modulestore(location) course_module = store.get_item(location, depth=0) @@ -542,6 +545,10 @@ def create_textbook(request, org, course, name): @ensure_csrf_cookie @require_http_methods(("GET", "POST", "DELETE")) def textbook_by_id(request, org, course, name, tid): + """ + JSON API endpoint for manipulating a textbook via its internal ID. + Used by the Backbone application. + """ location = get_location_and_verify_access(request, org, course, name) store = get_modulestore(location) course_module = store.get_item(location, depth=3) diff --git a/cms/djangoapps/contentstore/views/tabs.py b/cms/djangoapps/contentstore/views/tabs.py index d18612c41e..a7b232e92a 100644 --- a/cms/djangoapps/contentstore/views/tabs.py +++ b/cms/djangoapps/contentstore/views/tabs.py @@ -17,11 +17,13 @@ __all__ = ['edit_tabs', 'reorder_static_tabs', 'static_pages', 'edit_static'] def initialize_course_tabs(course): - # set up the default tabs - # I've added this because when we add static tabs, the LMS either expects a None for the tabs list or - # at least a list populated with the minimal times - # @TODO: I don't like the fact that the presentation tier is away of these data related constraints, let's find a better - # place for this. Also rather than using a simple list of dictionaries a nice class model would be helpful here + """ + set up the default tabs + I've added this because when we add static tabs, the LMS either expects a None for the tabs list or + at least a list populated with the minimal times + @TODO: I don't like the fact that the presentation tier is away of these data related constraints, let's find a better + place for this. Also rather than using a simple list of dictionaries a nice class model would be helpful here + """ # This logic is repeated in xmodule/modulestore/tests/factories.py # so if you change anything here, you need to also change it there. diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 5d5bb9d18b..6c5c1f66ca 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -186,21 +186,33 @@ class ModuleStoreTestCase(TestCase): super(ModuleStoreTestCase, self)._post_teardown() def assert2XX(self, status_code, msg=None): + """ + Assert that the given value is a success status (between 200 and 299) + """ if not 200 <= status_code < 300: msg = self._formatMessage(msg, "%s is not a success status" % safe_repr(status_code)) raise self.failureExecption(msg) def assert3XX(self, status_code, msg=None): + """ + Assert that the given value is a redirection status (between 300 and 399) + """ if not 300 <= status_code < 400: msg = self._formatMessage(msg, "%s is not a redirection status" % safe_repr(status_code)) raise self.failureExecption(msg) def assert4XX(self, status_code, msg=None): + """ + Assert that the given value is a client error status (between 400 and 499) + """ if not 400 <= status_code < 500: msg = self._formatMessage(msg, "%s is not a client error status" % safe_repr(status_code)) raise self.failureExecption(msg) def assert5XX(self, status_code, msg=None): + """ + Assert that the given value is a server error status (between 500 and 599) + """ if not 500 <= status_code < 600: msg = self._formatMessage(msg, "%s is not a server error status" % safe_repr(status_code)) raise self.failureExecption(msg)