Exemple #1
0
    def setUp(self):
        self.component_manager = ComponentManager()
        self.component_manager.clear_component_registry()
        component(scope='session')(TestTestRunnerComponents.Verifier)
        self.load_components()
        self.verifier = TestTestRunnerComponents.Verifier()
        self.parent_scope = Scope('session', None)
        self.parent_scope.register_instance(
            _InstanceId(TestTestRunnerComponents.Verifier, ()), self.verifier)
        self.run_queue = []
        self.messagebus = Mock()

        def send_request(message_id,
                         endpoint_id=None,
                         entities=None,
                         data=None):
            futures = Mock()
            if message_id == SCHEDULE_NEXT_TEST:
                future = Mock()
                if self.run_queue:
                    future.result.return_value = self.run_queue.pop(0)
                else:
                    future.result.return_value = None

                futures.wait.return_value = [future]
            return futures

        self.messagebus.send_request.side_effect = send_request
        self.tr = TestRunner(self.messagebus,
                             Factory(self.component_manager),
                             'suite-name',
                             parent_scope=self.parent_scope)
Exemple #2
0
 def test_throws_on_unexpected_exit_code(self):
     with _create_harness(ConfigManager()) as harness:
         scope = Scope(name='myscope')
         exec = harness.component_factory.call(DockerContainerExec, scope)
         harness.node._container.exec.return_value = ('stdout', 'stderr', 1)
         with self.assertRaises(DockerError):
             exec.send_line('command', expected_exit_code=0)
Exemple #3
0
    def init_component_handling(self, components):
        self.component_registry = create_registry()
        self.component_manager = ComponentManager(self.component_registry)
        self.component_factory = Factory(self.component_manager)
        self.messagebus = MessageBus(self.component_factory, Scope('session'))

        components.append(
            ComponentMock(name='ComponentFactory',
                          mock=self.component_factory))
        components.append(
            ComponentMock(name='MessageBus', mock=self.messagebus))
        components.append(ComponentMock(name='Config', mock=self.config))
        components.append(
            ComponentMock(name='ComponentManager',
                          mock=self.component_manager))
        components.append(
            ComponentMock(name='ExtensionManager', mock=MagicMock()))
        for comp in components:
            if type(comp) == ComponentMock:
                component(name=comp.name,
                          scope=comp.scope,
                          can=comp.can,
                          provided_by_extension=comp.provided_by_extension)(
                              comp, self.component_manager)
            else:
                self.component_manager.register_component(comp)
Exemple #4
0
 def test_with_extended_process_information(self):
     with _create_harness(ConfigManager()) as harness:
         scope = Scope(name='myscope')
         exec = harness.component_factory.call(DockerContainerExec, scope)
         harness.node._container.exec.return_value = ('stdout', 'stderr', 0)
         self.assertEqual(
             exec.send_line('command', extended_process_information=True),
             ('stdout', 'stderr', 0))
