From 27389f93951e5295a937b195e42dd25c1c76f1a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20Schr=C3=B6der?=
 <fschroeder@techfak.uni-bielefeld.de>
Date: Tue, 26 Mar 2024 10:59:35 +0100
Subject: [PATCH] Extract argument parser creation into separate file

Moved the creation of argparse.ArgumentParser objects used to parse command line arguments into a separate module, `argument_parser.py`. This includes organizing all the add_argument calls into specific functions within this new module, in order to increase code readability, reusability and organization within the argument parsing codebase. All existing usages have been updated accordingly.
---
 cooperative_cuisine/__main__.py               |  45 +++-
 cooperative_cuisine/argument_parser.py        | 196 ++++++++++++++++++
 cooperative_cuisine/game_server.py            |   9 +-
 cooperative_cuisine/pygame_2d_vis/drawing.py  |  20 +-
 cooperative_cuisine/pygame_2d_vis/gui.py      |  13 +-
 .../pygame_2d_vis/video_replay.py             |  26 ++-
 cooperative_cuisine/study_server.py           |  14 +-
 cooperative_cuisine/utils.py                  | 135 ------------
 tests/test_utils.py                           |  37 +++-
 9 files changed, 284 insertions(+), 211 deletions(-)
 create mode 100644 cooperative_cuisine/argument_parser.py

diff --git a/cooperative_cuisine/__main__.py b/cooperative_cuisine/__main__.py
index 685d2402..b29e8577 100644
--- a/cooperative_cuisine/__main__.py
+++ b/cooperative_cuisine/__main__.py
@@ -2,13 +2,19 @@ import argparse
 import time
 from multiprocessing import Process
 
-from cooperative_cuisine.utils import (
-    url_and_port_arguments,
+from cooperative_cuisine.argument_parser import (
+    study_server_arguments,
+    ssl_argument,
+    game_server_arguments,
+    create_screenshot_parser,
+    create_study_server_parser,
+    create_game_server_parser,
     disable_websocket_logging_arguments,
     add_list_of_manager_ids_arguments,
-    add_study_arguments,
     add_gui_arguments,
+    add_study_arguments,
 )
+from cooperative_cuisine.pygame_2d_vis.video_replay import create_replay_parser
 
 USE_STUDY_SERVER = True
 
@@ -54,14 +60,43 @@ def main(cli_args=None):
         description="Game Engine Server + PyGameGUI: Starts overcooked game engine server and a PyGame 2D Visualization window in two processes.",
         epilog="For further information, see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
     )
-    url_and_port_arguments(parser)
+    game_server_arguments(parser)
+    study_server_arguments(parser)
     disable_websocket_logging_arguments(parser)
     add_list_of_manager_ids_arguments(parser)
-    add_study_arguments(parser)
     add_gui_arguments(parser)
+    add_study_arguments(parser)
+    ssl_argument(parser)
+
+    subparsers = parser.add_subparsers(
+        help="Available CLI of Cooperative Cuisine", dest="command"
+    )
+    screenshot_parser = subparsers.add_parser(
+        "screenshot", help="Create a screenshot from a json state."
+    )
+    create_screenshot_parser(screenshot_parser)
+
+    study_server_parser = subparsers.add_parser(
+        "study-server", help="Start a study server."
+    )
+    create_study_server_parser(study_server_parser)
+
+    game_server_parser = subparsers.add_parser(
+        "game-server", help="Start a game server."
+    )
+    create_game_server_parser(game_server_parser)
+
+    replay_parser = subparsers.add_parser(
+        "replay", help="Create replay from json states or recordings."
+    )
+    create_replay_parser(replay_parser)
 
     cli_args = parser.parse_args()
 
+    if cli_args.command:
+        print(cli_args)
+        return
+
     game_server = None
     pygame_gui = None
     try:
