def setUp(self): # Mock shutil shutil_patcher = patch('runner.data_processing.shutil') self.addCleanup(shutil_patcher.stop) self.mock_shutil = shutil_patcher.start() # Patch audit runner instance in order to silence its initialization # errors regarding having a concrete `file_manager` object. self.mock_file_manager= Mock(spec=types.FunctionType) file_manager_patcher = patch.object( AuditRunnerProvider, 'file_manager', new=self.mock_file_manager, create=True, ) self.addCleanup(file_manager_patcher.stop) self.mock_file_manager = file_manager_patcher.start() # Patch AuditRunner's extension attribute ext_patcher = patch.object( AuditRunnerProvider, 'extension', new='test', create=True, ) self.addCleanup(ext_patcher.stop) self.mock_extension = ext_patcher.start() # Use this runner implementation for the next tests self.initial_data = [('doctype1','file/path/1'),('doctype2','file/path/2')] self.runner = AuditRunnerProvider(self.initial_data)
class AuditRunnerTestCase(TestCase): def setUp(self): # Mock shutil shutil_patcher = patch('runner.data_processing.shutil') self.addCleanup(shutil_patcher.stop) self.mock_shutil = shutil_patcher.start() # Patch audit runner instance in order to silence its initialization # errors regarding having a concrete `file_manager` object. self.mock_file_manager= Mock(spec=types.FunctionType) file_manager_patcher = patch.object( AuditRunnerProvider, 'file_manager', new=self.mock_file_manager, create=True, ) self.addCleanup(file_manager_patcher.stop) self.mock_file_manager = file_manager_patcher.start() # Patch AuditRunner's extension attribute ext_patcher = patch.object( AuditRunnerProvider, 'extension', new='test', create=True, ) self.addCleanup(ext_patcher.stop) self.mock_extension = ext_patcher.start() # Use this runner implementation for the next tests self.initial_data = [('doctype1','file/path/1'),('doctype2','file/path/2')] self.runner = AuditRunnerProvider(self.initial_data) def test_instantiation(self): """ Concrete runner should be instantiated with a raw file list, which will be stored at `self.raw_files` """ self.assertEqual( self.initial_data, self.runner.raw_files ) def test_run_calls_anciliary_methods(self): "runner.run must call a series of anciliary methods" # patch anciliary methods with patch.multiple(self.runner, organize_files=DEFAULT, process_data=DEFAULT, post_process=DEFAULT): self.runner.run() # Check calls on anciliary methods self.runner.organize_files.assert_called_once_with() self.runner.process_data.assert_called_once_with() self.runner.post_process.assert_called_once_with() def test_organize_files_dispatches_file_manager_function(self): # Use a fake return value to avoid runtime errors self.mock_file_manager.return_value = {'fake': 'files'} self.runner.organize_files() self.mock_file_manager.assert_called_once_with() def test_provides_files_at_runtime(self): """ At audit runtime, the runner instance must have a `self.files` attribute. """ self.runner.organize_files() self.assertEqual( self.runner.files, self.mock_file_manager.return_value ) @skip('not a priority right now') def test_organize_files_handles_errors_from_file_manager(self): pass @patch('runner.data_processing.TemporaryDirectory') def test_provides_temporary_workspace_at_runtime(self, mock_tempdir): """ A temporary directory must be created and assigned to runner.workspace at audit runtime. """ # Mocks for the TemporaryDirectory context manager enter_handler = mock_tempdir.return_value.__enter__ exit_handler = mock_tempdir.return_value.__exit__ with patch.multiple( self.runner, organize_files=DEFAULT, process_data=DEFAULT, ): # Inject an assertion about runner.workspace state, to be verified # when runner.process_data gets called. self.runner.process_data.side_effect = ( lambda: self.assertEqual( self.runner.workspace, enter_handler.return_value, # this is the tempdir path "runner.workspace must point to a tempdir at runtime" ) ) self.runner.run() # Assert TemporaryDirectory was called as a context manager enter_handler.assert_called_once_with() exit_handler.assert_called_once_with(None, None, None) def test_report_file_is_persisted_elsewhere(self): """ `shutil.move` must be called using the filepath from runner.output and runner.report_path. """ mock_output = Mock(return_value='new_file_path') with patch.multiple( self.runner, organize_files=DEFAULT, process_data=DEFAULT, ): self.runner.run() self.mock_shutil.move.assert_called_once_with( src=self.runner.output, dst=self.runner.report_path ) def test_runner_keeps_reference_to_report_path(self): """ The runner instance keeps a reference to the report final after the data processing phase. """ with patch.multiple(self.runner, organize_files=DEFAULT, process_data=DEFAULT): self.assertIsNone(self.runner.report_path) self.runner.run() self.assertIsNotNone(self.runner.report_path)