diff --git a/dvc/commands/commit.py b/dvc/commands/commit.py
--- a/dvc/commands/commit.py
+++ b/dvc/commands/commit.py
@@ -48,8 +48,8 @@ def add_parser(subparsers, parent_parser):
         action="store_true",
         default=False,
         help=(
-            "Commit data even if hash values for dependencies or",
-            "outputs did not change.",
+            "Commit data even if hash values for dependencies or "
+            "outputs did not change."
         ),
     )
     commit_parser.add_argument(
diff --git a/dvc/commands/completion.py b/dvc/commands/completion.py
--- a/dvc/commands/completion.py
+++ b/dvc/commands/completion.py
@@ -9,6 +9,9 @@
 logger = logging.getLogger(__name__)
 
 
+SUPPORTED_SHELLS = ["bash", "zsh"]
+
+
 class CmdCompletion(CmdBaseNoRepo):
     def run(self):
         import shtab
@@ -35,6 +38,6 @@ def add_parser(subparsers, parent_parser):
         "--shell",
         help="Shell syntax for completions.",
         default="bash",
-        choices=["bash", "zsh"],
+        choices=SUPPORTED_SHELLS,
     )
     completion_parser.set_defaults(func=CmdCompletion)

Thanks @chenrui333 for the report. This is broken due to https://github.com/iterative/dvc/pull/9760. Will fix shortly.
diff --git a/tests/unit/command/test_completion.py b/tests/unit/command/test_completion.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/command/test_completion.py
@@ -0,0 +1,17 @@
+import logging
+
+import pytest
+
+from dvc.cli import main
+from dvc.commands.completion import SUPPORTED_SHELLS
+
+
+@pytest.mark.parametrize("shell", SUPPORTED_SHELLS)
+def test_completion(caplog, capsys, shell):
+    with caplog.at_level(logging.INFO):
+        assert main(["completion", "-s", shell]) == 0
+    assert not caplog.text
+
+    out, err = capsys.readouterr()
+    assert not err
+    assert out
diff --git a/tests/unit/command/test_help.py b/tests/unit/command/test_help.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/command/test_help.py
@@ -0,0 +1,48 @@
+import logging
+from argparse import SUPPRESS, ArgumentParser
+from typing import Tuple
+
+import pytest
+import shtab
+
+from dvc.cli import main
+from dvc.cli.parser import get_main_parser
+
+
+def command_tuples():
+    root: Tuple[str, ...] = ()
+    commands = [root]
+
+    def recurse_parser(parser: ArgumentParser, parents: Tuple[str, ...] = root) -> None:
+        for positional in parser._get_positional_actions():
+            if positional.help != SUPPRESS and isinstance(positional.choices, dict):
+                public_cmds = shtab.get_public_subcommands(positional)
+                for subcmd, subparser in positional.choices.items():
+                    cmd = (*parents, subcmd)
+                    if subcmd in public_cmds:
+                        commands.append(cmd)
+                    recurse_parser(subparser, cmd)
+
+    main_parser = get_main_parser()
+    recurse_parser(main_parser)
+    return sorted(commands)
+
+
+def pytest_generate_tests(metafunc):
+    def ids(values):
+        if values:
+            return "-".join(values)
+        return "dvc"
+
+    metafunc.parametrize("command_tuples", command_tuples(), ids=ids)
+
+
+def test_help(caplog, capsys, command_tuples):
+    with caplog.at_level(logging.INFO), pytest.raises(SystemExit) as e:
+        main([*command_tuples, "--help"])
+    assert e.value.code == 0
+    assert not caplog.text
+
+    out, err = capsys.readouterr()
+    assert not err
+    assert out

shell completion issue with dvc 3.11.0 release build
# Bug Report

👋 while trying to upgrade dvc to the latest release, I ran into the shell completion failure

