Skip to content

Commit

Permalink
adding pytest/unittest first version
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkoBrie committed Feb 22, 2024
1 parent d364545 commit dde9236
Show file tree
Hide file tree
Showing 12 changed files with 649 additions and 5,032 deletions.
Binary file modified .DS_Store
Binary file not shown.
3,133 changes: 121 additions & 3,012 deletions .ipynb_checkpoints/2_Model_selection-checkpoint.ipynb

Large diffs are not rendered by default.

2,013 changes: 143 additions & 1,870 deletions 2_Model_selection.ipynb

Large diffs are not rendered by default.

Empty file added 3_FastAPI/__init__.py
Empty file.
68 changes: 68 additions & 0 deletions 3_FastAPI/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import uvicorn
from fastapi import FastAPI
import numpy as np
#import pickle # pipfile does not lock
import mlflow
import lightgbm
import os
from typing import List
from pydantic import BaseModel # for data validation

# load environment variables
port = os.environ["PORT"]

# initialize FastAPI
app = FastAPI(title="Automatic Credit Scoring",
description='''Obtain a credit score (0,1) for ClientID.
Visit this URL at port 8501 for the streamlit interface.''',
version="0.1.0",)

# Pydantic model for the input data
class DataPoint(BaseModel):
data_point: List[float]

# 3. Expose the prediction functionality, make a prediction from the passed
# JSON data and return the predicted flower species with the confidence
@app.post('/predict')
def predict_credit_score(data: DataPoint):
""" Endpoint for ML model
Args:
list (float): one data point of 239 floats
Returns:
float: prediction probability
int: prediction score
"""
print("predict_credit_score function")
#print(data)
print([data.data_point])

#if len(data) != 239:
# raise HTTPException(status_code=400, detail="Expected 239 data points")

#data_point = {"data_point": data_point}

#data_point = np.array(data_point) #.reshape(1, -1)

sklearn_pyfunc = mlflow.lightgbm.load_model(model_uri="LightGBM")
#data = [[0, 0, 1, 1, 63000.0, 310500.0, 15232.5, 310500.0, 0.026392, 16263, -214.0, -8930.0, -573, 0.0, 1, 1, 0, 1, 1, 0, 2.0, 2, 2, 11, 0, 0, 0, 0, 1, 1, 0.0, 0.0765011930557638, 0.0005272652387098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, True, False, False, False, False, False, False, False, True, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]]

prediction = sklearn_pyfunc.predict_proba([data.data_point]).max()
#print(prediction)
#prediction = 0.7

return {
'prediction': prediction,
'probability': 0.8
}

@app.get("/")
def index():
return {"data": "Application ran successfully - FastAPI release v4.2 with Github Actions no staging: cloudpickle try environment pipenv",

}
#return {st.title("Hello World")}

if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=port, reload=False)
6 changes: 2 additions & 4 deletions 3_STREAMlit_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ def request_prediction(model_uri, data):
#

def main():
#MLFLOW_URI = 'https://fastapi-cd-webapp.azurewebsites.net/predict'
MLFLOW_URI = 'http://0.0.0.0:8000/predict'


MLFLOW_URI = 'https://fastapi-cd-webapp.azurewebsites.net/predict'
#MLFLOW_URI = 'http://0.0.0.0:8000/predict'

api_choice = st.sidebar.selectbox(
'Quelle API souhaitez vous utiliser',
Expand Down
84 changes: 84 additions & 0 deletions 5_unittest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import unittest
import requests
from fastapi.testclient import TestClient
import httpx
from main import app
import pytest


client = TestClient(app)

class TestConnection(unittest.TestCase):
def test_connection_functionality(self):
"""
Test that connection is working and
"""
try:
test_location = "local"
if (test_location == "local"):
host = '127.0.0.1'
port = '8000'
# endpoint
url = f'http://{host}:{port}/predict'
else:
url = 'https://fastapi-cd-webapp.azurewebsites.net/predict'

data_for_request = [0, 0, 1, 1, 63000.0, 310500.0, 15232.5, 310500.0, 0.026392, 16263, -214.0, -8930.0, -573, 0.0, 1, 1, 0, 1, 1, 0, 2.0, 2, 2, 11, 0, 0, 0, 0, 1, 1, 0.0, 0.0765011930557638, 0.0005272652387098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, True, False, False, False, False, False, False, False, True, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False]
# Send the POST request with the data
response = requests.post(url, json={"data_point": data_for_request})
assert response.status_code == 200
except Exception as e:
pytest.fail(f"Test failed: {e}")

def test_response(self):
"""
TEST model output with fixture test data
"""
try:
test_location = "local"
if (test_location == "local"):
host = '127.0.0.1'
port = '8000'
# endpoint
url = f'http://{host}:{port}/predict'
else:
url = 'https://fastapi-cd-webapp.azurewebsites.net/predict'

# fixture simulation with test data
data_for_request = [0, 0, 1, 1, 63000.0, 310500.0, 15232.5, 310500.0, 0.026392, 16263, -214.0, -8930.0, -573, 0.0, 1, 1, 0, 1, 1, 0, 2.0, 2, 2, 11, 0, 0, 0, 0, 1, 1, 0.0, 0.0765011930557638, 0.0005272652387098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, True, False, False, False, False, False, False, False, True, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False]
# Send the POST request with the data
response = requests.post(url, json={"data_point": data_for_request})
assert response.status_code == 200
assert response.json() == {"prediction":0.857982822560715,"probability":0.8}
# Unit tests for response status codes
except Exception as e:
pytest.fail(f"Test failed: {e}")

def test_response(self):
"""
TEST "post" with empty data
"""
try:
test_location = "local"
if (test_location == "local"):
host = '127.0.0.1'
port = '8000'
# endpoint
url = f'http://{host}:{port}/predict'
else:
url = 'https://fastapi-cd-webapp.azurewebsites.net/predict'

# fixture simulation with test data
data_for_request = []

# Send the POST request with the data
response = requests.post(url, json={"data_point": data_for_request})
assert response.status_code == 500
assert response.json() == {"detail":"An error occurred during prediction: Found array with 0 feature(s) (shape=(1, 0)) while a minimum of 1 is required."}
except Exception as e:
pytest.fail(f"Test failed: {e}")

if __name__ == '__main__':
unittest.main()
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ RUN pip install uvicorn
RUN pip install fastapi
RUN pip install mlflow
RUN pip install lightgbm
#RUN pip install cloudpickle
RUN pip install pydantic
RUN pip install streamlit
RUN pip install typing
#RUN pipenv install --system --deploy --ignore-pipfile

# expose the port that uvicorn will run the app on
Expand Down
4 changes: 4 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ streamlit = "*"
mlflow = "2.9.2"
lightgbm = "4.1.0"
pydantic = "*"
httpx = "*"
pytest = "*"

[dev-packages]

[requires]
python_version = "3.8"

[scripts]
Loading

0 comments on commit dde9236

Please sign in to comment.