Exemple #5
0
    def test_maximum_config(self):
        config = ConfigManager()
        config.set(SUT, ['mysut'])
        config.set(SUT_DOCKER_IMAGE_ID, 'myimage', entity='mysut')
        config.set(DOCKER_IMAGES_IDS, ['myimage', 'myotherimage'])
        config.set(DOCKER_IMAGES_REPOSITORY, 'repository', entity='myimage')
        config.set(DOCKER_IMAGES_TAG, 'v1', entity='myimage')
        config.set(DOCKER_IMAGES_ENVIRONMENT, ['KEY=value'], entity='myimage')
        config.set(DOCKER_IMAGES_HOSTNAME, 'myhostname', entity='myimage')
        config.set(DOCKER_IMAGES_MOUNT_POINTS, [
            'type=tmpfs,target=/foo',
            'type=volume,source=myvolume,target=/bar',
            'type=bind,source=/foo,target=/bar,readonly'
        ],
                   entity='myimage')
        config.set(DOCKER_IMAGES_NETWORK, 'mynetwork', entity='myimage')

        config.set(DOCKER_IMAGES_REPOSITORY,
                   'otherrepository',
                   entity='myotherimage')
        config.set(DOCKER_IMAGES_TAG, 'v2', entity='myotherimage')

        config.set(DOCKER_IMAGE_PULL, False)
        config.set(DOCKER_IMAGE_REGISTRY, 'registry/')
        config.set(DOCKER_IMAGE_STOP_TIMEOUT, 5)
        config.set(DOCKER_KEEP_RUNNING, True)

        with patch('virt.docker.Docker'):
            with _create_harness(config) as harness:
                harness.sut.entity = 'mysut'
                scope = Scope(name='myscope')
                node = harness.component_factory.call(DockerContainerNode,
                                                      scope)

        self.assertEqual(node._image_entity, 'myimage')
        self.assertEqual(node._repository, 'repository')
        self.assertEqual(node._tag, 'v1')
        self.assertEqual(node._environment, {'KEY': 'value'})
        self.assertEqual(node._hostname, 'myhostname')
        self.assertEqual(node._mounts[0]['Source'], None)
        self.assertEqual(node._mounts[0]['Target'], '/foo')
        self.assertEqual(node._mounts[0]['Type'], 'tmpfs')
        self.assertEqual(node._mounts[0]['ReadOnly'], False)
        self.assertEqual(node._mounts[1]['Source'], 'myvolume')
        self.assertEqual(node._mounts[1]['Target'], '/bar')
        self.assertEqual(node._mounts[1]['Type'], 'volume')
        self.assertEqual(node._mounts[1]['ReadOnly'], False)
        self.assertEqual(node._mounts[2]['Source'], '/foo')
        self.assertEqual(node._mounts[2]['Target'], '/bar')
        self.assertEqual(node._mounts[2]['Type'], 'bind')
        self.assertEqual(node._mounts[2]['ReadOnly'], True)
        self.assertEqual(node._networkname, 'mynetwork')
        self.assertEqual(node._image_name, 'repository:v1')
        self.assertEqual(node._timeout, 5)
        self.assertFalse(node._pull)
        self.assertEqual(node._registry, 'registry/')
        self.assertTrue(node._keep_running)
Exemple #6
0
    def test_make_forwards_all_exceptions(self):
        docker_run = Mock()

        scope = Scope('scope')
        with create_harness(docker_run) as harness:
            application = Mock()
            application.config = harness.config

            docker_run.run_in_docker.side_effect = Exception()
            with self.assertRaises(Exception):
                harness.component_factory.call(make, scope, application)
    def test_filter_out_component_with_shorter_scope_than_parent(self):
        @component(name='A',
                   scope='long',
                   component_manager=self.component_manager)
        def a1():
            pass

        @component(name='A',
                   scope='short',
                   component_manager=self.component_manager)
        def a2():
            pass

        @component(name='B',
                   scope='long',
                   component_manager=self.component_manager)
        @requires(a='A')
        def b():
            pass

        @requires(b='B')
        def test(b):
            pass

        long = Scope('long')
        short = Scope('short', parent=long)

        dependency_graph = self.builder.create_dependency_graph(
            test, short, None)
        dependency_graph.select_scopes(short)
        dependency_graph.remove_with_shorter_scope_than_parent(short)

        self.assertEqual(dependency_graph._root.callable, test)
        self.assertEqual(dependency_graph._root.requirements['b'].argument,
                         'b')
        callable_b = dependency_graph._root.requirements['b'].callables[0]
        self.assertEqual(callable_b.callable.__name__, 'b')
        self.assertEqual(callable_b.requirements['a'].argument, 'a')
        self.assertEqual(
            callable_b.requirements['a'].callables[0].callable.__name__, 'a1')
        self.assertEqual(len(callable_b.requirements['a'].callables), 1)
Exemple #8
0
    def test_make_triggers_pre_make_event_with_make_arguments_as_data(self):
        docker_run = Mock()

        scope = Scope('scope')
        with create_harness(docker_run) as harness:
            application = Mock()
            application.config = harness.config
            application.messagebus = harness.messagebus
            docker_run.docker_config = DockerConfig(harness.config)

            with LocalMessageQueue(harness.messagebus, [PRE_MAKE], [MAKE_ENDPOINT]) as queue:
                harness.component_factory.call(make, scope, application)
                self.assertEqual(queue.get(timeout=1).data, ('arg1', '--opt2'))
