-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding pytest/unittest first version
- Loading branch information
Showing
12 changed files
with
649 additions
and
5,032 deletions.
There are no files selected for viewing
3,133 changes: 121 additions & 3,012 deletions
3,133
.ipynb_checkpoints/2_Model_selection-checkpoint.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.