Skip to content

Commit

Permalink
Add basic CLI tests (#624)
Browse files Browse the repository at this point in the history
* Add basic CLI tests

* Use stdlib only
  • Loading branch information
rikroe authored Jul 1, 2024
1 parent d1f7d42 commit 276f983
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 2 deletions.
8 changes: 6 additions & 2 deletions bimmer_connected/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ async def get_status(args) -> None:

if args.json:
if args.vin:
print(json.dumps(account.get_vehicle(args.vin), cls=MyBMWJSONEncoder))
print(json.dumps(get_vehicle_or_return(account, args.vin), cls=MyBMWJSONEncoder))
else:
print(json.dumps(account.vehicles, cls=MyBMWJSONEncoder))
else:
Expand Down Expand Up @@ -338,7 +338,11 @@ def main():
logging.getLogger("asyncio").setLevel(logging.WARNING)

loop = asyncio.get_event_loop()
loop.run_until_complete(args.func(args))
try:
loop.run_until_complete(args.func(args))
except Exception as ex: # pylint: disable=broad-except
sys.stderr.write(f"{type(ex).__name__}: {ex}\n")
sys.exit(1)


if __name__ == "__main__":
Expand Down
138 changes: 138 additions & 0 deletions bimmer_connected/tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import json
import subprocess
import sys
import tempfile
from pathlib import Path

import pytest

import bimmer_connected.cli

from . import get_fingerprint_count

ARGS_USER_PW_REGION = ["myuser", "mypassword", "rest_of_world"]
FIXTURE_CLI_HELP = "A simple executable to use and test the library."


def test_run_entrypoint():
"""Test if the entrypoint is installed correctly."""
result = subprocess.run(["bimmerconnected", "--help"], capture_output=True, text=True)

assert FIXTURE_CLI_HELP in result.stdout
assert result.returncode == 0


def test_run_module():
"""Test if the module can be run as a python module."""
result = subprocess.run(["python", "-m", "bimmer_connected.cli", "--help"], capture_output=True, text=True)

assert FIXTURE_CLI_HELP in result.stdout
assert result.returncode == 0


@pytest.mark.usefixtures("bmw_fixture")
@pytest.mark.parametrize(
("vin", "expected_count"),
[
("WBA00000000000F31", 1),
("WBA00000000000F31,WBA00000000DEMO03", 0),
("WBA00000000000Z99", 0),
],
)
def test_status_json_filtered(capsys: pytest.CaptureFixture, vin, expected_count):
"""Test the status command JSON output filtered by VIN."""

sys.argv = ["bimmerconnected", "status", "-j", "-v", vin, *ARGS_USER_PW_REGION]
try:
bimmer_connected.cli.main()
except SystemExit:
pass
result = capsys.readouterr()

if expected_count == 1:
result_json = json.loads(result.out)
assert isinstance(result_json, dict)
assert result_json["vin"] == vin
else:
assert "Error: Could not find vehicle" in result.err


@pytest.mark.usefixtures("bmw_fixture")
def test_status_json_unfiltered(capsys: pytest.CaptureFixture):
"""Test the status command JSON output filtered by VIN."""

sys.argv = ["bimmerconnected", "status", "-j", *ARGS_USER_PW_REGION]
bimmer_connected.cli.main()
result = capsys.readouterr()

result_json = json.loads(result.out)
assert isinstance(result_json, list)
assert len(result_json) == get_fingerprint_count("states")


@pytest.mark.usefixtures("bmw_fixture")
@pytest.mark.parametrize(
("vin", "expected_count"),
[
("WBA00000000000F31", 1),
("WBA00000000000F31,WBA00000000DEMO03", 0),
("WBA00000000000Z99", 0),
],
)
def test_status_filtered(capsys: pytest.CaptureFixture, vin, expected_count):
"""Test the status command text output filtered by VIN."""

sys.argv = ["bimmerconnected", "status", "-v", vin, *ARGS_USER_PW_REGION]
try:
bimmer_connected.cli.main()
except SystemExit:
pass
result = capsys.readouterr()

assert f"Found {get_fingerprint_count('states')} vehicles" in result.out

if expected_count == 1:
assert f"VIN: {vin}" in result.out
assert result.out.count("VIN: ") == expected_count
else:
assert result.out.count("VIN: ") == expected_count


@pytest.mark.usefixtures("bmw_fixture")
def test_status_unfiltered(capsys: pytest.CaptureFixture):
"""Test the status command text output filtered by VIN."""

sys.argv = ["bimmerconnected", "status", *ARGS_USER_PW_REGION]
bimmer_connected.cli.main()
result = capsys.readouterr()

assert f"Found {get_fingerprint_count('states')} vehicles" in result.out
assert result.out.count("VIN: ") == get_fingerprint_count("states")


@pytest.mark.usefixtures("bmw_fixture")
@pytest.mark.usefixtures("bmw_log_all_responses")
def test_fingerprint(capsys: pytest.CaptureFixture, monkeypatch: pytest.MonkeyPatch):
"""Test the fingerprint command."""

with tempfile.TemporaryDirectory() as tmpdirname:
tmp_path = Path(tmpdirname)
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)

sys.argv = ["bimmerconnected", "fingerprint", *ARGS_USER_PW_REGION]
bimmer_connected.cli.main()
result = capsys.readouterr()

assert "fingerprint of the vehicles written to" in result.out

files = list(tmp_path.rglob("*"))
json_files = [f for f in files if f.suffix == ".json"]
txt_files = [f for f in files if f.suffix == ".txt"]

assert len(json_files) == (
get_fingerprint_count("vehicles")
+ get_fingerprint_count("profiles")
+ get_fingerprint_count("states")
+ get_fingerprint_count("charging_settings")
)
assert len(txt_files) == 0

0 comments on commit 276f983

Please sign in to comment.