Example #1
0
    def test_write(self):
        """Test write configuration."""
        config = {
            "foobar": {
                "baz": "foo",
                "foo": "bar"
            }
        }

        conf = Config(self.filename)
        conf.update(config)
        self.assertEqual("foobar:\n  baz: foo\n  foo: bar\n", self.read_file())

        del conf["foobar"]
        conf["foo"] = "bar"
        self.assertEqual("foo: bar\n", self.read_file())
Example #2
0
    def setUp(self):
        """Setup test suite."""
        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.subparser = self.parser.add_subparsers(dest="show_subcommand")

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")

        config_data = {
            "workspaces": {
                "my_workspace": {
                    "path": "/my_workspace",
                    "repositories": {
                        "repo1": self.sandbox.path + "/my_workspace/repo1"
                    }
                },
                "another_workspace": {
                    "path": "/another_workspace",
                    "repositories": {
                        "repo1": self.sandbox.path + "/another_workspace/repo1"
                    }
                }
            }
        }

        self.sandbox.mkdir("my_workspace")
        self.sandbox.mkdir("my_workspace/repo1")
        self.sandbox.mkdir("another_workspace")
        self.sandbox.mkdir("another_workspace/repo1")
        self.config.update(config_data)

        self.show = Show()
        self.show.setup("show", self.config, self.subparser)
Example #3
0
    def setUp(self):
        """Setup test suite."""
        self.sandbox = Sandbox()
        self.sandbox.mkdir("yoda")
        self.sandbox.mkdir("yoda/yoda")
        self.sandbox.mkdir("yoda/other")

        self.sandbox.mkdir("sliim")
        self.sandbox.mkdir("sliim/emacs.d")
        self.sandbox.mkdir("sliim/yoda")

        config_data = {
            "workspaces": {
                "yoda": {
                    "path": os.path.join(self.sandbox.path, "yoda"),
                    "repositories": {
                        "yoda": os.path.join(self.sandbox.path, "yoda/yoda"),
                        "other": os.path.join(self.sandbox.path, "yoda/other"),
                        "1337": os.path.join(self.sandbox.path, "yoda/1337")
                    }
                },
                "sliim": {
                    "path": os.path.join(self.sandbox.path, "sliim"),
                    "repositories": {
                        "misc": os.path.join(self.sandbox.path, "sliim/misc"),
                        "yoda": os.path.join(self.sandbox.path, "sliim/yoda")
                    }
                }
            }
        }

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")
        self.config.update(config_data)
Example #4
0
    def setUp(self):
        """Setup test suite."""
        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.subparser = self.parser.add_subparsers(dest="subcommand_test")
        self.sandbox = Sandbox()
        self.sandbox.mkdir("tmp")
        self.sandbox.mkdir("tmp/repo-name")

        config_data = {
            "workspaces": {
                "yoda": {
                    "path": "/yoda",
                    "repositories": {
                        "yoda": "/project/yoda"
                    }
                }
            }
        }

        conf = Config(self.sandbox.path + "/config")
        conf.update(config_data)
        self.workspace = Workspace()
        self.workspace.setup(
            "workspace", conf, self.subparser)
Example #5
0
    def setUp(self):
        """Setup test suite."""
        self.sandbox = Sandbox()
        self.directory = self.sandbox.path + "/tmp"

        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.config_data = {
            "workspaces": {
                "yoda": {
                    "path": self.directory
                }
            }
        }

        self.config = Config(self.sandbox.path + "/config")
        self.config.update(self.config_data)
Example #6
0
    def setUp(self):
        """Setup test suite."""
        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.subparser = self.parser.add_subparsers(dest="subcommand_test")

        self.status = Status()
        config_data = {
            "workspaces": {
                "yoda": {
                    "path": "/yoda",
                    "repositories": {
                        "yoda": "/project/yoda"
                    }
                }
            }
        }

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")
        self.config.update(config_data)
        self.status.setup("status", self.config, self.subparser)
Example #7
0
 def setUp(self):
     self.sandbox = Sandbox()
     self.config = Config(self.sandbox.path + "/config")