Exemple #9
0
    def test_shell_called_with_correct_parameters(self):
        docker_run = Mock()

        scope = Scope('scope')
        with create_harness(docker_run) as harness:
            application = Mock()
            application.config = harness.config

            docker_run.run_in_docker.return_value = 0
            exit_code = harness.component_factory.call(shell, scope,
                                                       application)

            self.assertEqual(exit_code, 0)
            docker_run.run_in_docker.assert_called_with(['/bin/bash'],
                                                        forward_signals=True)
Exemple #10
0
    def test_exec_called_with_correct_parameters(self):
        docker_run = Mock()

        scope = Scope('scope')
        with create_harness(docker_run) as harness:
            application = Mock()
            application.config = harness.config

            docker_run.run_in_docker.return_value = 0
            exit_code = harness.component_factory.call(exec, scope,
                                                       application)

            self.assertEqual(exit_code, 0)
            docker_run.run_in_docker.assert_called_with(
                ('exec', 'with', 'args'), forward_signals=False)
Exemple #11
0
    def test_make_command_taken_from_image(self):
        docker_run = Mock()

        scope = Scope('scope')
        with create_harness(docker_run, 'abs.u12') as harness:
            application = Mock()
            application.config = harness.config
            docker_run.docker_config = DockerConfig(harness.config)

            docker_run.run_in_docker.return_value = 0
            exit_code = harness.component_factory.call(make, scope, application)

            self.assertEqual(exit_code, 0)
            docker_run.run_in_docker.assert_called_with(
                ['make', 'arg1', '--opt2'], forward_signals=False)
Exemple #12
0
    def test_default_containername(self):
        config = ConfigManager()
        config.set(SUT, ['mysut'])
        config.set(SUT_DOCKER_IMAGE_ID, 'myimage', entity='mysut')
        config.set(DOCKER_IMAGES_IDS, ['myimage'])
        config.set(DOCKER_IMAGES_REPOSITORY, 'repository', entity='myimage')
        config.set(DOCKER_IMAGES_TAG, 'v1', entity='myimage')

        with patch('virt.docker.Docker'):
            with _create_harness(config) as harness:
                harness.sut.entity = 'mysut'
                scope = Scope(name='myscope')
                node = harness.component_factory.call(DockerContainerNode,
                                                      scope)

        self.assertIsNone(node.containername)
Exemple #13
0
    def test_docker_config_component_uses_config_values(self):
        scope = Scope('scope')

        config = ConfigManager()
        config.set(IMAGE_OPTION, 'abs.u16')
        config.set(TAG_OPTION, 'tag')
        config.set(REGISTRY_OPTION, 'registry')
        config.set(USE_REGISTRY_OPTION, False)
        config.set(REGISTRY_CACHE_OPTION, 'registry_cache')
        config.set(PULL_OPTION, False)
        config.set(HOSTNAME_OPTION, 'hostname')
        config.set(ENV_VARIABLES_OPTION, ['envvar'])
        config.set(MOUNTS_OPTION, ['mount'])
        config.set(ROOT_OPTION, True)
        config.set(ROOT_DIR_OPTION, 'root_dir')
        config.set(CONTAINER_ROOT_DIR_OPTION, 'container_root_dir')
        config.set(PROJECT_DIR_OPTION, 'project_dir')
        config.set(PROJECT_DIR_NAME_OPTION, 'project_dir_name')
        config.set(NETWORK_OPTION, 'network')

        with create_harness(config) as harness:

            @requires(docker_config='DockerConfig')
            def assert_docker_config(docker_config):
                self.assertEqual(docker_config.image, 'abs.u16')
                self.assertEqual(docker_config.tag, 'tag')
                self.assertEqual(docker_config.registry, 'registry')
                self.assertFalse(docker_config.use_registry)
                self.assertEqual(docker_config.registry_cache, 'registry_cache')
                self.assertFalse(docker_config.pull)
                self.assertEqual(docker_config.hostname, 'hostname')
                self.assertEqual(docker_config.env_variables, ('envvar', ))
                self.assertEqual(docker_config.mounts, ('mount', ))
                self.assertEqual(docker_config.root, True)
                self.assertEqual(docker_config.root_dir, 'root_dir')
                self.assertEqual(docker_config.container_root_dir, 'container_root_dir')
                self.assertEqual(docker_config.project_dir, 'project_dir')
                self.assertEqual(docker_config.project_dir_name, 'project_dir_name')
                self.assertEqual(docker_config.network, 'network')

            harness.component_factory.call(assert_docker_config, scope)
