From 5644e26a85983cb04984ae2a2437c787d8205729 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Thu, 24 Oct 2013 21:15:44 -0400 Subject: [PATCH] Improved unit tests --- .../presentations/lib/powerpointcontroller.py | 4 +- .../presentations/lib/pptviewcontroller.py | 4 +- .../lib/presentationcontroller.py | 19 ++--- .../presentations/test_impresscontroller.py | 71 ++++++++---------- .../test_powerpointcontroller.py | 72 ++++++++++++++----- .../test_powerpointviewercontroller.py | 65 ++++++++++++++--- .../test_presentationcontroller.py | 41 ++++++----- 7 files changed, 177 insertions(+), 99 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index a3bfd3d85..5087a3bd7 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -326,7 +326,6 @@ class PowerpointDocument(PresentationDocument): """ titles = [] notes = [] - num = 0 for slide in self.presentation.Slides: try: text = slide.Shapes.Title.TextFrame.TextRange.Text @@ -334,12 +333,11 @@ class PowerpointDocument(PresentationDocument): log.exception(e) text = '' titles.append(text.replace('\n',' ').replace('\x0b',' ') + '\n') - num += 1 note = _get_text_from_shapes(slide.NotesPage.Shapes) if len(note) == 0: note = ' ' notes.append(note) - self.save_titles_and_notes(titles,notes) + self.save_titles_and_notes(titles,notes) return def _get_text_from_shapes(shapes): diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index d6de47e69..e6ae7c143 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -157,9 +157,11 @@ class PptviewDocument(PresentationDocument): and the notes to 'slideNotes[x].txt' in the thumbnails directory """ + titles = None + notes = None filename = os.path.normpath(self.filepath) # let's make sure we have a valid zipped presentation - if zipfile.is_zipfile(filename): + if os.path.exists(filename) and zipfile.is_zipfile(filename): namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main", "a": "http://schemas.openxmlformats.org/drawingml/2006/main"} diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 196a51dcb..ead64f2fe 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -322,15 +322,16 @@ class PresentationDocument(object): Performs the actual persisting of titles to the titles.txt and notes to the slideNote%.txt """ - titlesfile = os.path.join(self.get_thumbnail_folder(), 'titles.txt') - with open(titlesfile, mode='w') as fo: - fo.writelines(titles) - for num in range(len(notes)): - notesfile = os.path.join(self.get_thumbnail_folder(), - 'slideNotes%d.txt' % (num+1)) - with open(notesfile, mode='w') as fn: - fn.write(notes[num]) - + if titles: + titlesfile = os.path.join(self.get_thumbnail_folder(), 'titles.txt') + with open(titlesfile, mode='w') as fo: + fo.writelines(titles) + if notes: + for slide_no, note in enumerate(notes): + notesfile = os.path.join(self.get_thumbnail_folder(), + 'slideNotes%d.txt' % (slide_no+1)) + with open(notesfile, mode='w') as fn: + fn.write(notes[slide_no]) class PresentationController(object): """ diff --git a/tests/functional/openlp_plugins/presentations/test_impresscontroller.py b/tests/functional/openlp_plugins/presentations/test_impresscontroller.py index ef0628a87..bd91207ed 100644 --- a/tests/functional/openlp_plugins/presentations/test_impresscontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_impresscontroller.py @@ -45,16 +45,6 @@ class TestLibModule(TestCase): self.ppc = ImpressController(mocked_plugin) self.doc = ImpressDocument(self.ppc,self.file_name) - def verify_installation(self): - """ - Test the installation of ImpressViewer - """ - # GIVEN: A boolean value set to true - # WHEN: We "convert" it to a bool - isInstalled = self.ppc.check_available() - # THEN: We should get back a True bool - assert isInstalled is True, 'The result should be True' - def create_titles_and_notes_test(self): """ Test ImpressDocument.create_titles_and_notes @@ -76,38 +66,6 @@ class TestLibModule(TestCase): # THEN: save_titles_and_notes should have been called once with two arrays of two elements self.doc.save_titles_and_notes.assert_called_once_with(['\n','\n'],[' ',' ']) - def _mock_a_LibreOffice_document(self,pageCount,noteCount,textCount): - pages = MagicMock() - page = MagicMock() - pages.getByIndex.return_value = page - notesPage = MagicMock() - notesPage.getCount.return_value = noteCount - shape = MagicMock() - shape.supportsService.return_value = True - shape.getString.return_value = 'Note' - notesPage.getByIndex.return_value = shape - page.getNotesPage.return_value = notesPage - page.getCount.return_value = textCount - #pageShape.getString.return_value = 'Title' - #pageShape.getString.side_effect = self._get_string_side_effect - #page.getByIndex.return_value = pageShape - page.getByIndex.side_effect = self._get_page_shape_side_effect - pages.getCount.return_value = pageCount - document = MagicMock() - document.getDrawPages.return_value = pages - document.getByIndex.return_value = page - return document - - def _get_page_shape_side_effect(*args, **kwargs): - pageShape = MagicMock() - pageShape.supportsService.return_value = True - if args[1] == 0: - pageShape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape' - pageShape.getString.return_value = 'Title' - else: - pageShape.getString.return_value = 'String' - return pageShape - def get_text_from_page_out_of_bound_test(self): """ Test ImpressDocument.__get_text_from_page with out-of-bounds index @@ -158,3 +116,32 @@ class TestLibModule(TestCase): result = self.doc._ImpressDocument__get_text_from_page(1,TextType.SlideText) # THEN: result should be 'Title\nString\nString\n' assert result == 'Title\nString\nString\n', 'Result should be exactly \'Title\\nString\\nString\\n\'' + + def _mock_a_LibreOffice_document(self,pageCount,noteCount,textCount): + pages = MagicMock() + page = MagicMock() + pages.getByIndex.return_value = page + notesPage = MagicMock() + notesPage.getCount.return_value = noteCount + shape = MagicMock() + shape.supportsService.return_value = True + shape.getString.return_value = 'Note' + notesPage.getByIndex.return_value = shape + page.getNotesPage.return_value = notesPage + page.getCount.return_value = textCount + page.getByIndex.side_effect = self._get_page_shape_side_effect + pages.getCount.return_value = pageCount + document = MagicMock() + document.getDrawPages.return_value = pages + document.getByIndex.return_value = page + return document + + def _get_page_shape_side_effect(*args, **kwargs): + pageShape = MagicMock() + pageShape.supportsService.return_value = True + if args[1] == 0: + pageShape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape' + pageShape.getString.return_value = 'Title' + else: + pageShape.getString.return_value = 'String' + return pageShape diff --git a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py index 7a7f5b4d3..dbc210cc8 100644 --- a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py @@ -32,7 +32,7 @@ Functional tests to test the PowerPointController class and related methods. from unittest import TestCase import os from mock import MagicMock, patch -from openlp.plugins.presentations.lib.powerpointcontroller import PowerpointController, PowerpointDocument +from openlp.plugins.presentations.lib.powerpointcontroller import PowerpointController, PowerpointDocument, _get_text_from_shapes TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) @@ -44,9 +44,9 @@ class TestLibModule(TestCase): self.ppc = PowerpointController(mocked_plugin) self.file_name = os.path.join(TEST_PATH,"test.pptx") self.doc = PowerpointDocument(self.ppc,self.file_name) - self.doc.presentation_deleted() - - def verify_installation_test(self): + + # add _test to the name to enable + def verify_installation(self): """ Test the installation of Powerpoint """ @@ -70,20 +70,58 @@ class TestLibModule(TestCase): # THEN: result should be true assert result is True, u'The result should be True' - def verify_titles_test(self): + def create_titles_and_notes_test(self): """ - Test reading the titles from PowerPoint + Test creating the titles from PowerPoint """ - # GIVEN: + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides self.doc = PowerpointDocument(self.ppc,self.file_name) - self.doc.load_presentation() - self.doc.create_titles_and_notes() - #self.doc.load_presentation() + self.doc.save_titles_and_notes = MagicMock() + self.doc._PowerpointDocument__get_text_from_shapes = MagicMock() + slide = MagicMock() + slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText' + pres = MagicMock() + pres.Slides = [slide,slide] + self.doc.presentation = pres # WHEN reading the titles and notes - titles,notes = self.doc.get_titles_and_notes() - print("titles: ".join(titles)) - print("notes: ".join(notes)) - # THEN there should be exactly 5 titles and 5 notes - assert len(titles)==5, u'There should be five titles' - assert len(notes)==5, u'Theres should be five notes' - \ No newline at end of file + self.doc.create_titles_and_notes() + # THEN the save should have been called exactly once with 2 titles and 2 notes + self.doc.save_titles_and_notes.assert_called_once_with(['SlideText\n', 'SlideText\n'], [' ', ' ']) + + def create_titles_and_notes_with_no_slides_test(self): + """ + Test creating the titles from PowerPoint when it returns no slides + """ + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides + self.doc = PowerpointDocument(self.ppc,self.file_name) + self.doc.save_titles_and_notes = MagicMock() + self.doc._PowerpointDocument__get_text_from_shapes = MagicMock() + pres = MagicMock() + pres.Slides = [] + self.doc.presentation = pres + # WHEN reading the titles and notes + self.doc.create_titles_and_notes() + # THEN the save should have been called exactly once with empty titles and notes + self.doc.save_titles_and_notes.assert_called_once_with([], []) + + def get_text_from_shapes_test(self): + """ + Test getting text from powerpoint shapes + """ + # GIVEN: mocked + shape = MagicMock() + shape.PlaceholderFormat.Type = 2 + shape.HasTextFrame = shape.TextFrame.HasText = True + shape.TextFrame.TextRange.Text = 'slideText' + shapes = [shape,shape] + result = _get_text_from_shapes(shapes) + assert result == 'slideText\nslideText\n' + + def get_text_from_shapes_with_no_shapes_test(self): + """ + Test getting text from powerpoint shapes with no shapes + """ + # GIVEN: mocked + shapes = [] + result = _get_text_from_shapes(shapes) + assert result == '' diff --git a/tests/functional/openlp_plugins/presentations/test_powerpointviewercontroller.py b/tests/functional/openlp_plugins/presentations/test_powerpointviewercontroller.py index 398cb4209..bb7bf3b44 100644 --- a/tests/functional/openlp_plugins/presentations/test_powerpointviewercontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_powerpointviewercontroller.py @@ -31,7 +31,7 @@ Functional tests to test the PptviewController class and related methods. """ from unittest import TestCase import os -from mock import MagicMock, patch +from mock import MagicMock, patch, mock_open from openlp.plugins.presentations.lib.pptviewcontroller import PptviewController, PptviewDocument TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) @@ -44,10 +44,8 @@ class TestLibModule(TestCase): self.ppc = PptviewController(mocked_plugin) self.file_name = os.path.join(TEST_PATH,"test.pptx") self.doc = PptviewDocument(self.ppc,self.file_name) - self.doc.presentation_deleted() - #add _test to the function - # I don't haver powerpointviewer to verify + #add _test to the function name to enable test def verify_installation(self): """ Test the installation of PowerpointViewer @@ -58,7 +56,7 @@ class TestLibModule(TestCase): # THEN: We should get back a True bool assert isInstalled is True, u'The result should be True' - # add _test to the following if necessary + # add _test to the following if necessary to enable test # I don't have powerpointviewer to verify def verify_loading_document(self): """ @@ -71,9 +69,10 @@ class TestLibModule(TestCase): self.doc.load_presentation() result = self.doc.is_loaded() # THEN: result should be true - assert result is True, u'The result should be True' + assert result is True, 'The result should be True' - def verify_titles_test(self): + # disabled + def verify_titles(self): """ Test reading the titles from PowerpointViewer """ @@ -85,6 +84,52 @@ class TestLibModule(TestCase): print("titles: ".join(titles)) print("notes: ".join(notes)) # THEN there should be exactly 5 titles and 5 notes - assert len(titles)==5, u'There should be five titles' - assert len(notes)==5, u'Theres should be five notes' - \ No newline at end of file + assert len(titles)==5, 'There should be five titles' + assert len(notes)==5, 'Theres should be five notes' + + def create_titles_and_notes_test(self): + """ + Test PowerpointController.create_titles_and_notes + """ + # GIVEN: mocked PresentationController.save_titles_and_notes + self.doc.save_titles_and_notes = MagicMock() + # WHEN reading the titles and notes + self.doc.create_titles_and_notes() + # THEN save_titles_and_notes should have been called once with empty arrays + self.doc.save_titles_and_notes.assert_called_once_with(['Test 1\n', '\n', 'Test 2\n', 'Test 4\n', 'Test 3\n'], ['Notes for slide 1', 'Inserted', 'Notes for slide 2', 'Notes \nfor slide 4', 'Notes for slide 3']) + + def create_titles_and_notes_nonexistent_file_test(self): + """ + Test PowerpointController.create_titles_and_notes with nonexistent file + """ + # GIVEN: mocked PresentationController.save_titles_and_notes and an nonexistent file + with patch('builtins.open') as mocked_open, \ + patch('openlp.plugins.presentations.lib.pptviewcontroller.os.path.exists') as mocked_exists: + mocked_exists.return_value = False + self.doc = PptviewDocument(self.ppc,'Idontexist.pptx') + self.doc.save_titles_and_notes = MagicMock() + # WHEN: reading the titles and notes + self.doc.create_titles_and_notes() + # THEN: + self.doc.save_titles_and_notes.assert_called_once_with(None,None) + mocked_exists.assert_any_call('Idontexist.pptx') + + def create_titles_and_notes_invalid_file_test(self): + """ + Test PowerpointController.create_titles_and_notes with invalid file + """ + # GIVEN: mocked PresentationController.save_titles_and_notes and an invalid file + with patch('builtins.open', mock_open(read_data='this is a test')) as mocked_open, \ + patch('openlp.plugins.presentations.lib.pptviewcontroller.os.path.exists') as mocked_exists, \ + patch('openlp.plugins.presentations.lib.pptviewcontroller.zipfile.is_zipfile') as mocked_is_zf: + mocked_is_zf.return_value = False + mocked_exists.return_value = True + mocked_open.filesize = 10 + self.doc = PptviewDocument(self.ppc,os.path.join(TEST_PATH,"test.ppt")) + self.doc.save_titles_and_notes = MagicMock() + # WHEN: reading the titles and notes + self.doc.create_titles_and_notes() + # THEN: + self.doc.save_titles_and_notes.assert_called_once_with(None,None) + assert mocked_is_zf.call_count == 1 + \ No newline at end of file diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py index 2b393030b..ce908b800 100644 --- a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py @@ -27,7 +27,8 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -Functional tests to test the Impress class and related methods. +Functional tests to test the PresentationController and PresentationDocument +classes and related methods. """ from unittest import TestCase import os @@ -48,20 +49,25 @@ class TestLibModule(TestCase): Test PresentationDocument.save_titles_and_notes method with two valid lists """ # GIVEN: two lists of length==2 and a mocked open and get_thumbnail_folder - with patch('builtins.open') as mocked_open, \ + mocked_open = mock_open() + with patch('builtins.open', mocked_open), \ patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \ as mocked_get_thumbnail_folder: - t = ['uno', 'dos'] - n = ['one', 'two'] + titles = ['uno', 'dos'] + notes = ['one', 'two'] # WHEN: calling save_titles_and_notes mocked_get_thumbnail_folder.return_value = 'test' - self.document.save_titles_and_notes(t,n) + self.document.save_titles_and_notes(titles,notes) # THEN: the last call to open should have been for slideNotes2.txt - mocked_open.assert_called_with( - os.path.join('test','slideNotes2.txt'), mode='w') + mocked_open.assert_any_call(os.path.join('test','titles.txt'), mode='w') + mocked_open.assert_any_call(os.path.join('test','slideNotes1.txt'), mode='w') + mocked_open.assert_any_call(os.path.join('test','slideNotes2.txt'), mode='w') assert mocked_open.call_count == 3, 'There should be exactly three files opened' + mocked_open().writelines.assert_called_once_with(['uno','dos']) + mocked_open().write.assert_called_any('one') + mocked_open().write.assert_called_any('two') - def save_titles_and_notes_with_None_and_empty_test(self): + def save_titles_and_notes_with_None_test(self): """ Test PresentationDocument.save_titles_and_notes method with no data """ @@ -69,14 +75,13 @@ class TestLibModule(TestCase): with patch('builtins.open') as mocked_open, \ patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \ as mocked_get_thumbnail_folder: - t = None - n = [] + titles = None + notes = None # WHEN: calling save_titles_and_notes mocked_get_thumbnail_folder.return_value = 'test' - self.document.save_titles_and_notes(t,n) - # THEN: the one and only call to open should have been for titles.txt - mocked_open.assert_called_once_with( - os.path.join('test','titles.txt'), mode='w') + self.document.save_titles_and_notes(titles,notes) + # THEN: No file should have been created + assert mocked_open.call_count == 0, 'No file should be created' def get_titles_and_notes_test(self): @@ -97,9 +102,11 @@ class TestLibModule(TestCase): assert len(result_titles) == 2 assert type(result_notes) is list assert len(result_notes) == 2 - assert mocked_open.call_count == 3 - mocked_open.assert_called_with(os.path.join('test','slideNotes2.txt')) - assert mocked_exists.call_count == 3 + assert mocked_open.call_count == 3, 'Three files should be opened' + mocked_open.assert_any_call(os.path.join('test','titles.txt')) + mocked_open.assert_any_call(os.path.join('test','slideNotes1.txt')) + mocked_open.assert_any_call(os.path.join('test','slideNotes2.txt')) + assert mocked_exists.call_count == 3, 'Three files should have been checked' def get_titles_and_notes_with_file_not_found_test(self): """