Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
Signed-off-by: yzamir <kobi.zamir@gmail.com>
  • Loading branch information
yaacov committed Sep 11, 2023
1 parent e641ca8 commit f64802d
Show file tree
Hide file tree
Showing 15 changed files with 631 additions and 6 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ lint-fix:
make -C rose/server lint-fix

test:
make -C rose/client test-coverage
make -C rose/server test-coverage
make -C rose/client test
make -C rose/server test

clean:
-find . -name '.coverage' -exec rm {} \;
-find . -name 'htmlcov' -exec rmdir {} \;
-find . -name '*.pyc' -exec rm {} \;
-find . -name '__pycache__' -exec rmdir {} \;
-find . -name '.pytest_cache' -exec rmdir {} \;

2 changes: 1 addition & 1 deletion rose/client/.coveragerc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[run]
omit = *_test.py
omit = test_*.py
4 changes: 4 additions & 0 deletions rose/client/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# conftest.py
import sys

sys.path.append(".")
14 changes: 14 additions & 0 deletions rose/client/game/test_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from game.actions import NONE, RIGHT, LEFT, PICKUP, JUMP, BRAKE, ALL


def test_constants():
assert NONE == "none"
assert RIGHT == "right"
assert LEFT == "left"
assert PICKUP == "pickup"
assert JUMP == "jump"
assert BRAKE == "brake"


def test_all_constant():
assert ALL == (NONE, RIGHT, LEFT, PICKUP, JUMP, BRAKE)
21 changes: 21 additions & 0 deletions rose/client/game/test_car.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest
from game.car import Car


def test_car_initialization():
info = {"x": 5, "y": 10}
car = Car(info)

assert car.x == 5
assert car.y == 10


def test_car_initialization_missing_key():
info_missing_x = {"y": 10}
info_missing_y = {"x": 5}

with pytest.raises(KeyError):
Car(info_missing_x)

with pytest.raises(KeyError):
Car(info_missing_y)
32 changes: 32 additions & 0 deletions rose/client/game/test_obstacles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import pytest
from game.obstacles import (
NONE,
CRACK,
TRASH,
PENGUIN,
BIKE,
WATER,
BARRIER,
ALL,
get_random_obstacle,
)


def test_constants():
assert NONE == ""
assert CRACK == "crack"
assert TRASH == "trash"
assert PENGUIN == "penguin"
assert BIKE == "bike"
assert WATER == "water"
assert BARRIER == "barrier"


def test_all_constant():
assert ALL == (NONE, CRACK, TRASH, PENGUIN, BIKE, WATER, BARRIER)


def test_get_random_obstacle():
# This test checks if the function returns a valid obstacle
obstacle = get_random_obstacle()
assert obstacle in ALL
57 changes: 57 additions & 0 deletions rose/client/game/test_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import requests
import threading
from game.server import MyTCPServer, MyHTTPRequestHandler


def drive(world):
return ""


# Start the server in a separate thread for testing
@pytest.fixture(scope="module")
def start_server():
server_address = ("", 8081)
MyHTTPRequestHandler.drive = drive
httpd = MyTCPServer(server_address, MyHTTPRequestHandler)
thread = threading.Thread(target=httpd.serve_forever)
thread.start()
yield
httpd.shutdown()
thread.join()


def test_get_driver_name(start_server):
response = requests.get("http://localhost:8081/")
data = response.json()
assert data["info"]["name"] == "Unknown" # Default driver name


def test_post_valid_data(start_server):
payload = {
"info": {"car": {"x": 3, "y": 8}},
"track": [
["", "", "bike"],
["", "", ""],
["", "", ""],
["", "", ""],
["", "", ""],
["", "", ""],
["", "", ""],
["", "", ""],
],
}
response = requests.post("http://localhost:8081/", json=payload)
data = response.json()
assert "action" in data["info"]


def test_post_invalid_json(start_server):
response = requests.post("http://localhost:8081/", data="not a valid json")
assert response.status_code == 400


def test_post_unexpected_data_structure(start_server):
payload = {"unexpected": "data"}
response = requests.post("http://localhost:8081/", json=payload)
assert response.status_code == 500
46 changes: 46 additions & 0 deletions rose/client/game/test_track.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pytest
from game.track import Track