diff --git a/cooperative_cuisine/argument_parser.py b/cooperative_cuisine/argument_parser.py
new file mode 100644
index 00000000..f2999fce
--- /dev/null
+++ b/cooperative_cuisine/argument_parser.py
@@ -0,0 +1,196 @@
+import uuid
+from argparse import ArgumentParser, FileType
+
+from cooperative_cuisine import ROOT_DIR
+
+DEFAULT_SERVER_URL = "localhost"
+"""Default server URL of game and server study."""
+
+DEFAULT_SERVER_PORT = 8080
+"""Default study server port."""
+
+DEFAULT_GAME_PORT = 8000
+"""Default game server port."""
+
+
+def study_server_arguments(
+    parser: ArgumentParser,
+    default_study_port=DEFAULT_SERVER_PORT,
+    default_server_url=DEFAULT_SERVER_URL,
+):
+    parser.add_argument(
+        "-s",
+        "--study-url",
+        "--study-host",
+        type=str,
+        default=default_server_url,
+        help=f"Overcooked Study Server host url.",
+    )
+    parser.add_argument(
+        "-p",
+        "--study-port",
+        type=int,
+        default=default_study_port,
+        help=f"Port number for the Study Server",
+    )
+
+
+def game_server_arguments(
+    parser: ArgumentParser,
+    default_game_port=DEFAULT_GAME_PORT,
+    default_server_url=DEFAULT_SERVER_URL,
+):
+    parser.add_argument(
+        "-g",
+        "--game-url",
+        "--game-host",
+        type=str,
+        default=default_server_url,
+        help=f"Overcooked Game Server url.",
+    )
+    parser.add_argument(
+        "-gp",
+        "--game-port",
+        type=int,
+        default=default_game_port,
+        help=f"Port number for the Game Server",
+    )
+
+
+def disable_websocket_logging_arguments(parser):
+    """Disables the logging of WebSocket arguments in the provided parser.
+
+    Args:
+        parser: The argument parser object (argparse.ArgumentParser) to which the
+            "--enable-websocket-logging" argument will be added.
+
+    """
+    parser.add_argument(
+        "--enable-websocket-logging" "", action="store_true", default=True
+    )
+
+
+def add_list_of_manager_ids_arguments(parser):
+    """This function adds the manager ids argument to the given argument parser.
+
+    Args:
+        parser: An ArgumentParser object used to parse command line arguments.
+
+    Returns:
+        None
+    """
+    parser.add_argument(
+        "-m",
+        "--manager-ids",
+        nargs="+",
+        type=str,
+        default=[uuid.uuid4().hex],
+        help="List of manager IDs that can create environments.",
+    )
+
+
+def add_study_arguments(parser):
+    """This function adds the study configuration argument to the given argument parser.
+
+    Args:
+        parser (argparse.ArgumentParser): The argument parser object.
+
+
+    Example:
+        ```python
+        import argparse
+        parser = argparse.ArgumentParser()
+        add_study_arguments(parser)
+        ```
+    """
+    parser.add_argument(
+        "--study-config",
+        type=str,
+        default=ROOT_DIR / "configs" / "study" / "study_config.yaml",
+        help="The config of the study.",
+    )
+
+
+def add_gui_arguments(parser):
+    """Adds the gui debug argument to the given argument parser.
+        If set, additional debug / admin elements are shown.
+
+    Args:
+        parser (argparse.ArgumentParser): The argument parser object.
+
+
+    Example:
+        ```python
+        import argparse
+        parser = argparse.ArgumentParser()
+        add_gui_arguments(parser)
+        ```
+    """
+    parser.add_argument(
+        "--do-study",
+        default=True,
+        help="Disable additional debug / admin elements.",
+        action="store_false",
+    )
+
+
+def ssl_argument(parser: ArgumentParser):
+    parser.add_argument(
+        "--ssl",
+        action="store_true",
+        help="Use SSL certificate. Connect to https and wss.",
+    )
+
+
+def visualization_config_argument(parser: ArgumentParser):
+    parser.add_argument(
+        "-v",
+        "--visualization_config",
+        type=FileType("r", encoding="UTF-8"),
+        default=ROOT_DIR / "pygame_2d_vis" / "visualization.yaml",
+    )
+
+
+def output_file_argument(parser: ArgumentParser, default_file: str):
+    parser.add_argument(
+        "-o",
+        "--output_file",
+        type=str,
+        default=default_file,
+    )
+
+
+def create_game_server_parser(parser: ArgumentParser):
+    game_server_arguments(parser)
+    disable_websocket_logging_arguments(parser)
+    add_list_of_manager_ids_arguments(parser)
+    ssl_argument(parser)
+
+
+def create_study_server_parser(parser: ArgumentParser):
+    study_server_arguments(parser)
+    # TODO study server can handle several game server
+    game_server_arguments(parser)
+    add_list_of_manager_ids_arguments(parser=parser)
+    add_study_arguments(parser=parser)
+    ssl_argument(parser)
+
+
+def create_gui_parser(parser: ArgumentParser):
+    study_server_arguments(parser)
+    disable_websocket_logging_arguments(parser)
+    add_list_of_manager_ids_arguments(parser)
+    add_gui_arguments(parser)
+    ssl_argument(parser)
+
+
+def create_screenshot_parser(parser: ArgumentParser):
+    parser.add_argument(
+        "-s",
+        "--state",
+        type=FileType("r", encoding="UTF-8"),
+        default=ROOT_DIR / "pygame_2d_vis" / "sample_state.json",
+    )
+    visualization_config_argument(parser)
+    output_file_argument(parser, ROOT_DIR / "generated" / "screenshot.jpg")
+    return parser
diff --git a/cooperative_cuisine/game_server.py b/cooperative_cuisine/game_server.py
index 01a3b02c..081588dd 100644
--- a/cooperative_cuisine/game_server.py
+++ b/cooperative_cuisine/game_server.py
@@ -30,6 +30,7 @@ from starlette.websockets import WebSocketDisconnect
 from typing_extensions import TypedDict
 
 from cooperative_cuisine.action import Action