Exemple #14
0
    def test_iterable_sut_config_extends_image_config(self):
        config = ConfigManager()
        config.set(SUT, ['mysut'])
        config.set(SUT_DOCKER_IMAGE_ID, 'myimage', entity='mysut')
        config.set(DOCKER_IMAGES_IDS, ['myimage'])
        config.set(DOCKER_IMAGES_REPOSITORY, 'repository', entity='myimage')
        config.set(DOCKER_IMAGES_TAG, 'v1', entity='myimage')
        config.set(DOCKER_IMAGES_ENVIRONMENT, ['KEY=value', 'A=a'],
                   entity='myimage')
        config.set(DOCKER_IMAGES_MOUNT_POINTS, ['type=tmpfs,target=/foo'],
                   entity='myimage')
        config.set(SUT_DOCKER_IMAGE_ENVIRONMENT, ['SUT_KEY=sut_value', 'A=b'],
                   entity='mysut')
        config.set(SUT_DOCKER_IMAGE_MOUNT_POINTS, ['type=tmpfs,target=/bar'],
                   entity='mysut')

        with patch('virt.docker.Docker'):
            with _create_harness(config) as harness:
                harness.sut.entity = 'mysut'
                scope = Scope(name='myscope')
                node = harness.component_factory.call(DockerContainerNode,
                                                      scope)

        self.assertEqual(node._image_entity, 'myimage')
        self.assertEqual(node._repository, 'repository')
        self.assertEqual(node._tag, 'v1')
        self.assertEqual(
            node._environment,
            OrderedDict([('SUT_KEY', 'sut_value'), ('A', 'b'),
                         ('KEY', 'value')]))
        self.assertEqual(node._mounts[0]['Source'], None)
        self.assertEqual(node._mounts[0]['Target'], '/bar')
        self.assertEqual(node._mounts[0]['Type'], 'tmpfs')
        self.assertEqual(node._mounts[0]['ReadOnly'], False)
        self.assertEqual(node._mounts[1]['Source'], None)
        self.assertEqual(node._mounts[1]['Target'], '/foo')
        self.assertEqual(node._mounts[1]['Type'], 'tmpfs')
        self.assertEqual(node._mounts[1]['ReadOnly'], False)
Exemple #15
0
    def test_minimum_config(self):
        config = ConfigManager()
        config.set(SUT, ['mysut'])
        config.set(SUT_DOCKER_IMAGE_ID, 'myimage', entity='mysut')
        config.set(DOCKER_IMAGES_IDS, ['myimage'])
        config.set(DOCKER_IMAGES_REPOSITORY, 'repository', entity='myimage')
        config.set(DOCKER_IMAGES_TAG, 'v1', entity='myimage')

        with patch('virt.docker.Docker'):
            with _create_harness(config) as harness:
                harness.sut.entity = 'mysut'
                scope = Scope(name='myscope')
                node = harness.component_factory.call(DockerContainerNode,
                                                      scope)

        self.assertEqual(node._image_entity, 'myimage')
        self.assertEqual(node._repository, 'repository')
        self.assertEqual(node._tag, 'v1')
        self.assertEqual(node._hostname, None)
        self.assertEqual(node._image_name, 'repository:v1')
        self.assertEqual(node._timeout, 10)
        self.assertTrue(node._pull)
        self.assertFalse(node._keep_running)