def test_track_initialization():
t = Track()
assert t.max_x == 0
assert t.max_y == 0

t2 = Track([["a", "b"], ["c", "d"]])
assert t2.max_x == 2
assert t2.max_y == 2


def test_track_get():
t = Track([["a", "b"], ["c", "d"]])
assert t.get(0, 0) == "a"
assert t.get(1, 0) == "b"
assert t.get(0, 1) == "c"
assert t.get(1, 1) == "d"


def test_track_get_out_of_bounds():
t = Track([["a", "b"], ["c", "d"]])

with pytest.raises(IndexError, match="x out of range: 0-1"):
t.get(2, 0)

with pytest.raises(IndexError, match="y out of range: 0-1"):
t.get(0, 2)


def test_track_validate_pos():
t = Track([["a", "b"], ["c", "d"]])

# These should not raise any errors
t._validate_pos(0, 0)
t._validate_pos(1, 0)
t._validate_pos(0, 1)
t._validate_pos(1, 1)

with pytest.raises(IndexError, match="x out of range: 0-1"):
t._validate_pos(2, 0)

with pytest.raises(IndexError, match="y out of range: 0-1"):
t._validate_pos(0, 2)
4 changes: 4 additions & 0 deletions rose/client/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ flake8>=3.9.0
coverage>=7.3.0
radon>=6.0.0
black>=23.7.0
pytest
pytest-check-links
pytest-coverage
pytest-timeout
2 changes: 1 addition & 1 deletion rose/server/.coveragerc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[run]
omit = tests/*
omit = test_*.py
4 changes: 4 additions & 0 deletions rose/server/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# conftest.py
import sys

sys.path.append(".")
2 changes: 1 addition & 1 deletion rose/server/game/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def reset(self):
self.x = self.lane * config.cells_per_player + 1 # | |0| | |1 | |
self.y = config.matrix_height // 3 * 2 # 1/3 of track
self.action = actions.NONE
self.response_time = 0
self.response_time = None
self.score = 0
self.pickups = 0
self.misses = 0
Expand Down
74 changes: 74 additions & 0 deletions rose/server/game/test_player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from common import actions, config
from game import player


def test_player_initialization():
player1 = player.Player("John", 1, 1)

assert player1.name == "John"
assert player1.car == 1
assert player1.lane == 1
# player.Player x value should be middle of it's lane
assert player1.x == player1.lane * config.cells_per_player + 1
assert player1.y == config.matrix_height // 3 * 2
assert player1.action == actions.NONE
assert player1.response_time is None
assert player1.score == 0


def test_player_reset():
player1 = player.Player("John", 1, 1)

player1.score = 50 # Modify player to make sure reset works
player1.reset()
assert player1.x == player1.lane * config.cells_per_player + 1
assert player1.y == config.matrix_height // 3 * 2
assert player1.action == actions.NONE
assert player1.response_time is None
assert player1.score == 0


def test_player_in_lane():
player1 = player.Player("John", 1, 1)

lane_start = player1.lane * config.cells_per_player

for offset in range(config.cells_per_player):
player1.x = lane_start + offset
assert player1.in_lane()


def test_player_not_in_lane():
player1 = player.Player("John", 1, 1)

# Modify player's position to be out of their lane
other_lane = (player1.lane + 1) % config.max_players
other_lane_start = other_lane * config.cells_per_player

for offset in range(config.cells_per_player):
player1.x = other_lane_start + offset
assert not player1.in_lane()


def test_player_state():
player1 = player.Player("John", 2, 1)

expected_state = {
"name": "John",
"car": 2,
"x": 4, # 1 * config.cells_per_player + 1
"y": config.matrix_height // 3 * 2,
"action": actions.NONE,
"response_time": None,
"error": None,
"lane": 1,
"score": 0,
"pickups": 0,
"misses": 0,
"hits": 0,
"breaks": 0,
"jumps": 0,
"collisions": 0,
}

assert player1.state() == expected_state
Loading

0 comments on commit f64802d

Please sign in to comment.