+from cooperative_cuisine.argument_parser import create_game_server_parser
 from cooperative_cuisine.environment import Environment
 from cooperative_cuisine.server_results import (
     CreateEnvResult,
@@ -37,9 +38,6 @@ from cooperative_cuisine.server_results import (
     PlayerRequestResult,
 )
 from cooperative_cuisine.utils import (
-    url_and_port_arguments,
-    add_list_of_manager_ids_arguments,
-    disable_websocket_logging_arguments,
     setup_logging,
     UUID_CUTOFF,
 )
@@ -848,10 +846,7 @@ if __name__ == "__main__":
         epilog="For further information, see "
         "https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/cooperative_cuisine.html",
     )
-
-    url_and_port_arguments(parser)
-    disable_websocket_logging_arguments(parser)
-    add_list_of_manager_ids_arguments(parser)
+    create_game_server_parser(parser)
     args = parser.parse_args()
     main(args.game_url, args.game_port, args.manager_ids, args.enable_websocket_logging)
     """
diff --git a/cooperative_cuisine/pygame_2d_vis/drawing.py b/cooperative_cuisine/pygame_2d_vis/drawing.py
index 2cc1f6f4..cea0ee33 100644
--- a/cooperative_cuisine/pygame_2d_vis/drawing.py
+++ b/cooperative_cuisine/pygame_2d_vis/drawing.py
@@ -13,6 +13,7 @@ import yaml
 from scipy.spatial import KDTree
 
 from cooperative_cuisine import ROOT_DIR
+from cooperative_cuisine.argument_parser import create_screenshot_parser
 from cooperative_cuisine.environment import Environment
 from cooperative_cuisine.pygame_2d_vis.game_colors import colors, RGB
 from cooperative_cuisine.state_representation import (
@@ -1039,24 +1040,7 @@ def main(args):
         description="Generate images for a state in json.",
         epilog="For further information, see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
     )
-    parser.add_argument(
-        "-s",
-        "--state",
-        type=argparse.FileType("r", encoding="UTF-8"),
-        default=ROOT_DIR / "pygame_2d_vis" / "sample_state.json",
-    )
-    parser.add_argument(
-        "-v",
-        "--visualization_config",
-        type=argparse.FileType("r", encoding="UTF-8"),
-        default=ROOT_DIR / "pygame_2d_vis" / "visualization.yaml",
-    )
-    parser.add_argument(
-        "-o",
-        "--output_file",
-        type=str,
-        default=ROOT_DIR / "generated" / "screenshot.jpg",
-    )
+    create_screenshot_parser(parser)
     args = parser.parse_args(args)
     with open(args.visualization_config, "r") as f:
         viz_config = yaml.safe_load(f)
diff --git a/cooperative_cuisine/pygame_2d_vis/gui.py b/cooperative_cuisine/pygame_2d_vis/gui.py
index df472228..f296809a 100644
--- a/cooperative_cuisine/pygame_2d_vis/gui.py
+++ b/cooperative_cuisine/pygame_2d_vis/gui.py
@@ -21,6 +21,7 @@ from websockets.sync.client import connect
 
 from cooperative_cuisine import ROOT_DIR
 from cooperative_cuisine.action import ActionType, InterActionData, Action
+from cooperative_cuisine.argument_parser import create_gui_parser
 from cooperative_cuisine.game_server import (
     CreateEnvironmentConfig,
     WebsocketMessage,
@@ -31,11 +32,7 @@ from cooperative_cuisine.pygame_2d_vis.game_colors import colors
 from cooperative_cuisine.server_results import PlayerInfo
 from cooperative_cuisine.state_representation import StateRepresentation
 from cooperative_cuisine.utils import (
-    url_and_port_arguments,
-    disable_websocket_logging_arguments,
-    add_list_of_manager_ids_arguments,
     setup_logging,
-    add_gui_arguments,
 )
 
 
@@ -1472,7 +1469,7 @@ class PyGameGUI:
             environment_config=environment_config,
             layout_config=layout,
             seed=seed,
-            env_name=layout_path.stem
+            env_name=layout_path.stem,
         ).model_dump(mode="json")
 
         # print(CreateEnvironmentConfig.model_validate_json(json_data=creation_json))
@@ -2210,11 +2207,7 @@ if __name__ == "__main__":
         epilog="For further information, "
         "see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
     )
-
-    url_and_port_arguments(parser)
-    disable_websocket_logging_arguments(parser)
-    add_list_of_manager_ids_arguments(parser)
-    add_gui_arguments(parser)
+    create_gui_parser(parser)
     args = parser.parse_args()
     main(
         args.study_url,
diff --git a/cooperative_cuisine/pygame_2d_vis/video_replay.py b/cooperative_cuisine/pygame_2d_vis/video_replay.py
index 46521e12..4892b29f 100644
--- a/cooperative_cuisine/pygame_2d_vis/video_replay.py
+++ b/cooperative_cuisine/pygame_2d_vis/video_replay.py
@@ -29,7 +29,6 @@ python video_replay.py -h
 
 # Code Documentation
 """