Exemple #16
0
    def test_atomic_sut_config_overrides_image_config(self):
        config = ConfigManager()
        config.set(SUT, ['mysut'])
        config.set(SUT_DOCKER_IMAGE_ID, 'myimage', entity='mysut')
        config.set(DOCKER_IMAGES_IDS, ['myimage'])
        config.set(DOCKER_IMAGES_REPOSITORY, 'repository', entity='myimage')
        config.set(DOCKER_IMAGES_TAG, 'v1', entity='myimage')
        config.set(DOCKER_IMAGES_HOSTNAME, 'myhostname', entity='myimage')
        config.set(DOCKER_IMAGES_NETWORK, 'mynetwork', entity='myimage')
        config.set(SUT_DOCKER_IMAGE_HOSTNAME, 'mysuthostname', entity='mysut')
        config.set(SUT_DOCKER_IMAGE_NETWORK, 'mysutnetwork', entity='mysut')

        with patch('virt.docker.Docker'):
            with _create_harness(config) as harness:
                harness.sut.entity = 'mysut'
                scope = Scope(name='myscope')
                node = harness.component_factory.call(DockerContainerNode,
                                                      scope)

        self.assertEqual(node._image_entity, 'myimage')
        self.assertEqual(node._repository, 'repository')
        self.assertEqual(node._tag, 'v1')
        self.assertEqual(node._hostname, 'mysuthostname')
        self.assertEqual(node._networkname, 'mysutnetwork')
 def setUp(self):
     self.component_manager = ComponentManager(create_registry(),
                                               create_entity_map())
     self.registry = self.component_manager.COMPONENT_REGISTRY
     self.builder = DependencyGraphBuilder(self.registry)
     self.scope = Scope('scope')