Example #8
0
class TestWorkspace(unittest.TestCase):
    """Test workspace commands."""

    config = None
    sandbox = None

    def setUp(self):
        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")

    def tearDown(self):
        self.sandbox.destroy()

    def test_add(self):
        """Test add workspace."""
        self.config.update({
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}})
        ws = Workspace(self.config)
        ws.add("bar", os.path.realpath(__file__))

    def test_add_existing_workspace(self):
        """Test add workspace with existing name."""
        self.config.update({
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}})
        ws = Workspace(self.config)
        self.assertRaises(
            ValueError, ws.add, "foo", os.path.realpath(__file__))

    def test_add_with_nonexistent_path(self):
        """Test add workspace with path doesn't exists."""
        self.config.update({"workspaces": {}})
        ws = Workspace(self.config)
        self.assertRaises(
            ValueError, ws.add, "foo", "/dir/doesnt/exists")

    def test_remove(self):
        """Test remove workspace."""
        self.config.update({
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}})
        ws = Workspace(self.config)
        ws.remove("foo")

    def test_remove_nonexistent(self):
        """Test remove workspace that doesn't exists."""
        self.config.update({
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}})
        ws = Workspace(self.config)
        self.assertRaises(
            ValueError, ws.remove, "bar")

    def test_list(self):
        """Test list workspace."""
        config_mock_data = {"workspaces": {
            "foo": {"path": "/foo", "repositories": {}},
            "bar": {"path": "/bar", "repositories": {}}}}
        self.config.update(config_mock_data)

        ws = Workspace(self.config)
        list = ws.list()
        self.assertIn("foo", list)
        self.assertIn("bar", list)
        self.assertEqual(
            {"name": "foo",
             "path": "/foo",
             "repositories": {}}, list["foo"])
        self.assertEqual(
            {"name": "bar",
             "path": "/bar",
             "repositories": {}}, list["bar"])

    def test_get_workspace(self):
        """Test get workspace from name."""
        config_mock_data = {"workspaces": {
            "foo": {"path": "/foo", "repositories": {}}}}
        self.config.update(config_mock_data)

        ws = Workspace(self.config)
        self.assertEqual({
            "name": "foo",
            "path": "/foo",
            "repositories": {}}, ws.get("foo"))

    def test_get_workspace_none(self):
        """Test get workspace that doesn't exists."""
        ws = Workspace(self.config)
        self.assertIsNone(ws.get("foo"))

    def test_exists(self):
        """Test exists workspace."""
        config_mock_data = {
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}}
        self.config.update(config_mock_data)
        ws = Workspace(self.config)
        self.assertTrue(ws.exists("foo"))

    def test_not_exists(self):
        """Test workspace doesn't exists."""
        config_mock_data = {
            "workspaces": {"foo": {"path": "/foo", "repositories": {}}}}
        self.config.update(config_mock_data)
        ws = Workspace(self.config)
        self.assertFalse(ws.exists("bar"))

    def test_not_instance_of_config(self):
        """Test if parameter is an instance of Config."""
        self.assertRaises(TypeError, lambda: Workspace(()))

    def test_repository_exists(self):
        """Test workspace has repository."""
        config_mock_data = {"workspaces": {
            "foo": {"path": "/foo", "repositories": {"repo1": "/foo/repo1"}}}}
        self.config.update(config_mock_data)
        ws = Workspace(self.config)
        self.assertTrue(ws.repository_exists("foo", "repo1"))

    def test_has_not_repo(self):
        """Test workspace has not repository."""
        config_mock_data = {"workspaces": {
            "foo": {"path": "/foo", "repositories": {"repo1": "/foo/repo1"}}}}
        self.config.update(config_mock_data)
        ws = Workspace(self.config)
        self.assertFalse(ws.repository_exists("foo", "repo2"))

    def test_repository_exists_invalid_workspace(self):
        """Test workspace has not repository."""
        config_mock_data = {"workspaces": {
            "foo": {"path": "/foo", "repositories": {"repo1": "/foo/repo1"}}}}
        self.config.update(config_mock_data)
        ws = Workspace(self.config)
        self.assertFalse(ws.repository_exists("bar", "repo1"))