-import argparse
 import json
 import os
 import os.path
@@ -42,8 +41,8 @@ import yaml
 from PIL import Image
 from tqdm import tqdm
 
-from cooperative_cuisine import ROOT_DIR
 from cooperative_cuisine.action import Action
+from cooperative_cuisine.argument_parser import visualization_config_argument
 from cooperative_cuisine.environment import Environment
 from cooperative_cuisine.pygame_2d_vis.drawing import Visualizer
 from cooperative_cuisine.recording import FileRecorder
@@ -297,19 +296,9 @@ def video_from_images(image_paths, video_name, fps):
     print("See:", video_name)
 
 
-if __name__ == "__main__":
-    parser = ArgumentParser(
-        prog="Cooperative Cuisine Video Generation",
-        description="Generate videos from recorded data.",
-        epilog="For further information, see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
-    )
+def create_replay_parser(parser: ArgumentParser):
     parser.add_argument("-j", "--json_state", help="Json states file path", type=str)
-    parser.add_argument(
-        "-v",
-        "--visualization_config",
-        type=argparse.FileType("r", encoding="UTF-8"),
-        default=ROOT_DIR / "pygame_2d_vis" / "visualization.yaml",
-    )
+    visualization_config_argument(parser)
     parser.add_argument(
         "-o",
         "--output",
@@ -380,6 +369,15 @@ if __name__ == "__main__":
         type=str,
         help="Create a video from a folder full of images.",
     )
+
+
+if __name__ == "__main__":
+    parser = ArgumentParser(
+        prog="Cooperative Cuisine Video Generation",
+        description="Generate videos from recorded data.",
+        epilog="For further information, see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
+    )
+    create_replay_parser(parser)
     args = parser.parse_args()
     with open(args.visualization_config, "r") as f:
         viz_config = yaml.safe_load(f)
