def test_check_client_settings_with_settings(self): client = Client({ 'foo': {'transport': {'path': 'pysoa.test.stub_service:StubClientTransport'}}, 'bar': {'transport': {'path': 'pysoa.test.stub_service:StubClientTransport'}}, 'baz': {'transport': {'path': 'pysoa.test.stub_service:StubClientTransport'}}, 'qux': {'transport': {'path': 'pysoa.test.stub_service:StubClientTransport'}}, }) action_request = EnrichedActionRequest(action='status', body={}, switches=None, client=client) baz_body = { 'conformity': '1.2.3', 'pysoa': '1.0.2', 'python': '3.7.4', 'version': '9.7.8', } with stub_action('foo', 'status') as foo_stub,\ stub_action('bar', 'status', errors=[Error('BAR_ERROR', 'Bar error')]),\ stub_action('baz', 'status', body=baz_body),\ stub_action('qux', 'status') as qux_stub: foo_stub.return_value = JobResponse(errors=[Error('FOO_ERROR', 'Foo error')]) qux_stub.side_effect = MessageReceiveTimeout('Timeout calling qux') response = _CheckOtherServicesAction()(action_request) self.assertIsInstance(response, ActionResponse) self.assertEqual(six.text_type(conformity.__version__), response.body['conformity']) self.assertEqual(six.text_type(pysoa.__version__), response.body['pysoa']) self.assertEqual(six.text_type(platform.python_version()), response.body['python']) self.assertEqual('8.71.2', response.body['version']) self.assertIn('healthcheck', response.body) self.assertEqual([], response.body['healthcheck']['warnings']) self.assertIn( ('FOO_CALL_ERROR', six.text_type([Error('FOO_ERROR', 'Foo error')])), response.body['healthcheck']['errors'], ) self.assertIn( ('BAR_STATUS_ERROR', six.text_type([Error('BAR_ERROR', 'Bar error')])), response.body['healthcheck']['errors'], ) self.assertIn( ('QUX_TRANSPORT_ERROR', 'Timeout calling qux'), response.body['healthcheck']['errors'], ) self.assertEqual(3, len(response.body['healthcheck']['errors'])) self.assertEqual( { 'services': { 'baz': { 'conformity': '1.2.3', 'pysoa': '1.0.2', 'python': '3.7.4', 'version': '9.7.8', }, }, }, response.body['healthcheck']['diagnostics'], )
def _start_stubbed_actions(test_target): if 'stubbed_actions' in test_target: # We must start the stubs in a predictable order... for service, action in sorted(six.iterkeys(test_target['stubbed_actions'])): stub_config = test_target['stubbed_actions'][service, action] if 'errors' in stub_config: stub = stub_action(service, action, errors=[Error(**e) for e in stub_config['errors']]) else: stub = stub_action(service, action, body=stub_config.get('body', {})) mock_action = stub.start() stub_config['started_stub'] = stub stub_config['mock_action'] = mock_action
def test_one_stub_as_context_manager_with_body(self): with stub_action('test_service', 'test_action_1', body={'value': 1}) as stub_test_action_1: response = self.client.call_action('test_service', 'test_action_1') self.assertEqual({'value': 1}, response.body) self.assertEqual(1, stub_test_action_1.call_count) self.assertEqual({}, stub_test_action_1.call_body) stub_test_action_1.assert_called_once_with({})
def _do_stub( service, # type: six.text_type action, # type: six.text_type body=None, # type: Optional[Body] errors=None, # type: Optional[Errors] side_effect=None, # type: Optional[Union[Body, ActionError, Callable[[Body], Body]]] ): # type: (...) -> mock.MagicMock stubby = stub_action(service, action, body, errors, side_effect) # type: stub_action stubbies.append(stubby) return stubby.__enter__()
def stub_test_action(add_extra=True): def _run(body, **kwargs): if add_extra and body.get('type') == 'admin': body['extra'] = 'data' return body return stub_action( 'test_service', 'test_action', side_effect=_run, )
def test_using_start_stop(self): action_stubber = stub_action('test_service', 'test_action_1') stubbed_action = action_stubber.start() stubbed_action.return_value = {'what about': 'this'} response = self.client.call_action('test_service', 'test_action_1', {'burton': 'guster', 'sean': 'spencer'}) self.assertEqual({'what about': 'this'}, response.body) self.assertEqual(1, stubbed_action.call_count) self.assertEqual({'burton': 'guster', 'sean': 'spencer'}, stubbed_action.call_body) stubbed_action.assert_called_once_with({'burton': 'guster', 'sean': 'spencer'}) action_stubber.stop()
def test_one_stub_as_context_manager_with_real_call_handled(self): with stub_action('test_service', 'test_action_1', body={'value': 1}) as stub_test_action_1: response = self.client.call_action('test_service', 'test_action_1') self.assertEqual(response.body, {'value': 1}) response = self.secondary_stub_client.call_action('cat', 'meow') self.assertEqual({'type': 'squeak'}, response.body) response = self.secondary_stub_client.call_action('dog', 'bark') self.assertEqual({'sound': 'woof'}, response.body) self.assertEqual(1, stub_test_action_1.call_count) self.assertEqual({}, stub_test_action_1.call_body)
def test_two_stubs_different_services_split(self, stub_test_action_1): stub_test_action_1.return_value = {'value': 1} with stub_action('test_another_service', 'test_action_2') as stub_test_action_2: stub_test_action_2.return_value = {'another_value': 2} response = self.client.call_action('test_service', 'test_action_1') self.assertEqual({'value': 1}, response.body) response = self.client.call_action('test_another_service', 'test_action_2', {'input_attribute': True}) self.assertEqual({'another_value': 2}, response.body) self.assertEqual(1, stub_test_action_1.call_count) self.assertEqual({}, stub_test_action_1.call_body) self.assertEqual(1, stub_test_action_2.call_count) self.assertEqual({'input_attribute': True}, stub_test_action_2.call_body)
def test_works_with_other_action_stubbed_as_context_manager(self, stub_test_action_2): stub_test_action_2.return_value = {'brown': 'cow'} with stub_action('test_service', 'test_action_1', body={'christmas': 'tree'}) as stub_test_action_1: response = self.client.call_action('test_service', 'test_action_1', {'which': 'decoration'}) self.assertEqual({'christmas': 'tree'}, response.body) response = self.client.call_action('test_service', 'test_action_2', {'how': 'now'}) self.assertEqual({'brown': 'cow'}, response.body) self.assertEqual(1, stub_test_action_1.call_count) self.assertEqual({'which': 'decoration'}, stub_test_action_1.call_body) stub_test_action_1.assert_called_once_with({'which': 'decoration'}) self.assertEqual(1, stub_test_action_2.call_count) self.assertEqual({'how': 'now'}, stub_test_action_2.call_body) stub_test_action_2.assert_called_once_with({'how': 'now'})
def _run_test_case(self, test_case, test_fixture, test_fixture_results, *_, **__): """ This does the actual work of running the test case. :param test_case: The directive instructions to run and assert this specific test case :type test_case: dict :param test_fixture: List of test cases in this fixture :type test_fixture: list :param test_fixture_results: List of all action-call results in the entire fixture :type test_fixture_results: list """ # noinspection PyUnusedLocal # This instructs the traceback manipulator that this frame belongs to _run_test_case, which is simpler than # having it analyze the code path details to determine the frame location. _run_test_case_frame = True # noqa F841 action_results = {} action_response_bodies = {} test_fixture_results.append(action_results) for action_path in test_case['actions']: action_name, action_index = action_path.split('.') action_case = test_case[action_path] if 'inputs' in action_case: substitute_variables(action_case['inputs'], action_response_bodies, self.model_constants) if 'job_control_inputs' in action_case: substitute_variables(action_case['job_control_inputs'], action_response_bodies, self.model_constants) if 'job_context_inputs' in action_case: substitute_variables(action_case['job_context_inputs'], action_response_bodies, self.model_constants) self.set_up_test_case_action(action_name, action_case, test_case, test_fixture) self._run_directive_hook('set_up_test_case_action', action_name, action_case, test_case, test_fixture) stub_context = self._WrapperContextManager() # it's a no-op with no arguments if ( action_name not in self.server_class.action_class_map and # if the server doesn't have this action action_name not in ('status', 'introspect') and # if the action isn't one of the built-in actions hasattr(self, '_process_stub_action_{}'.format(action_name)) # if the test job has a mock action ): # Hook for custom, test-only actions that are not real commands on the service. Custom actions must # must work the same as side-effect functions on stub_action (must accept a request body dict and # return a response body dict, `ActionResponse`, or `JobResponse` or raise an `ActionError` or # `JobError`). stub_context = self._WrapperContextManager( stub_action(self.server_class.service_name, action_name), getattr(self, '_process_stub_action_{}'.format(action_name)), ) with stub_context: job_response = self.client.call_actions( service_name=self.server_class.service_name, actions=[{'action': action_name, 'body': action_case.get('inputs', {})}], raise_job_errors=False, raise_action_errors=False, context=action_case.get('job_context_inputs', {}), control_extra=action_case.get('job_control_inputs', {}), ) action_results[action_path] = job_response.actions[0] if job_response.actions else None action_response_bodies[action_path] = job_response.actions[0].body if job_response.actions else None substitute_variables(action_response_bodies, action_response_bodies, self.model_constants) substitute_variables(action_case, action_response_bodies, self.model_constants) try: self._run_directive_hook( 'assert_test_case_action_results', action_name, action_case, test_case, test_fixture, action_results[action_path], job_response, action_path, ) finally: try: self._run_directive_hook( 'tear_down_test_case_action', action_name, action_case, test_case, test_fixture, ) finally: self.tear_down_test_case_action(action_name, action_case, test_case, test_fixture) self._run_directive_hook('assert_test_case_results', action_results, test_case, test_fixture)
def _do_stub(*args, **kwargs): stubby = stub_action(*args, **kwargs) stubbies.append(stubby) return stubby.__enter__()