Example #9
0
class TestSubcommandStatus(unittest.TestCase):
    """Status subcommand test suite."""
    sandbox = None
    config = None
    parser = None
    subparser = None
    status = None

    def setUp(self):
        """Setup test suite."""
        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.subparser = self.parser.add_subparsers(dest="subcommand_test")

        self.status = Status()
        config_data = {
            "workspaces": {
                "yoda": {
                    "path": "/yoda",
                    "repositories": {
                        "yoda": "/project/yoda"
                    }
                }
            }
        }

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")
        self.config.update(config_data)
        self.status.setup("status", self.config, self.subparser)

    def tearDown(self):
        """Tear down test suite."""
        self.parser = None
        self.status = None

    def test_parse_status(self):
        """Test parse status subcommand."""
        self.status.parse()

        args = self.parser.parse_args(["status", "ws1/repo1"])

        self.assertEqual("status", args.subcommand_test)
        self.assertEqual("ws1/repo1", args.name)

        args = self.parser.parse_args(["status", "--all"])

        self.assertEqual("status", args.subcommand_test)
        self.assertEqual(True, args.all)

        self.assertRaises(
            SystemExit,
            self.parser.parse_args, ["status", "--all", "ws1/repo1"]
        )

    def test_exec_status_workspace_only(self):
        """Test exec status subcommand."""
        args = Mock()
        args.name = "foo/bar"

        mock_path = {"foo/bar": "/tmp/foo/bar"}

        self.status.print_status = Mock()

        with patch("yoda.subcommand.status.find_path",
                   return_value=mock_path) as patch_fp:
            self.status.execute(args)
            patch_fp.assert_called_once_with("foo/bar", self.status.config)
            self.status.print_status.assert_called_once_with(
                "foo/bar", "/tmp/foo/bar")

    def test_exec_status_all_workspaces(self):
        """Test exec with all workspaces."""
        args = Mock()
        args.name = None
        args.all = True

        mock_path = {"foo/bar": "/tmp/foo/bar"}

        self.status.print_status = Mock()

        with patch("yoda.subcommand.status.find_path",
                   return_value=mock_path):
            self.status.execute(args)

    def test_exec_status_no_matches(self):
        """Test exec status subcommand with no matches."""
        args = Mock()
        args.name = "foobar"

        self.status.logger = Mock()
        self.status.print_status = Mock()

        with patch("yoda.subcommand.status.find_path", return_value={}):
            self.assertFalse(self.status.execute(args))
            self.status.logger.error.assert_called_once_with(
                "No matches for `foobar`")

    def test_print_status(self):
        """Test print_status."""
        self.status.logger = Mock()
        with patch("yoda.subcommand.status.Repository"):
            self.status.print_status("foo", "bar")
            self.status.logger.info.assert_has_calls(
                [call("\033[32m=> [foo] bar\033[0m")])