diff --git a/cooperative_cuisine/study_server.py b/cooperative_cuisine/study_server.py
index 7988acf5..9e1e87f5 100644
--- a/cooperative_cuisine/study_server.py
+++ b/cooperative_cuisine/study_server.py
@@ -10,7 +10,6 @@ python game_server.py --manager-ids COPIED_UUID
 
 The environment starts when all players connected.
 """
-
 import argparse
 import asyncio
 import json
@@ -31,14 +30,12 @@ from fastapi import FastAPI, HTTPException, Request
 from pydantic import BaseModel
 
 from cooperative_cuisine import ROOT_DIR
+from cooperative_cuisine.argument_parser import create_study_server_parser
 from cooperative_cuisine.environment import EnvironmentConfig
 from cooperative_cuisine.game_server import CreateEnvironmentConfig, EnvironmentData
 from cooperative_cuisine.server_results import PlayerInfo, CreateEnvResult
 from cooperative_cuisine.utils import (
-    url_and_port_arguments,
-    add_list_of_manager_ids_arguments,
     expand_path,
-    add_study_arguments,
     deep_update,
     UUID_CUTOFF,
 )
@@ -705,15 +702,8 @@ if __name__ == "__main__":
         epilog="For further information, "
         "see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
     )
-    url_and_port_arguments(
-        parser=parser,
-        server_name="Study Server",
-    )
-    add_list_of_manager_ids_arguments(parser=parser)
-    add_study_arguments(parser=parser)
+    create_study_server_parser(parser)
     args = parser.parse_args()
-
-    game_server_url = f"https://{args.game_url}:{args.game_port}"
     main(
         args.study_url,
         args.study_port,
diff --git a/cooperative_cuisine/utils.py b/cooperative_cuisine/utils.py
index 88719d54..601a1f3d 100644
--- a/cooperative_cuisine/utils.py
+++ b/cooperative_cuisine/utils.py
@@ -9,7 +9,6 @@ import json
 import logging
 import os
 import sys
-import uuid
 from collections import deque
 from datetime import datetime, timedelta
 from enum import Enum
@@ -26,15 +25,6 @@ if TYPE_CHECKING:
     from cooperative_cuisine.counters import Counter
 from cooperative_cuisine.player import Player
 
-DEFAULT_SERVER_URL = "localhost"
-"""Default server URL of game and server study."""
-
-DEFAULT_SERVER_PORT = 8080
-"""Default study server port."""
-
-DEFAULT_GAME_PORT = 8000
-"""Default game server port."""
-
 UUID_CUTOFF = 8
 """The cutoff length for UUIDs."""
 
@@ -297,131 +287,6 @@ def setup_logging(enable_websocket_logging=False):
         logging.getLogger("websockets.client").setLevel(logging.ERROR)
 
 
-def url_and_port_arguments(
-    parser,
-    server_name="game server",
-    default_study_port=DEFAULT_SERVER_PORT,
-    default_game_port=DEFAULT_GAME_PORT,
-    default_server_url=DEFAULT_SERVER_URL,
-):
-    """Adds arguments to the given parser for the URL and port configuration of a server.
-
-    Args:
-        parser: The argument parser to add arguments to.
-        server_name: (Optional) The name of the server. Defaults to "game server".
-        default_study_port: (Optional) The default port number for the study URL. Defaults to 8080.
-        default_game_port: (Optional) The default port number for the game URL. Defaults to 8000.
-        default_server_url: (Optional) The default url for the server. Defaults to "localhost".
-    """
-    parser.add_argument(
-        "-s",
-        "--study-url",
-        "--study-host",
-        type=str,
-        default=default_server_url,
-        help=f"Overcooked {server_name} study host url.",
-    )
-    parser.add_argument(
-        "-sp",
-        "--study-port",
-        type=int,
-        default=default_study_port,
-        help=f"Port number for the {server_name}",
-    )
-    parser.add_argument(
-        "-g",
-        "--game-url",
-        "--game-host",
-        type=str,
-        default=DEFAULT_SERVER_URL,
-        help=f"Overcooked {server_name} game server url.",
-    )
-    parser.add_argument(
-        "-gp",
-        "--game-port",
-        type=int,
-        default=default_game_port,
-        help=f"Port number for the {server_name}",
-    )
-
-
-def disable_websocket_logging_arguments(parser):
-    """Disables the logging of WebSocket arguments in the provided parser.
-
-    Args:
-        parser: The argument parser object (argparse.ArgumentParser) to which the
-            "--enable-websocket-logging" argument will be added.
-
-    """
-    parser.add_argument(
-        "--enable-websocket-logging" "", action="store_true", default=True
-    )
-
-
-def add_list_of_manager_ids_arguments(parser):
-    """This function adds the manager ids argument to the given argument parser.
-
-    Args:
-        parser: An ArgumentParser object used to parse command line arguments.
-
-    Returns:
-        None
-    """
-    parser.add_argument(
-        "-m",
-        "--manager-ids",
-        nargs="+",
-        type=str,
-        default=[uuid.uuid4().hex],
-        help="List of manager IDs that can create environments.",
-    )
-
-
-def add_study_arguments(parser):
-    """This function adds the study configuration argument to the given argument parser.
-
-    Args:
-        parser (argparse.ArgumentParser): The argument parser object.
-
-
-    Example:
-        ```python
-        import argparse
-        parser = argparse.ArgumentParser()
-        add_study_arguments(parser)
-        ```
-    """
-    parser.add_argument(
-        "--study-config",
-        type=str,
-        default=ROOT_DIR / "configs" / "study" / "study_config.yaml",
-        help="The config of the study.",
-    )
-
-
-def add_gui_arguments(parser):
-    """Adds the gui debug argument to the given argument parser.
-        If set, additional debug / admin elements are shown.
-
-    Args:
-        parser (argparse.ArgumentParser): The argument parser object.
-
-
-    Example:
-        ```python
-        import argparse
-        parser = argparse.ArgumentParser()
-        add_gui_arguments(parser)
-        ```
-    """
-    parser.add_argument(
-        "--do-study",
-        default=True,
-        help="Disable additional debug / admin elements.",
-        action="store_false",
-    )
-
-
 class NumpyAndDataclassEncoder(json.JSONEncoder):
     """Special json encoder for numpy types"""
 
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 2802bb3a..a629bc57 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -4,6 +4,18 @@ from argparse import ArgumentParser
 import networkx
 import pytest
 
+from cooperative_cuisine.argument_parser import (
+    game_server_arguments,
+    study_server_arguments,
+    disable_websocket_logging_arguments,
+    add_list_of_manager_ids_arguments,
+    add_gui_arguments,
+    add_study_arguments,
+    ssl_argument,
+    create_study_server_parser,
+    create_game_server_parser,
+    create_gui_parser,
+)
 from cooperative_cuisine.environment import Environment
 from cooperative_cuisine.state_representation import (
     create_movement_graph,
@@ -11,11 +23,6 @@ from cooperative_cuisine.state_representation import (
     astar_heuristic,
 )
 from cooperative_cuisine.utils import (
-    url_and_port_arguments,
-    add_list_of_manager_ids_arguments,
-    disable_websocket_logging_arguments,
-    add_study_arguments,
-    add_gui_arguments,
     create_layout_with_counters,
     setup_logging,
 )
@@ -23,19 +30,20 @@ from tests.test_start import env_config_no_validation
 from tests.test_start import layout_empty_config, item_info
 
 
-def test_parser_gen():
+def test_arguments():
     parser = ArgumentParser()
-    url_and_port_arguments(parser)
+    game_server_arguments(parser)
+    study_server_arguments(parser)
     disable_websocket_logging_arguments(parser)
     add_list_of_manager_ids_arguments(parser)
-    add_study_arguments(parser)
     add_gui_arguments(parser)
-
+    add_study_arguments(parser)
+    ssl_argument(parser)
     parser.parse_args(
         [
             "-s",
             "localhost",
-            "-sp",
+            "-p",
             "8000",
             "-g",
             "localhost",
@@ -49,6 +57,15 @@ def test_parser_gen():
     )
 
 
+def test_parser_creation():
+    parser = ArgumentParser()
+    create_game_server_parser(parser)
+    parser = ArgumentParser()
+    create_study_server_parser(parser)
+    parser = ArgumentParser()
+    create_gui_parser(parser)
+
+
 def test_layout_creation():
     assert """###\n#_#\n###\n""" == create_layout_with_counters(3, 3)
     assert """###\n#_#\n#_#\n###\n""" == create_layout_with_counters(3, 4)
-- 
GitLab