From 2c67a31cb0a5434c4f471b6ae4c31a169de19bbd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 13:30:16 +0000 Subject: [PATCH] feat(cli): add input validation with friendly error messages - Validates `days`, `initial_cash`, `initial_price`, and `volatility` arguments. - Prints descriptive error messages using `Colors.FAIL` (red) for better visibility. - Exits with status code 1 on validation failure. - Adds `test_cli.py` to verify CLI validation logic using subprocess. This improvement prevents confusing behavior (e.g., negative days resulting in empty simulations) and guides the user towards correct usage. Co-authored-by: EiJackGH <172181576+EiJackGH@users.noreply.github.com> --- bitcoin_trading_simulation.py | 13 ++++++++++ test_cli.py | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test_cli.py diff --git a/bitcoin_trading_simulation.py b/bitcoin_trading_simulation.py index cb07d20..8972e46 100644 --- a/bitcoin_trading_simulation.py +++ b/bitcoin_trading_simulation.py @@ -142,6 +142,19 @@ def countdown(quiet=False): if args.no_color: Colors.disable() + if args.days <= 0: + print(f"{Colors.FAIL}Error: --days must be a positive integer.{Colors.ENDC}") + sys.exit(1) + if args.initial_cash <= 0: + print(f"{Colors.FAIL}Error: --initial-cash must be positive.{Colors.ENDC}") + sys.exit(1) + if args.initial_price <= 0: + print(f"{Colors.FAIL}Error: --initial-price must be positive.{Colors.ENDC}") + sys.exit(1) + if args.volatility < 0: + print(f"{Colors.FAIL}Error: --volatility must be non-negative.{Colors.ENDC}") + sys.exit(1) + # Simulate prices prices = simulate_bitcoin_prices(days=args.days, initial_price=args.initial_price, volatility=args.volatility) diff --git a/test_cli.py b/test_cli.py new file mode 100644 index 0000000..23eef17 --- /dev/null +++ b/test_cli.py @@ -0,0 +1,49 @@ +import subprocess +import pytest +import sys + +def run_cli(args): + """Runs the CLI script with given arguments.""" + cmd = [sys.executable, "bitcoin_trading_simulation.py"] + args + result = subprocess.run( + cmd, + capture_output=True, + text=True + ) + return result + +def test_cli_negative_days(): + result = run_cli(["--days", "-5"]) + assert result.returncode == 1 + assert "Error: --days must be a positive integer." in result.stdout + +def test_cli_zero_days(): + result = run_cli(["--days", "0"]) + assert result.returncode == 1 + assert "Error: --days must be a positive integer." in result.stdout + +def test_cli_negative_cash(): + result = run_cli(["--initial-cash", "-100"]) + assert result.returncode == 1 + assert "Error: --initial-cash must be positive." in result.stdout + +def test_cli_zero_cash(): + result = run_cli(["--initial-cash", "0"]) + assert result.returncode == 1 + assert "Error: --initial-cash must be positive." in result.stdout + +def test_cli_negative_price(): + result = run_cli(["--initial-price", "-500"]) + assert result.returncode == 1 + assert "Error: --initial-price must be positive." in result.stdout + +def test_cli_negative_volatility(): + result = run_cli(["--volatility", "-0.5"]) + assert result.returncode == 1 + assert "Error: --volatility must be non-negative." in result.stdout + +def test_cli_valid_run(): + # Run with a short duration and quiet mode for speed + result = run_cli(["--days", "5", "--quiet", "--no-color"]) + assert result.returncode == 0 + assert "Final Portfolio Performance" in result.stdout