Example #10
0
class TestFindPathFunction(unittest.TestCase):
    """Test suite for find_path function."""

    def setUp(self):
        """Setup test suite."""
        self.sandbox = Sandbox()
        self.sandbox.mkdir("yoda")
        self.sandbox.mkdir("yoda/yoda")
        self.sandbox.mkdir("yoda/other")

        self.sandbox.mkdir("sliim")
        self.sandbox.mkdir("sliim/emacs.d")
        self.sandbox.mkdir("sliim/yoda")

        config_data = {
            "workspaces": {
                "yoda": {
                    "path": os.path.join(self.sandbox.path, "yoda"),
                    "repositories": {
                        "yoda": os.path.join(self.sandbox.path, "yoda/yoda"),
                        "other": os.path.join(self.sandbox.path, "yoda/other"),
                        "1337": os.path.join(self.sandbox.path, "yoda/1337")
                    }
                },
                "sliim": {
                    "path": os.path.join(self.sandbox.path, "sliim"),
                    "repositories": {
                        "misc": os.path.join(self.sandbox.path, "sliim/misc"),
                        "yoda": os.path.join(self.sandbox.path, "sliim/yoda")
                    }
                }
            }
        }

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")
        self.config.update(config_data)

    def tearDown(self):
        """Destroy sandbox."""
        self.sandbox.destroy()

    def test_find_path_workspace(self):
        """Test find_path for workspace."""
        res = find_path("yoda", self.config)
        self.assertEqual(4, len(res))
        self.assertIn("yoda/yoda", res)
        self.assertIn("yoda/other", res)
        self.assertIn("yoda/1337", res)
        self.assertIn("sliim/yoda", res)

    def test_find_path_workspace_only(self):
        """Test find_path for workspace only."""
        res = find_path("sliim", self.config, True)
        self.assertEqual(1, len(res))
        self.assertIn("sliim", res)

    def test_find_path_repository(self):
        """Test find_path for repository."""
        res = find_path("other", self.config)
        self.assertEqual(1, len(res))
        self.assertIn("yoda/other", res)

    def test_find_path_workspace_and_repository(self):
        """Test find_path for workspace/repository."""
        res = find_path("yoda/1337", self.config)
        self.assertEqual(1, len(res))
        self.assertIn("yoda/1337", res)

    def test_find_path_no_matches(self):
        """Test find_path when no matches found."""
        self.assertEqual({}, find_path("foo/bar", self.config))

    def test_find_path_no_workspace(self):
        """Test find_path when no workspace registered."""
        self.config = Config(self.sandbox.path + "/fake-config")
        self.assertEqual({}, find_path(
            "yoda/yoda", self.config))
Example #11
0
 def test_find_path_no_workspace(self):
     """Test find_path when no workspace registered."""
     self.config = Config(self.sandbox.path + "/fake-config")
     self.assertEqual({}, find_path(
         "yoda/yoda", self.config))
