예제 #1
0
    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'],
        )
예제 #2
0
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
예제 #3
0
    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({})
예제 #4
0
 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__()
예제 #5
0
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,
    )
예제 #6
0
    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()
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
    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'})
예제 #10
0
    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)
예제 #11
0
 def _do_stub(*args, **kwargs):
     stubby = stub_action(*args, **kwargs)
     stubbies.append(stubby)
     return stubby.__enter__()