```
Successfully installed dvc-3.11.0
[31mERROR[39m: unexpected error - unsupported operand type(s) for %: 'tuple' and 'dict'

[33mHaving any troubles?[0m Hit us up at [34mhttps://dvc.org/support[0m, we are always happy to help!
[31mError:[0m Failure while executing; `\{\"SHELL\"=\>\"zsh\"\} /opt/homebrew/Cellar/dvc/3.11.0/bin/dvc completion -s zsh` exited with 255. Here's the output:
```

relates to https://github.com/Homebrew/homebrew-core/pull/138416

tests/unit/command/test_completion.py::test_completion[bash] tests/unit/command/test_completion.py::test_completion[zsh] tests/unit/command/test_help.py::test_help[dvc] tests/unit/command/test_help.py::test_help[add] tests/unit/command/test_help.py::test_help[cache] tests/unit/command/test_help.py::test_help[cache-dir] tests/unit/command/test_help.py::test_help[cache-migrate] tests/unit/command/test_help.py::test_help[check-ignore] tests/unit/command/test_help.py::test_help[checkout] tests/unit/command/test_help.py::test_help[commit] tests/unit/command/test_help.py::test_help[completion] tests/unit/command/test_help.py::test_help[config] tests/unit/command/test_help.py::test_help[daemon-analytics] tests/unit/command/test_help.py::test_help[daemon-updater] tests/unit/command/test_help.py::test_help[dag] tests/unit/command/test_help.py::test_help[data-status] tests/unit/command/test_help.py::test_help[destroy] tests/unit/command/test_help.py::test_help[diff] tests/unit/command/test_help.py::test_help[doctor] tests/unit/command/test_help.py::test_help[exp] tests/unit/command/test_help.py::test_help[exp-apply] tests/unit/command/test_help.py::test_help[exp-branch] tests/unit/command/test_help.py::test_help[exp-clean] tests/unit/command/test_help.py::test_help[exp-diff] tests/unit/command/test_help.py::test_help[exp-list] tests/unit/command/test_help.py::test_help[exp-pull] tests/unit/command/test_help.py::test_help[exp-push] tests/unit/command/test_help.py::test_help[exp-remove] tests/unit/command/test_help.py::test_help[exp-run] tests/unit/command/test_help.py::test_help[exp-save] tests/unit/command/test_help.py::test_help[exp-show] tests/unit/command/test_help.py::test_help[experiments] tests/unit/command/test_help.py::test_help[experiments-apply] tests/unit/command/test_help.py::test_help[experiments-branch] tests/unit/command/test_help.py::test_help[experiments-clean] tests/unit/command/test_help.py::test_help[experiments-diff] tests/unit/command/test_help.py::test_help[experiments-list] tests/unit/command/test_help.py::test_help[experiments-pull] tests/unit/command/test_help.py::test_help[experiments-push] tests/unit/command/test_help.py::test_help[experiments-remove] tests/unit/command/test_help.py::test_help[experiments-run] tests/unit/command/test_help.py::test_help[experiments-save] tests/unit/command/test_help.py::test_help[experiments-show] tests/unit/command/test_help.py::test_help[fetch] tests/unit/command/test_help.py::test_help[freeze] tests/unit/command/test_help.py::test_help[gc] tests/unit/command/test_help.py::test_help[get] tests/unit/command/test_help.py::test_help[get-url] tests/unit/command/test_help.py::test_help[git-hook-merge-driver] tests/unit/command/test_help.py::test_help[git-hook-post-checkout] tests/unit/command/test_help.py::test_help[git-hook-pre-commit] tests/unit/command/test_help.py::test_help[git-hook-pre-push] tests/unit/command/test_help.py::test_help[import] tests/unit/command/test_help.py::test_help[import-url] tests/unit/command/test_help.py::test_help[init] tests/unit/command/test_help.py::test_help[install] tests/unit/command/test_help.py::test_help[list] tests/unit/command/test_help.py::test_help[list-url] tests/unit/command/test_help.py::test_help[ls] tests/unit/command/test_help.py::test_help[ls-url] tests/unit/command/test_help.py::test_help[machine-add] tests/unit/command/test_help.py::test_help[machine-create] tests/unit/command/test_help.py::test_help[machine-default] tests/unit/command/test_help.py::test_help[machine-destroy] tests/unit/command/test_help.py::test_help[machine-list] tests/unit/command/test_help.py::test_help[machine-modify] tests/unit/command/test_help.py::test_help[machine-remove] tests/unit/command/test_help.py::test_help[machine-rename] tests/unit/command/test_help.py::test_help[machine-ssh] tests/unit/command/test_help.py::test_help[machine-status] tests/unit/command/test_help.py::test_help[metrics] tests/unit/command/test_help.py::test_help[metrics-diff] tests/unit/command/test_help.py::test_help[metrics-show] tests/unit/command/test_help.py::test_help[move] tests/unit/command/test_help.py::test_help[params] tests/unit/command/test_help.py::test_help[params-diff] tests/unit/command/test_help.py::test_help[plots] tests/unit/command/test_help.py::test_help[plots-diff] tests/unit/command/test_help.py::test_help[plots-modify] tests/unit/command/test_help.py::test_help[plots-show] tests/unit/command/test_help.py::test_help[plots-templates] tests/unit/command/test_help.py::test_help[pull] tests/unit/command/test_help.py::test_help[push] tests/unit/command/test_help.py::test_help[queue] tests/unit/command/test_help.py::test_help[queue-kill] tests/unit/command/test_help.py::test_help[queue-logs] tests/unit/command/test_help.py::test_help[queue-remove] tests/unit/command/test_help.py::test_help[queue-start] tests/unit/command/test_help.py::test_help[queue-status] tests/unit/command/test_help.py::test_help[queue-stop] tests/unit/command/test_help.py::test_help[remote] tests/unit/command/test_help.py::test_help[remote-add] tests/unit/command/test_help.py::test_help[remote-default] tests/unit/command/test_help.py::test_help[remote-list] tests/unit/command/test_help.py::test_help[remote-modify] tests/unit/command/test_help.py::test_help[remote-remove] tests/unit/command/test_help.py::test_help[remote-rename] tests/unit/command/test_help.py::test_help[remove] tests/unit/command/test_help.py::test_help[repro] tests/unit/command/test_help.py::test_help[root] tests/unit/command/test_help.py::test_help[stage] tests/unit/command/test_help.py::test_help[stage-add] tests/unit/command/test_help.py::test_help[stage-list] tests/unit/command/test_help.py::test_help[status] tests/unit/command/test_help.py::test_help[unfreeze] tests/unit/command/test_help.py::test_help[unprotect] tests/unit/command/test_help.py::test_help[update] tests/unit/command/test_help.py::test_help[version]