Example #12
0
class TestWorkspacesSubcommands(unittest.TestCase):
    """Test suite for workspaces subcommands setup."""
    config = None
    parser = None
    config_data = None
    directory = None

    def setUp(self):
        """Setup test suite."""
        self.sandbox = Sandbox()
        self.directory = self.sandbox.path + "/tmp"

        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.config_data = {
            "workspaces": {
                "yoda": {
                    "path": self.directory
                }
            }
        }

        self.config = Config(self.sandbox.path + "/config")
        self.config.update(self.config_data)

    def tearDown(self):
        """Tear down test suite."""
        self.sandbox.destroy()
        self.parser = None

    def test_exec_without_command(self):
        """Test repository execute without subcommand."""
        subparser = self.parser.add_subparsers(dest="subcommand_test")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        try:
            args = self.parser.parse_args(["yoda"])
            self.assertIsNone(ws_subcmds.execute(args))
        except SystemExit:
            #Raised in Python 2.7.x
            self.assertEqual("2.7", sys.version[:3])

    def test_parse_add(self):
        """Test parse add subcommands."""
        subparser = self.parser.add_subparsers(dest="subcommand_test")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args([
            "yoda", "add", "repo-name", "-u", "repo-url", "-p", "repo-path"])

        self.assertEqual("add", args.action)
        self.assertEqual("repo-name", args.repo_name)
        self.assertEqual("repo-url", args.url)
        self.assertEqual("repo-path", args.path)

    def test_execute_add_subcommand_repo_already_exists(self):
        """Test execute add subcommands when repo name already exists."""
        subparser = self.parser.add_subparsers(dest="subcommand")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args(["yoda", "add", "repo-name"])
        self.sandbox.mkdir("tmp")
        ws_subcmds.execute(args)
        self.assertTrue(os.path.exists(self.directory + "/repo-name"))
        self.assertRaises(ValueError, lambda: ws_subcmds.execute(args))

    def test_execute_add_subcommand(self):
        """Test execute add subcommand."""
        subparser = self.parser.add_subparsers(dest="subcommand")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args(
            ["yoda", "add", "other-repo", "-p",
             "%s/repo-name" % self.directory, "-u", "repo-url"])

        with patch(
                "yoda.subcommand.workspace.clone") as patch_clone:
            self.sandbox.mkdir("tmp")
            ws_subcmds.execute(args)
            patch_clone.assert_called_once_with(
                "repo-url",
                "%s/repo-name" % self.directory)

    @patch("%s.input" % builtins_module,
           Mock(side_effect=["n", "y"]))
    def test_execute_remove_subcommad(self):
        """Test execute remove subcommands."""
        self.config_data["workspaces"]["yoda"]["repositories"] = {
            "repo-name": self.directory + "/repo-name"
        }
        subparser = self.parser.add_subparsers(dest="subcommand")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args(["yoda", "remove", "repo-name"])
        ws_subcmds.execute(args)
        self.assertFalse(os.path.exists(self.directory + "/repo-name"))

        args = self.parser.parse_args(["yoda", "remove", "1377"])
        self.assertRaises(ValueError, lambda: ws_subcmds.execute(args))

    def test_sync(self):
        """Test synchronize workspace."""
        subparser = self.parser.add_subparsers(dest="subcommand_test")
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, self.config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args([
            "yoda", "sync"])

        self.assertEqual("sync", args.action)

    def test_execute_sync_subcommand(self):
        """Test execute sync subcommand."""
        self.config_data["workspaces"]["yoda"]["repositories"] = {
            "repo-name": self.directory + "/repo-name"
        }
        subparser = self.parser.add_subparsers(dest="subcommand")
        config = self.config
        ws_subcmds = WorkspaceSubcommands(
            "yoda", subparser, config
        )
        ws_subcmds.parse()

        args = self.parser.parse_args(
            ["yoda", "sync", "yoda"]
        )
        self.sandbox.mkdir("tmp")

        self.assertFalse(ws_subcmds.execute(args))
        with patch(
                "yoda.subcommand.workspace.Repository.__init__",
                return_value=None):
            ws_subcmds.execute(args)
Example #13
0
class TestFindPathFunction(YodaTestHelper):
    """Test suite for find_path function."""
    def setUp(self):
        """Setup test suite."""
        super(TestFindPathFunction, self).setUp()
        self.sandbox.mkdir("yoda")
        self.sandbox.mkdir("yoda/yoda")
        self.sandbox.mkdir("yoda/other")

        self.sandbox.mkdir("sliim")
        self.sandbox.mkdir("sliim/emacs.d")
        self.sandbox.mkdir("sliim/yoda")

        config_data = {
            "workspaces": {
                "yoda": {
                    "path": os.path.join(self.sandbox.path, "yoda"),
                    "repositories": {
                        "yoda": os.path.join(self.sandbox.path, "yoda/yoda"),
                        "other": os.path.join(self.sandbox.path, "yoda/other"),
                        "1337": os.path.join(self.sandbox.path, "yoda/1337")
                    }
                },
                "sliim": {
                    "path": os.path.join(self.sandbox.path, "sliim"),
                    "repositories": {
                        "misc": os.path.join(self.sandbox.path, "sliim/misc"),
                        "yoda": os.path.join(self.sandbox.path, "sliim/yoda")
                    }
                }
            }
        }

        self.config = Config(self.sandbox.path + "/config")
        self.config.update(config_data)

    def test_find_path_workspace(self):
        """Test find_path for workspace."""
        res = find_path("yoda", self.config)
        self.assertEqual(4, len(res))
        self.assertIn("yoda/yoda", res)
        self.assertIn("yoda/other", res)
        self.assertIn("yoda/1337", res)
        self.assertIn("sliim/yoda", res)

    def test_find_path_workspace_only(self):
        """Test find_path for workspace only."""
        res = find_path("sliim", self.config, True)
        self.assertEqual(1, len(res))
        self.assertIn("sliim", res)

    def test_find_path_repository(self):
        """Test find_path for repository."""
        res = find_path("other", self.config)
        self.assertEqual(1, len(res))
        self.assertIn("yoda/other", res)

    def test_find_path_workspace_and_repository(self):
        """Test find_path for workspace/repository."""
        res = find_path("yoda/1337", self.config)
        self.assertEqual(1, len(res))
        self.assertIn("yoda/1337", res)

    def test_find_path_no_matches(self):
        """Test find_path when no matches found."""
        self.assertEqual({}, find_path("foo/bar", self.config))

    def test_find_path_no_workspace(self):
        """Test find_path when no workspace registered."""
        self.config = Config(self.sandbox.path + "/fake-config")
        self.assertEqual({}, find_path(
            "yoda/yoda", self.config))

    def test_find_path_raise_value_error(self):
        """
        Test find_path raises a ValueError when there is more than one slash.
        """
        self.assertRaises(ValueError, find_path, "foo/bar/baz", self.config)