Exemple #18
0
class TestTestRunnerComponents(unittest.TestCase):
    class Verifier(object):
        def __init__(self):
            self.data = []

    def load_components(self):
        @component()
        @requires(verifier='Verifier')
        class MyComponent(object):
            def __init__(self, verifier):
                self.verifier = verifier

            def __enter__(self):
                self.verifier.data.append('enter')
                return self

            def __exit__(self, exc_type, exc_val, exc_tb):
                self.verifier.data.append('exit')

            def __call__(self, *args, **kwargs):
                self.verifier.data.append('call')

        @component()
        @requires(verifier='Verifier')
        class MyEnterFailComponent(object):
            def __init__(self, verifier):
                self.verifier = verifier

            def __enter__(self):
                self.verifier.data.append('enter')
                raise (Exception('enter fails'))

            def __exit__(self, exc_type, exc_val, exc_tb):
                self.verifier.data.append('exit')

            def __call__(self, *args, **kwargs):
                self.verifier.data.append('call')

        @component()
        @requires(verifier='Verifier')
        class MyExitFailComponent(object):
            def __init__(self, verifier):
                self.verifier = verifier

            def __enter__(self):
                self.verifier.data.append('enter')
                return self

            def __exit__(self, exc_type, exc_val, exc_tb):
                self.verifier.data.append('exit')
                raise (Exception('exit fails'))

            def __call__(self, *args, **kwargs):
                self.verifier.data.append('call')

    def setUp(self):
        self.component_manager = ComponentManager()
        self.component_manager.clear_component_registry()
        component(scope='session')(TestTestRunnerComponents.Verifier)
        self.load_components()
        self.verifier = TestTestRunnerComponents.Verifier()
        self.parent_scope = Scope('session', None)
        self.parent_scope.register_instance(
            _InstanceId(TestTestRunnerComponents.Verifier, ()), self.verifier)
        self.run_queue = []
        self.messagebus = Mock()

        def send_request(message_id,
                         endpoint_id=None,
                         entities=None,
                         data=None):
            futures = Mock()
            if message_id == SCHEDULE_NEXT_TEST:
                future = Mock()
                if self.run_queue:
                    future.result.return_value = self.run_queue.pop(0)
                else:
                    future.result.return_value = None

                futures.wait.return_value = [future]
            return futures

        self.messagebus.send_request.side_effect = send_request
        self.tr = TestRunner(self.messagebus,
                             Factory(self.component_manager),
                             'suite-name',
                             parent_scope=self.parent_scope)

    def test_enters_and_exit_called_on_component_with_test_scope(self):
        @requires(comp='MyComponent', scope='test')
        def my_test_case(comp):
            comp()

        self.run_queue.append(TestCaseDefinition(my_test_case))
        self.tr.run()
        assert 'enter' in self.verifier.data
        assert 'call' in self.verifier.data
        assert 'exit' in self.verifier.data

    def test_enters_and_exit_called_on_component_with_module_scope(self):
        @requires(comp='MyComponent', scope='module')
        def my_test_case(comp):
            comp()

        self.run_queue.append(TestCaseDefinition(my_test_case))
        self.tr.run()
        assert 'enter' in self.verifier.data
        assert 'call' in self.verifier.data
        assert 'exit' in self.verifier.data

    def test_enters_and_exit_called_on_component_with_class_scope(self):
        class TestMyTestCase(object):
            @requires(comp='MyComponent', scope='class')
            def my_test_case(self, comp):
                comp()

        self.run_queue.append(TestCaseDefinition(
            TestMyTestCase().my_test_case))
        self.tr.run()
        assert 'enter' in self.verifier.data
        assert 'call' in self.verifier.data
        assert 'exit' in self.verifier.data

    def test_enters_and_exit_called_on_component_with_runner_scope(self):
        @requires(comp='MyComponent', scope='module')
        def my_test_case(comp):
            comp()

        self.run_queue.append(TestCaseDefinition(my_test_case))
        self.tr.run()
        assert 'enter' in self.verifier.data
        assert 'call' in self.verifier.data
        assert 'exit' in self.verifier.data

    def test_enter_and_exit_called_once_on_class_scope_component_for_test_cases_in_same_class(
            self):
        class TestMyTestCase(object):
            @requires(comp='MyComponent', scope='class')
            def my_test_case1(self, comp):
                comp()

            @requires(comp='MyComponent', scope='class')
            def my_test_case2(self, comp):
                comp()

        test_case_class = TestMyTestCase()
        self.run_queue.extend([
            TestCaseDefinition(test_case_class.my_test_case1),
            TestCaseDefinition(test_case_class.my_test_case2)
        ])
        self.tr.run()
        assert self.verifier.data.count('enter') == 1
        assert self.verifier.data.count('call') == 2
        assert self.verifier.data.count('exit') == 1

    def test_enter_and_exit_called_once_on_module_scope_component_for_test_cases_in_same_module(
            self):
        @requires(comp='MyComponent', scope='module')
        def my_test_case1(comp):
            comp()

        @requires(comp='MyComponent', scope='module')
        def my_test_case2(comp):
            comp()

        self.run_queue.extend([
            TestCaseDefinition(my_test_case1),
            TestCaseDefinition(my_test_case2)
        ])
        self.tr.run()
        assert self.verifier.data.count('enter') == 1
        assert self.verifier.data.count('call') == 2
        assert self.verifier.data.count('exit') == 1

    def test_enter_and_exit_called_once_on_runner_scope_component(self):
        @requires(comp='MyComponent', scope='runner')
        def my_test_case1(comp):
            comp()

        @requires(comp='MyComponent', scope='runner')
        def my_test_case2(comp):
            comp()

        self.run_queue.extend([
            TestCaseDefinition(my_test_case1),
            TestCaseDefinition(my_test_case2)
        ])
        self.tr.run()
        assert self.verifier.data.count('enter') == 1
        assert self.verifier.data.count('call') == 2
        assert self.verifier.data.count('exit') == 1

    def test_enter_fails_sets_test_case_verdict_to_error_and_exit_is_called(
            self):
        @requires(comp='MyEnterFailComponent', scope='runner')
        def my_test_case1(comp):
            comp()

        self.run_queue.extend([TestCaseDefinition(my_test_case1)])
        self.tr.run()
        assert self.tr.run_history[0].verdict == Verdict.ERROR
        assert 'enter' in self.verifier.data
        assert 'call' not in self.verifier.data
        assert 'exit' in self.verifier.data

    def test_enter_fails_sets_test_case_verdict_to_error_and_continues_to_next_test_case(
            self):
        @requires(comp='MyEnterFailComponent', scope='runner')
        def my_test_case1(comp):
            comp()

        @requires(comp='MyComponent', scope='runner')
        def my_test_case2(comp):
            comp()

        self.run_queue.extend([
            TestCaseDefinition(my_test_case1),
            TestCaseDefinition(my_test_case2)
        ])
        self.tr.run()
        assert self.tr.run_history[0].verdict == Verdict.ERROR
        assert self.tr.run_history[1].verdict == Verdict.PASSED

    def test_exit_fails_on_test_scope_aborts_test_run(self):
        @requires(comp='MyExitFailComponent', scope='test')
        def my_test_case1(comp):
            comp()

        @requires(comp='MyComponent', scope='runner')
        def my_test_case2(comp):
            comp()

        self.run_queue.extend([
            TestCaseDefinition(my_test_case1),
            TestCaseDefinition(my_test_case2)
        ])
        self.tr.run()
        assert self.tr.run_history[0].verdict == Verdict.PASSED
        assert self.tr.run_history[1].verdict == Verdict.SKIPPED

    def test_exit_fails_on_non_test_scope_aborts_test_run(self):
        class MyTestCase1(object):
            @requires(comp='MyExitFailComponent', scope='class')
            def my_test_case1(self, comp):
                comp()

        class MyTestCase2(object):
            @requires(comp='MyComponent', scope='class')
            def my_test_case2(self, comp):
                comp()

        self.run_queue.extend([
            TestCaseDefinition(MyTestCase1().my_test_case1),
            TestCaseDefinition(MyTestCase2().my_test_case2)
        ])
        self.tr.run()
        assert self.tr.run_history[0].verdict == Verdict.PASSED
        assert self.tr.run_history[1].verdict == Verdict.SKIPPED
    def test_error_message_when_remove_with_shorter_scope(self):
        @component(name='A',
                   can=['stuff', 'other_stuff'],
                   scope='short',
                   component_manager=self.component_manager)
        def component_a_scope():
            pass

        @component(name='A',
                   can=['no_stuff'],
                   component_manager=self.component_manager)
        def component_a_cans():
            pass

        @component(name='A',
                   can=['stuff', 'other_stuff'],
                   component_manager=self.component_manager)
        @requires(require_not_exists='NotExists')
        def component_a_depends(require_not_exists):
            pass

        @component(name='B',
                   scope='long',
                   component_manager=self.component_manager)
        @requires(require_a='A', can=['stuff', 'other_stuff'])
        def component_b(require_a):
            pass

        @component(name='C',
                   can=['stuff2', 'stuff3', 'stuff4'],
                   component_manager=self.component_manager)
        def component_c():
            pass

        @component(name='D', component_manager=self.component_manager)
        @requires(require_c='C', can=['stuff2', 'stuff3'])
        def component_d(require_c):
            pass

        @requires(require_b='B')
        @requires(require_d=component_d)
        def test(require_b, require_d):
            pass

        long = Scope('long')
        short = Scope('short', parent=long)

        dependency_graph = self.builder.create_dependency_graph(
            test, short, None)
        expected_message = dedent("""\
            Error fulfilling requirements for test
            U: Requirement 'require_b' with name 'B': Unfulfilled
              U: Component 'component_b' with name 'B': Unfullfilled requirements
                U: Requirement 'require_a' with name 'A' and cans 'stuff, other_stuff': Unfulfilled
                  C: Component 'component_a_cans' with name 'A': Cans not fulfilled 'stuff, other_stuff'
                  U: Component 'component_a_depends' with name 'A': Unfullfilled requirements
                    M: Requirement 'require_not_exists' with name 'NotExists': Missing component 'NotExists'
                  S: Component 'component_a_scope' with name 'A': Scope 'short' is not one of the valid scopes 'long'
            F: Requirement 'require_d' with name 'component_d': Fulfilled
              E: Component 'component_d' with name 'component_d': Exists
                F: Requirement 'require_c' with name 'C': Fulfilled
                  E: Component 'component_c' with name 'C': Exists""")

        with self.assertRaises(ComponentDependencyError) as exc:
            dependency_graph.resolve(short)
            self.assertEqual(str(exc), expected_message)