Skip to content

Commit

Permalink
Prediction tests (#15)
Browse files Browse the repository at this point in the history
* init prediction tests check default 200 for known player

* black formatting

* black formatting

* invalid user test

* rename to represent 404

* formatting and new tests

* verbose testing

* test rename

* tests/test_prediction_api.py

* adding hypothesis

* adding hypothesis tests to invalid names

* max char length is 13, moving to 14

* function name changes and more tests

* fixing function names, expanding tests

* make sure test is in front of all fuctions for pytest

* cleanup of comments

* tests for player not found invalid user returns

* cleanup

* linux guide describing make file use

* missing crypto again

* cleanup of user specific name in examples

* explaing actions

* cleanup make test command after debugging

* more readme explinations for setup

* adding directory the terminal is in to avoid confusion

* syntax

* make package install instructions

* venv setup, make file adding venv create and venv delete

* adding comments to makefile

* cleanup of make file

* make help updates

* add (.venv) to terminal commands where it should be activated to avoid confusion

* readme structure changes

* more formatting

* Cleanup of #

* more structure and lists

* add check

* adding comments to check

* ssh -> sh (=shell)

* make more copy pastable

* linux wanna do some commits?!

---------

Co-authored-by: extreme4all <[email protected]>
Co-authored-by: extreme4all <>
  • Loading branch information
RusticPotatoes and extreme4all authored Oct 29, 2023
1 parent 8dea2f9 commit a9eee32
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 48 deletions.
43 changes: 22 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ clean-test: ## cleanup pytests leftovers
rm -f test-results.html
rm -f output.xml

test: clean ## Run pytest unit tests
python3 -m pytest
test: clean-test ## Run pytest unit tests
python3 -m pytest --verbosity=1

test-debug: ## Run unit tests with debugging enabled
python3 -m pytest --pdb

test-coverage: clean ## Run unit tests and check code coverage
test-coverage: clean-test ## Run unit tests and check code coverage
PYTHONPATH=src python3 -m pytest --cov=src tests/ --disable-warnings

docker-up: ## Startup docker
docker-compose --verbose up

docker-build: ## Startup docker
docker-build: ## Startup docker with build switch
docker-compose --verbose up --build

setup: requirements pre-commit-setup docker-build test-setup api-setup ## setup & run after downloaded repo
setup: requirements venv-create pre-commit-setup docker-build test-setup api-setup ## setup & run after downloaded repo

pre-commit-setup: ## Install pre-commit
python3 -m pip install pre-commit
Expand All @@ -55,33 +55,34 @@ pre-commit-setup: ## Install pre-commit
pre-commit: ## Run pre-commit
pre-commit run --all-files

test-setup:
test-setup: ## installs pytest singular package for local testing
python3 -m pip install pytest

requirements:
requirements: ## installs all requirements
python3 -m pip install -r requirements.txt

docker-down:
docker-down: ## shutdown docker
docker-compose down

docker-rebuild: docker-down
docker-rebuild: docker-down ## shuts down docker then brings it up and rebuilds
docker-compose --verbose up --build

docker-force-rebuild:
docker-force-rebuild: docker-down ## shuts down docker than brings it up and force rebuilds
docker-compose --verbose up --build --force-recreate

api-setup:
api-setup: ## installs fastapi singular package, for local testing
python3 -m pip install "fastapi[all]"

env-setup:
touch .env
echo "KAFKA_HOST= 'localhost:9092'" >> .env
echo "DATABASE_URL= 'mysql+aiomysql://root:root_bot_buster@localhost:3306/playerdata'" >> .env
echo "ENV='DEV'" >> .env
echo "POOL_RECYCLE='60'" >> .env
echo "POOL_TIMEOUT='30'" >> .env

docs:
docs: # opens your browser to the webapps testing docs
open http://localhost:5000/docs
xdg-open http://localhost:5000/docs
. http://localhost:5000/docs
. http://localhost:5000/docs

venv-create: venv-remove ## cleans the .venv then creates a venv in the folder .venv
python3 -m venv .venv

venv-remove: ## removes the .venv folder
rm -rf .venv

check: ## run pre commit hooks for github, should do black checks
pre-commit
202 changes: 193 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ structure:
- src.core: contains the core componetns
- src.core.database: contains all the database functionality

# setup
## windows
# Setup
1. Create fork of primary repo
2. Download a clone of the forked repo `git clone <your github repo path url>`
3. Open a terminal to your cloned repo
4. follow linux or windows sections for further setup
## Windows
creating a python venv to work in and install the project requirements
```sh
python -m venv .venv
Expand All @@ -16,18 +20,198 @@ python -m pip install --upgrade pip
pip install -r requirements.txt
pre-commit install
```
## linux
make sure to have pip
## Linux
Setup overview:
1. install requirements: python, pip, make, docker
2. create venv `make venv-create` or `python3 -m venv .venv`
3. activate venv `source .venv/bin/activate`
4. run setup `make setup`

detailed guide in sections below

### Install make and pip
#### Debian
distros such as ubuntu, mint, pop, kali
```sh
sudo apt install make
sudo apt install python3-pip
```

#### Red Hat
distros such as fedora, centos, rocky
```sh
sudo yum install make
sudo yum install python3-pip
```

#### Arch Linux
```sh
sudo pacman -Syu make
sudo pacman -Syu python3-pip
```

#### MacOS
typically requires xcode command line tools from http://developer.apple.com/
or using homebrew from https://brew.sh/ (example below). note the command it installs is `gmake`, ideally just make an alias `make` by adding it to your bash profile
```sh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew --version
Homebrew 4.1.17
brew install make
brew install python3-pip
```

add your alias to your bash profile (loaded on terminal start)
```sh
nano ~/.bash_profile
```

ctrl+x and enter to save once you have added the alias line (example below line to add)
```sh
alias make="gmake"
```

### Python Virtual Enviornment
#### Setup
run the following command to create your venv
```sh
make venv-create
```

#### Activate
next command is to activate your virtiual envionrment, you should see to the far left of your prompt showing you what env you are in
```sh
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
pip install -r requirements.txt
pre-commit install
```

if you ever need to get out of the virtual enviornment run the `deactivate` command
```sh
deactivate
```

### Make User Guide
use the `make` command with an `action` when developing on linux. think of `actions` as a list of predefined commands to help simplify common development routines.

#### view avaiable actions
`make help` to see all avaiable actions
```sh
clean-pyc clean python cache files
clean-test cleanup pytests leftovers
test Run pytest unit tests
test-debug Run unit tests with debugging enabled
test-coverage Run unit tests and check code coverage
docker-up Startup docker
docker-build Startup docker with build switch
setup setup & run after downloaded repo
pre-commit-setup Install pre-commit
pre-commit Run pre-commit
test-setup installs pytest singular package for local testing
requirements installs all requirements
docker-down shutdown docker
docker-rebuild shuts down docker then brings it up and rebuilds
docker-force-rebuild shuts down docker than brings it up and force rebuilds
api-setup installs fastapi singular package, for local testing
venv-create cleans the .venv then creates a venv in the folder .venv
venv-remove removes the .venv folder
```

### Docker
#### Pre-reqs
- docker
- python3
- local clone of repo
- terminal opened to cloned repos root path


#### Setup Docker Enviornment
run `setup`
```sh
make setup
```

once complete you will have to open a new terminal as the docker output will be running in the current one. you are looking for the message 'Application startup complete.' to know when the `setup` is done and containers are running.

more explinations of different `make` `actions` that can be run in the other sections below

#### Shutdown Docker Containers
run `docker-down`

```sh
make docker-down
```
the outcome should be like
```sh
docker-compose down
[+] Running 6/6
✔ Container kafdrop Removed 10.2s
✔ Container public_api Removed 0.4s
✔ Container kafka_setup Removed 0.0s
✔ Container database Removed 0.8s
✔ Container kafka Removed 0.9s
✔ Network public-api_botdetector-network Removed 0.0s
```

##### Startup Docker Containers
run `docker-up`. example below is using public-api
```sh
make docker-up
```
the outcome should be like
```sh
docker-compose --verbose up
[+] Building 0.0s (0/0)
[+] Running 7/5
✔ Network public-api_botdetector-Network
✔ Container database kafka_setup
✔ Container kafka
✔ Container kafka_setup
✔ Container kafdrop
...
...
public_api | INFO: Application startup complete.
...
```

##### Force Rebuild of Docker Containers
run `docker-force-rebuild`. usually done if requirements.txt are changed. or if containers are having weird issues and you want to start fresh.
```sh
make docker-force-rebuild
```

### TDD using pytest
#### Verifying Tests Pass
run `test`
```sh
make test
```
the outcome should be like
```sh
python3 -m pytest --verbosity=1 --rootdir=./
=============== test session starts ===============
platform darwin -- Python 3.11.6, pytest-7.4.2, pluggy-1.3.0 -- /opt/homebrew/opt/[email protected]/bin/python3.11
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase(PosixPath('./bot-detector/public-api/.hypothesis/examples'))
rootdir: public-api
plugins: hypothesis-6.88.1, anyio-3.7.1
collected 13 items

tests/test_player_api.py::TestPlayerAPI::test_invalid_player_returns_empty PASSED [ 7%]
tests/test_player_api.py::TestPlayerAPI::test_invalid_player_returns_success PASSED [ 15%]
tests/test_player_api.py::TestPlayerAPI::test_valid_player_returns_data PASSED [ 23%]
tests/test_player_api.py::TestPlayerAPI::test_valid_player_returns_success PASSED [ 30%]
tests/test_prediction_api.py::TestPredictionAPI::test_invalid_max_player_name_length_returns_unkonwn PASSED [ 38%]
tests/test_prediction_api.py::TestPredictionAPI::test_invalid_min_player_name_length_returns_unknown PASSED [ 46%]
tests/test_prediction_api.py::TestPredictionAPI::test_invalid_player_breakdown_false_returns_player_not_found PASSED [ 53%]
tests/test_prediction_api.py::TestPredictionAPI::test_invalid_player_breakdown_true_returns_player_not_found PASSED [ 61%]
tests/test_prediction_api.py::TestPredictionAPI::test_invalid_player_breakdown_true_returns_unknown PASSED [ 69%]
tests/test_prediction_api.py::TestPredictionAPI::test_valid_player_breakdown_false_returns_empty_property PASSED [ 76%]
tests/test_prediction_api.py::TestPredictionAPI::test_valid_player_breakdown_false_returns_success PASSED [ 84%]
tests/test_prediction_api.py::TestPredictionAPI::test_valid_player_breakdown_true_returns_populated_property PASSED [ 92%]
tests/test_prediction_api.py::TestPredictionAPI::test_valid_player_breakdown_true_returns_success PASSED [100%]

=============== 13 passed in 1.54s ===============
```

# for admin purposes saving & upgrading
when you added some dependancies update the requirements
```sh
Expand All @@ -41,4 +225,4 @@ powershell "(Get-Content requirements.txt) | ForEach-Object { $_ -replace '==',
call pip install -r requirements.txt --upgrade
call pip freeze > requirements.txt
powershell "(Get-Content requirements.txt) | ForEach-Object { $_ -replace '>=', '==' } | Set-Content requirements.txt"
```
```
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ uvicorn==0.23.2
virtualenv==20.24.5
watchfiles==0.20.0
websockets==11.0.3
hypothesis==6.88.1
cryptography==41.0.4
52 changes: 34 additions & 18 deletions tests/test_player_api.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
import os
import sys
import requests
import json
from unittest import TestCase


sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))


class TestPlayerAPI(TestCase):
def test_valid_player_returns_success(self):
url = "http://localhost:5000/v2/players/score"
params = {}
# build params
params["name"] = ["Player1"]
score = requests.get(url, params)
assert score.status_code == 200

def testValidPlayerReturns200(self):
url = "http://localhost:5000/v2/players/score"
params = {"name": ["Player1"]}
score = requests.get(url, params)
assert score.status_code == 200
def test_invalid_player_returns_success(self):
url = "http://localhost:5000/v2/players/score"
params = {"name": [""]}
score = requests.get(url, params)
assert score.status_code == 200

def testInvalidPlayerReturns200(self):
url = "http://localhost:5000/v2/players/score"
params = {"name": [""]}
response = requests.get(url, params)
assert response.status_code == 200

def testInvalidPlayerBodyIsEmpty(self):
url = "http://localhost:5000/v2/players/score"
params = {"name": [""]}
response = requests.get(url, params)
error = f"Invalid response return type, expected list[dict]"
print(response.json())
assert isinstance(response.json(), list), error
def test_valid_player_returns_data(self):
url = "http://localhost:5000/v2/players/score"
params = {}
# build params
params["name"] = ["Player1"]
score = requests.get(url, params)
json_data = json.loads(score.text)
error = f"Invalid response return type, expected list[dict]"
# print(len(json_data))
assert len(json_data) > 0

def test_invalid_player_returns_empty(self):
url = "http://localhost:5000/v2/players/score"
params = {}
# build params
params["name"] = [""]
score = requests.get(url, params)
# get first element because conversion makes it in a list
json_data = json.loads(score.text)
# should return a populated dictionary, should be True
assert len(json_data) == 0
Loading

0 comments on commit a9eee32

Please sign in to comment.