Example #14
0
class TestSubcommandShow(unittest.TestCase):
    """Show subcommand test suite."""
    config = None
    sandbox = None
    parser = None
    subparser = None
    show = None

    def setUp(self):
        """Setup test suite."""
        self.parser = argparse.ArgumentParser(prog="yoda_test")
        self.subparser = self.parser.add_subparsers(dest="show_subcommand")

        self.sandbox = Sandbox()
        self.config = Config(self.sandbox.path + "/config")

        config_data = {
            "workspaces": {
                "my_workspace": {
                    "path": "/my_workspace",
                    "repositories": {
                        "repo1": self.sandbox.path + "/my_workspace/repo1"
                    }
                },
                "another_workspace": {
                    "path": "/another_workspace",
                    "repositories": {
                        "repo1": self.sandbox.path + "/another_workspace/repo1"
                    }
                }
            }
        }

        self.sandbox.mkdir("my_workspace")
        self.sandbox.mkdir("my_workspace/repo1")
        self.sandbox.mkdir("another_workspace")
        self.sandbox.mkdir("another_workspace/repo1")
        self.config.update(config_data)

        self.show = Show()
        self.show.setup("show", self.config, self.subparser)

    def tearDown(self):
        """Tear down test suite."""
        self.sandbox.destroy()
        self.parser = None
        self.show = None

    def test_parse_show(self):
        """Test show to workspace."""

        self.show.parse()

        args = self.parser.parse_args(["show", "ws1"])

        self.assertEqual("show", args.show_subcommand)
        self.assertEqual("ws1", args.name)

        args = self.parser.parse_args(["show", "--all"])

        self.assertEqual("show", args.show_subcommand)
        self.assertTrue(args.all)

        self.assertRaises(
            SystemExit,
            self.parser.parse_args, ["show", "--all", "ws1/repo1"]
        )

    def test_exec_show(self):
        """Test exec show subcommand."""
        args = Mock()
        args.name = "my_workspace"

        self.show.show_workspace = Mock()
        self.show.execute(args)
        self.show.show_workspace.assert_called_once_with("my_workspace")

    def test_exec_show_all(self):
        """Test exec show all workspace details subcommand."""
        args = Mock()
        args.name = None
        args.all = True

        self.show.show_workspace = Mock()
        self.show.execute(args)

        self.show.show_workspace.assert_has_calls([call("my_workspace")])
        self.show.show_workspace.assert_has_calls([call("another_workspace")])

    def test_show_workspace_no_matches(self):
        """Test exec show subcommand when no matches."""
        args = Mock()
        args.name = "not_exists"

        self.assertRaises(ValueError, self.show.execute, args)

    def test_show_workspace(self):
        """Test exec show subcommand with workspaces."""
        args = Mock()
        args.name = "my_workspace"

        self.show.logger = Mock()
        self.show.execute(args)

        calls = [
            call("<== \x1b[32mmy_workspace\x1b[0m workspace ==>"),
            call("\tPath: /my_workspace"),
            call("\tNumber of repositories: \x1b[33m1\x1b[0m")
        ]
        self.show.logger.info.assert_has_calls(calls)