Merge pull request #5494 from OpenBB-finance/feature/integration-testing

Test coverage of providers and params on integration tests
This commit is contained in:
Igor Radovanovic
2023-10-09 13:32:33 +02:00
committed by GitHub
34 changed files with 3047 additions and 819 deletions

View File

@@ -1,9 +1,6 @@
name: API Integration Tests
on:
push:
branches:
- feature/openbb-sdk-v4
workflow_dispatch:
concurrency:
@@ -15,6 +12,9 @@ jobs:
runs-on: ubuntu-latest
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
OPENBB_API_AUTH: true
OPENBB_API_USERNAME: "USER"
OPENBB_API_PASSWORD: "PASS"
steps:
- name: Slack Notification - Starting
@@ -43,7 +43,7 @@ jobs:
uses: actions/cache@v3
with:
path: runner_env
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock', '**/dev_install.py') }}
key: runner_env-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock', '**/dev_install.py') }}
- name: Install Dependencies
if: steps.cached-python-environment.outputs.cache-hit != 'true'
@@ -60,7 +60,8 @@ jobs:
./openbb_platform/providers/intrinio \
./openbb_platform/extensions/futures \
./openbb_platform/extensions/qa \
./openbb_platform/extensions/ta
./openbb_platform/extensions/ta \
./openbb_platform/extensions/econometrics
pip uninstall -y openbb_core
pip uninstall -y openbb_provider
cd openbb_platform/platform/core
@@ -72,13 +73,14 @@ jobs:
- name: Populate System Setting Files
run: |
mkdir -p ${{ github.workspace }}/.openbb_platform
touch ${{ github.workspace }}/.openbb_platform/system_settings.json
echo '{"log_collect":false}' > ${{ github.workspace }}/.openbb_platform/system_settings.json
mkdir -p ~/.openbb_platform
touch ~/.openbb_platform/system_settings.json
echo '{"log_collect":false}' > ~/.openbb_platform/system_settings.json
cat ~/.openbb_platform/system_settings.json
- name: Create and Populate user_settings.json from GitHub Secrets
run: |
touch ${{ github.workspace }}/.openbb_platform/user_settings.json
touch ~/.openbb_platform/user_settings.json
echo '{
"credentials": {
"benzinga_api_key": ${{ secrets.BENZINGA_API_KEY }},
@@ -88,25 +90,31 @@ jobs:
"fred_api_key": "${{ secrets.FRED_API_KEY }}",
"intrinio_api_key": "${{ secrets.INTRINIO_API_KEY }}"
}
}' > ${{ github.workspace }}/.openbb_platform/user_settings.json
}' > ~/.openbb_platform/user_settings.json
- name: Launch the Uvicorn Process
run: |
source runner_env/bin/activate
pip list
pwd
uvicorn openbb_core.api.rest_api:app --host 0.0.0.0 --port 8000 --reload &
- name: Wait for 1 minute
run: sleep 60
- name: Wait for 10 seconds
run: sleep 10
- name: Run API Integration Tests
run: |
source runner_env/bin/activate
pip list
pwd
cd openbb_platform
pytest . -m integration
pytest -m integration
- name: Cache pip packages
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: runner_env-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock', '**/dev_install.py') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Upload summary to Slack
uses: adrey/slack-file-upload-action@master

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -28,6 +26,7 @@ def headers():
"symbol": "BTCUSD",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"timeseries": 1,
}
),
(
@@ -37,6 +36,7 @@ def headers():
"symbol": "BTCUSD",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
@@ -93,6 +93,6 @@ def test_crypto_load(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/crypto/load?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -31,6 +31,7 @@ def obb(pytestconfig):
"symbol": "BTCUSD",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"timeseries": 1,
}
),
(
@@ -40,6 +41,7 @@ def obb(pytestconfig):
"symbol": "BTCUSD",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(

View File

@@ -1,246 +1,273 @@
import base64
import json
import random
from typing import List
from typing import Literal
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
data = {}
def auth_header():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
def get_headers():
if "headers" in data:
return data["headers"]
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
data["headers"] = {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
return data["headers"]
@pytest.fixture(scope="session")
def headers():
h = {}
auth = auth_header()
h.update(auth)
return h
def get_random_data(menu: str, symbols: List[str], providers: List[str]):
def request_data(menu: str, symbol: str, provider: str):
"""Randomly pick a symbol and a provider and get data from the selected menu."""
symbol = random.choice(symbols) # noqa: S311
provider = random.choice(providers) # noqa: S311
url = f"http://0.0.0.0:8000/api/v1/{menu}/load?symbol={symbol}&provider={provider}"
result = requests.get(url, headers=auth_header(), timeout=5)
result = requests.get(url, headers=get_headers(), timeout=10)
return result.json()["results"]
symbols = ["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "GOOG", "FB", "BABA", "TSM", "V"]
providers = ["fmp", "intrinio", "polygon", "yfinance"]
stocks_data = get_random_data("stocks", symbols=symbols, providers=providers)
def get_stocks_data():
if "stocks_data" in data:
return data["stocks_data"]
# TODO : add more crypto providers and symbols
symbols_crypto = ["BTC"]
providers_crypto = ["fmp"]
crypto_data = get_random_data(
menu="crypto", symbols=symbols_crypto, providers=providers_crypto
)
symbol = random.choice(["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "V"]) # noqa: S311
provider = random.choice(["fmp", "intrinio", "polygon", "yfinance"]) # noqa: S311
data["stocks_data"] = request_data("stocks", symbol=symbol, provider=provider)
return data["stocks_data"]
def get_crypto_data():
if "crypto_data" in data:
return data["crypto_data"]
# TODO : add more crypto providers and symbols
symbol = random.choice(["BTC"]) # noqa: S311
provider = random.choice(["fmp"]) # noqa: S311
data["crypto_data"] = request_data(
menu="crypto",
symbol=symbol,
provider=provider,
)
return data["crypto_data"]
def get_data(menu: Literal["stocks", "crypto"]):
funcs = {"stocks": get_stocks_data, "crypto": get_crypto_data}
return funcs[menu]()
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data}),
({"data": crypto_data}),
({"data": ""}, "stocks"),
({"data": ""}, "crypto"),
],
)
@pytest.mark.integration
def test_econometrics_corr(params, headers):
def test_econometrics_corr(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
body = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/corr?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "y_column": "close", "x_columns": ["date"]}),
({"data": crypto_data, "y_column": "close", "x_columns": ["date"]}),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_ols_summary(params, headers):
def test_econometrics_ols_summary(params, data_type):
params = {p: v for p, v in params.items() if v}
body = json.dumps(
{
"data": params.pop("data"),
"data": get_data(data_type),
"x_columns": params.pop("x_columns"),
}
)
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/ols_summary?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=body)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "y_column": "volume", "x_columns": ["close"]}),
({"data": crypto_data, "y_column": "volume", "x_columns": ["close"]}),
(
{"data": "", "y_column": "volume", "x_columns": ["close"]},
"stocks",
),
(
{"data": "", "y_column": "volume", "x_columns": ["close"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_dwat(params, headers):
def test_econometrics_dwat(params, data_type):
params = {p: v for p, v in params.items() if v}
body = json.dumps(
{
"data": params.pop("data"),
"data": get_data(data_type),
"x_columns": params.pop("x_columns"),
}
)
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/dwat?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=body)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
(
{
"data": stocks_data,
"data": "",
"y_column": "volume",
"x_columns": ["close"],
"lags": "",
}
},
"stocks",
),
(
{
"data": crypto_data,
"data": "",
"y_column": "volume",
"x_columns": ["close"],
"lags": "2",
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_bgot(params, headers):
def test_econometrics_bgot(params, data_type):
params = {p: v for p, v in params.items() if v}
body = json.dumps(
{
"data": params.pop("data"),
"data": get_data(data_type),
"x_columns": params.pop("x_columns"),
}
)
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/bgot?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=body)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
(
{
"data": stocks_data,
"data": "",
"columns": ["close", "volume"],
}
},
"stocks",
),
(
{
"data": crypto_data,
"data": "",
"columns": ["close", "volume"],
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_coint(params, headers):
def test_econometrics_coint(params, data_type):
params = {p: v for p, v in params.items() if v}
body = json.dumps(
{
"data": params.pop("data"),
"data": get_data(data_type),
"columns": params.pop("columns"),
}
)
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/coint?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=body)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
(
{
"data": stocks_data,
"data": "",
"y_column": "volume",
"x_columns": "close",
"x_column": "close",
"lag": "",
}
},
"stocks",
),
(
{
"data": crypto_data,
"data": "",
"y_column": "volume",
"x_columns": "close",
"x_column": "close",
"lag": "2",
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_granger(params, headers):
def test_econometrics_granger(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
body = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/granger?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
({"data": stocks_data, "column": "close", "regression": "c"}),
({"data": crypto_data, "column": "volume", "regression": "ctt"}),
],
"params, data_type",
[({"data": "", "column": "", "regression": ""}, "stocks")],
)
@pytest.mark.integration
def test_econometrics_unitroot(params, headers):
def test_econometrics_unitroot(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
body = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/econometrics/unitroot?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=body)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -0,0 +1,410 @@
"""Test econometrics extension."""
import random
from typing import Literal
import pytest
from openbb_core.app.model.obbject import OBBject
@pytest.fixture(scope="session")
def obb(pytestconfig):
"""Fixture to setup obb."""
if pytestconfig.getoption("markexpr") != "not integration":
import openbb
return openbb.obb
data = {}
def get_stocks_data():
import openbb # pylint:disable=import-outside-toplevel
if "stocks_data" in data:
return data["stocks_data"]
symbol = random.choice(["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "V"]) # noqa: S311
provider = random.choice(["fmp", "intrinio", "polygon", "yfinance"]) # noqa: S311
data["stocks_data"] = openbb.obb.stocks.load(
symbol=symbol, provider=provider
).results
return data["stocks_data"]
def get_crypto_data():
import openbb # pylint:disable=import-outside-toplevel
if "crypto_data" in data:
return data["crypto_data"]
# TODO : add more crypto providers and symbols
symbol = random.choice(["BTC"]) # noqa: S311
provider = random.choice(["fmp"]) # noqa: S311
data["crypto_data"] = openbb.obb.crypto.load(
symbol=symbol, provider=provider
).results
return data["crypto_data"]
def get_data(menu: Literal["stocks", "crypto"]):
funcs = {"stocks": get_stocks_data, "crypto": get_crypto_data}
return funcs[menu]()
@pytest.mark.parametrize(
"params, data_type",
[
({"data": ""}, "stocks"),
({"data": ""}, "crypto"),
],
)
@pytest.mark.integration
def test_econometrics_corr(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.corr(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_ols(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.ols(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params",
[
({"data": "", "y_column": "close", "x_columns": ["date"]}),
({"data": "", "y_column": "close", "x_columns": ["date"]}),
],
)
@pytest.mark.integration
def test_econometrics_ols_summary(params, obb):
params = {p: v for p, v in params.items() if v}
result = obb.econometrics.ols_summary(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "volume", "x_columns": ["close"]},
"stocks",
),
(
{"data": "", "y_column": "volume", "x_columns": ["close"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_dwat(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.dwat(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"y_column": "volume",
"x_columns": ["close"],
"lags": "",
},
"stocks",
),
(
{
"data": "",
"y_column": "volume",
"x_columns": ["close"],
"lags": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_bgot(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.bgot(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"columns": ["close", "volume"],
},
"stocks",
),
(
{
"data": "",
"columns": ["close", "volume"],
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_coint(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.coint(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"y_column": "volume",
"x_column": "close",
"lag": "",
},
"stocks",
),
(
{
"data": "",
"y_column": "volume",
"x_column": "close",
"lag": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_granger(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.granger(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "column": "close", "regression": "c"}, "stocks"),
(
{"data": "", "column": "volume", "regression": "ctt"},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_unitroot(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.unitroot(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelre(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelre(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelbols(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelbols(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelpols(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelpols(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelols(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelols(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelfd(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelfd(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"stocks",
),
(
{"data": "", "y_column": "close", "x_columns": ["date"]},
"crypto",
),
],
)
@pytest.mark.integration
def test_econometrics_panelfmac(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.econometrics.panelfmac(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -27,7 +25,7 @@ def test_economy_const(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/const?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -53,7 +51,7 @@ def test_economy_cpi(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/cpi?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -87,6 +85,7 @@ def test_economy_cpi(params, headers):
"symbol": "^DJI",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
@@ -96,6 +95,7 @@ def test_economy_cpi(params, headers):
"symbol": "^DJI",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
@@ -156,7 +156,7 @@ def test_economy_index(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/index?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -191,7 +191,7 @@ def test_economy_european_index(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/european_index?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -206,14 +206,19 @@ def test_economy_european_index_constituents(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/european_index_constituents?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[({}), ({"europe": True, "provider": "cboe"})],
[
({}),
({"europe": True, "provider": "cboe"}),
({"provider": "fmp"}),
({"provider": "yfinance"}),
],
)
@pytest.mark.integration
def test_economy_available_indices(params, headers):
@@ -221,7 +226,7 @@ def test_economy_available_indices(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/available_indices?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -236,7 +241,7 @@ def test_economy_risk(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/risk?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -261,7 +266,7 @@ def test_economy_index_search(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/index_search?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -276,7 +281,7 @@ def test_economy_index_snapshots(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/index_snapshots?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -291,7 +296,7 @@ def test_economy_cot_search(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/cot_search?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -321,7 +326,7 @@ def test_economy_cot(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/cot?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -346,7 +351,7 @@ def test_economy_sp500_multiples(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/sp500_multiples?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -370,6 +375,6 @@ def test_economy_fred_index(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/fred_index?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -86,6 +86,7 @@ def test_economy_cpi(params):
"symbol": "^DJI",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
@@ -95,6 +96,7 @@ def test_economy_cpi(params):
"symbol": "^DJI",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
@@ -214,6 +216,8 @@ def test_economy_european_index_constituents(params):
[
({}),
({"europe": True, "provider": "cboe"}),
({"provider": "fmp"}),
({"provider": "yfinance"}),
],
)
@pytest.mark.integration

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -27,7 +25,7 @@ def test_fixedincome_treasury(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/treasury?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -42,7 +40,7 @@ def test_fixedincome_ycrv(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/ycrv?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -67,7 +65,7 @@ def test_fixedincome_sofr(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/sofr?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -92,7 +90,7 @@ def test_fixedincome_estr(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/estr?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -117,7 +115,7 @@ def test_fixedincome_sonia(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/sonia?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -142,7 +140,7 @@ def test_fixedincome_ameribor(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/ameribor?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -167,7 +165,7 @@ def test_fixedincome_fed(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/fed?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -182,7 +180,7 @@ def test_fixedincome_projections(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/projections?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -197,6 +195,6 @@ def test_fixedincome_iorb(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/fixedincome/iorb?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -33,6 +31,16 @@ def headers():
"provider": "polygon",
}
),
(
{
"provider": "fmp",
}
),
(
{
"provider": "intrinio",
}
),
],
)
@pytest.mark.integration
@@ -41,7 +49,7 @@ def test_forex_pairs(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/forex/pairs?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -62,7 +70,7 @@ def test_forex_pairs(params, headers):
(
{
"interval": "1day",
"provider": "fmp",
"provider": "intrinio",
"symbol": "EURUSD",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
@@ -122,6 +130,6 @@ def test_forex_load(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/forex/load?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -31,6 +31,16 @@ def obb(pytestconfig):
"provider": "polygon",
}
),
(
{
"provider": "fmp",
}
),
(
{
"provider": "intrinio",
}
),
],
)
@pytest.mark.integration
@@ -44,13 +54,7 @@ def test_forex_pairs(params, obb):
@pytest.mark.parametrize(
"params",
[
(
{
"symbol": "EURUSD",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
}
),
({"symbol": "EURUSD", "start_date": "2023-01-01", "end_date": "2023-06-06"}),
(
{
"interval": "1min",
@@ -63,7 +67,7 @@ def test_forex_pairs(params, obb):
(
{
"interval": "1day",
"provider": "fmp",
"provider": "intrinio",
"symbol": "EURUSD",
"start_date": "2023-01-01",
"end_date": "2023-06-06",

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -50,14 +48,18 @@ def test_futures_load(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/futures/load?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[({"symbol": "AAPL", "date": "2023-01-01"})],
[
({"symbol": "AAPL", "date": "2023-01-01"}),
({"provider": "cboe", "symbol": "AAPL", "date": "2023-01-01"}),
({"provider": "yfinance", "symbol": "AAPL", "date": "2023-01-01"}),
],
)
@pytest.mark.integration
def test_futures_curve(params, headers):
@@ -65,6 +67,6 @@ def test_futures_curve(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/futures/curve?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -52,6 +52,8 @@ def test_futures_load(params, obb):
"params",
[
({"symbol": "AAPL", "date": "2023-01-01"}),
({"provider": "cboe", "symbol": "AAPL", "date": "2023-01-01"}),
({"provider": "yfinance", "symbol": "AAPL", "date": "2023-01-01"}),
],
)
@pytest.mark.integration

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -41,6 +39,18 @@ def headers():
"limit": 20,
}
),
(
{
"provider": "fmp",
"limit": 20,
}
),
(
{
"provider": "intrinio",
"limit": 20,
}
),
],
)
@pytest.mark.integration
@@ -49,6 +59,6 @@ def test_news_globalnews(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/news/globalnews?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -38,6 +38,18 @@ def obb(pytestconfig):
"limit": 20,
}
),
(
{
"provider": "fmp",
"limit": 20,
}
),
(
{
"provider": "intrinio",
"limit": 20,
}
),
],
)
@pytest.mark.integration

View File

@@ -1,276 +1,317 @@
import base64
import json
import random
from typing import List
from typing import Literal
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
data = {}
def auth_header():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
def get_headers():
if "headers" in data:
return data["headers"]
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
data["headers"] = {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
return data["headers"]
@pytest.fixture(scope="session")
def headers():
h = {}
auth = auth_header()
h.update(auth)
return h
def get_data(menu: Literal["stocks", "crypto"]):
funcs = {"stocks": get_stocks_data, "crypto": get_crypto_data}
return funcs[menu]()
def get_random_data(menu: str, symbols: List[str], providers: List[str]):
def request_data(menu: str, symbol: str, provider: str):
"""Randomly pick a symbol and a provider and get data from the selected menu."""
symbol = random.choice(symbols) # noqa: S311
provider = random.choice(providers) # noqa: S311
url = f"http://0.0.0.0:8000/api/v1/{menu}/load?symbol={symbol}&provider={provider}"
result = requests.get(url, headers=auth_header(), timeout=5)
result = requests.get(url, headers=get_headers(), timeout=10)
return result.json()["results"]
symbols = ["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "GOOG", "FB", "BABA", "TSM", "V"]
providers = ["fmp", "intrinio", "polygon", "yfinance"]
stocks_data = get_random_data("stocks", symbols=symbols, providers=providers)
def get_stocks_data():
if "stocks_data" in data:
return data["stocks_data"]
# TODO : add more crypto providers and symbols
symbols_crypto = ["BTC"]
providers_crypto = ["fmp"]
crypto_data = get_random_data(
menu="crypto", symbols=symbols_crypto, providers=providers_crypto
)
symbol = random.choice(["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "V"]) # noqa: S311
provider = random.choice(["fmp", "intrinio", "polygon", "yfinance"]) # noqa: S311
data["stocks_data"] = request_data("stocks", symbol=symbol, provider=provider)
return data["stocks_data"]
def get_crypto_data():
if "crypto_data" in data:
return data["crypto_data"]
# TODO : add more crypto providers and symbols
symbol = random.choice(["BTC"]) # noqa: S311
provider = random.choice(["fmp"]) # noqa: S311
data["crypto_data"] = request_data(
menu="crypto",
symbol=symbol,
provider=provider,
)
return data["crypto_data"]
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close"}),
({"data": crypto_data, "target": "high"}),
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_normality(params, headers):
def test_qa_normality(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/normality?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close"}),
({"data": crypto_data, "target": "high"}),
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_capm(params, headers):
def test_qa_capm(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/capm?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
(
{
"data": stocks_data,
"data": "",
"target": "close",
"threshold_start": "",
"threshold_end": "",
}
},
"stocks",
),
(
{
"data": crypto_data,
"data": "",
"target": "high",
"threshold_start": "0.1",
"threshold_end": "1.6",
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_om(params, headers):
def test_qa_om(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/om?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close", "window": "5"}),
({"data": crypto_data, "target": "high", "window": "10"}),
({"data": "", "target": "close", "window": "5"}, "stocks"),
({"data": "", "target": "high", "window": "10"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_kurtosis(params, headers):
def test_qa_kurtosis(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/kurtosis?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
({"data": stocks_data, "target": "close", "fuller_reg": "c", "kpss_reg": "ct"}),
({"data": stocks_data, "target": "high", "fuller_reg": "ct", "kpss_reg": "c"}),
],
)
@pytest.mark.integration
def test_qa_unitroot(params, headers):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/unitroot?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
({"data": stocks_data, "target": "close", "rfr": "", "window": ""}),
({"data": crypto_data, "target": "high", "rfr": "0.5", "window": "250"}),
],
)
@pytest.mark.integration
def test_qa_sh(params, headers):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/sh?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
(
{
"data": stocks_data,
"data": "",
"target": "close",
"fuller_reg": "c",
"kpss_reg": "ct",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"fuller_reg": "ct",
"kpss_reg": "c",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_unitroot(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/unitroot?{query_str}"
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close", "rfr": "", "window": ""}, "stocks"),
({"data": "", "target": "high", "rfr": "0.5", "window": "250"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_sh(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/sh?{query_str}"
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"target_return": "",
"window": "",
"adjusted": "",
}
},
"stocks",
),
(
{
"data": crypto_data,
"data": "",
"target": "close",
"target_return": "0.5",
"window": "275",
"adjusted": "true",
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_so(params, headers):
def test_qa_so(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/so?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close", "window": "220"}),
({"data": "", "target": "close", "window": "220"}, "stocks"),
],
)
@pytest.mark.integration
def test_qa_skew(params, headers):
def test_qa_skew(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/skew?{query_str}"
result = requests.post(url, headers=headers, timeout=60, data=data)
result = requests.post(url, headers=get_headers(), timeout=60, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close", "window": "10", "quantile_pct": ""}),
(
{
"data": crypto_data,
"data": "",
"target": "close",
"window": "10",
"quantile_pct": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"window": "50",
"quantile_pct": "0.6",
}
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_quantile(params, headers):
def test_qa_quantile(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/quantile?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
"params, data_type",
[
({"data": stocks_data, "target": "close"}),
({"data": crypto_data, "target": "high"}),
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_summary(params, headers):
def test_qa_summary(params, data_type):
params = {p: v for p, v in params.items() if v}
data = json.dumps(params.pop("data"))
data = json.dumps(get_data(data_type))
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/qa/summary?{query_str}"
result = requests.post(url, headers=headers, timeout=5, data=data)
result = requests.post(url, headers=get_headers(), timeout=10, data=data)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -0,0 +1,292 @@
"""Test qa extension."""
import random
from typing import Literal
import pytest
from openbb_core.app.model.obbject import OBBject
@pytest.fixture(scope="session")
def obb(pytestconfig):
"""Fixture to setup obb."""
if pytestconfig.getoption("markexpr") != "not integration":
import openbb
return openbb.obb
data = {}
def get_stocks_data():
import openbb # pylint:disable=import-outside-toplevel
if "stocks_data" in data:
return data["stocks_data"]
symbol = random.choice(["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "V"]) # noqa: S311
provider = random.choice(["fmp", "intrinio", "polygon", "yfinance"]) # noqa: S311
data["stocks_data"] = openbb.obb.stocks.load(
symbol=symbol, provider=provider
).results
return data["stocks_data"]
def get_crypto_data():
import openbb # pylint:disable=import-outside-toplevel
if "crypto_data" in data:
return data["crypto_data"]
# TODO : add more crypto providers and symbols
symbol = random.choice(["BTC"]) # noqa: S311
provider = random.choice(["fmp"]) # noqa: S311
data["crypto_data"] = openbb.obb.crypto.load(
symbol=symbol, provider=provider
).results
return data["crypto_data"]
def get_data(menu: Literal["stocks", "crypto"]):
funcs = {"stocks": get_stocks_data, "crypto": get_crypto_data}
return funcs[menu]()
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_normality(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.normality(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_capm(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.capm(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"threshold_start": "",
"threshold_end": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"threshold_start": "0.1",
"threshold_end": "1.6",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_om(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.om(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close", "window": "5"}, "stocks"),
({"data": "", "target": "high", "window": "10"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_kurtosis(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.kurtosis(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"fuller_reg": "c",
"kpss_reg": "ct",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"fuller_reg": "ct",
"kpss_reg": "c",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_unitroot(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.unitroot(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close", "rfr": "", "window": ""}, "stocks"),
({"data": "", "target": "high", "rfr": "0.5", "window": "250"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_sh(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.sh(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"target_return": "",
"window": "",
"adjusted": "",
},
"stocks",
),
(
{
"data": "",
"target": "close",
"target_return": "0.5",
"window": "275",
"adjusted": "true",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_so(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.so(**params)
assert result
assert isinstance(result, OBBject)
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close", "window": "220"}, "stocks"),
],
)
@pytest.mark.integration
def test_qa_skew(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.skew(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"window": "10",
"quantile_pct": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"window": "50",
"quantile_pct": "0.6",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_qa_quantile(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.quantile(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "target": "close"}, "stocks"),
({"data": "", "target": "high"}, "crypto"),
],
)
@pytest.mark.integration
def test_qa_summary(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.qa.summary(**params)
assert result
assert isinstance(result, OBBject)

View File

@@ -1,20 +1,18 @@
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
@@ -33,9 +31,9 @@ def headers():
),
(
{
"company_name": "Apple Inc",
"company_name_search": "AAPL",
"sic": "35719904",
"company_name": "Apple Inc.",
"company_name_search": "Apple Inc.",
"sic": "3571",
"include_sources": True,
"order": "asc",
"sort": "filing_date",
@@ -43,6 +41,33 @@ def headers():
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2022-10-27",
"filing_date_lt": "2022-11-01",
"filing_date_lte": "2022-11-01",
"filing_date_gt": "2022-10-10",
"filing_date_gte": "2022-10-10",
"period_of_report_date": "2022-09-24",
"period_of_report_date_lt": "2022-11-01",
"period_of_report_date_lte": "2022-11-01",
"period_of_report_date_gt": "2022-10-10",
"period_of_report_date_gte": "2022-10-10",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "fmp",
"cik": "0000320193",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "yfinance",
}
),
],
@@ -53,7 +78,7 @@ def test_stocks_fa_balance(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/balance?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -68,7 +93,7 @@ def test_stocks_fa_balance_growth(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/balance_growth?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -83,7 +108,7 @@ def test_stocks_fa_cal(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/cal?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -114,6 +139,33 @@ def test_stocks_fa_cal(params, headers):
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2023-09-15",
"filing_date_lt": "2023-09-20",
"filing_date_lte": "2023-09-20",
"filing_date_gt": "2023-09-10",
"filing_date_gte": "2023-09-10",
"period_of_report_date": "2023-10-15",
"period_of_report_date_lt": "2023-10-20",
"period_of_report_date_lte": "2023-10-20",
"period_of_report_date_gt": "2023-10-10",
"period_of_report_date_gte": "2023-10-10",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "fmp",
"cik": "0000320193",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "yfinance",
}
),
],
@@ -124,7 +176,7 @@ def test_stocks_fa_cash(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/cash?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -139,7 +191,7 @@ def test_stocks_fa_cash_growth(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/cash_growth?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -154,7 +206,7 @@ def test_stocks_fa_comp(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/comp?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -169,7 +221,7 @@ def test_stocks_fa_comsplit(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/comsplit?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -184,7 +236,7 @@ def test_stocks_fa_divs(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/divs?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -199,7 +251,7 @@ def test_stocks_fa_earning(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/earning?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -214,7 +266,7 @@ def test_stocks_fa_emp(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/emp?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -229,7 +281,7 @@ def test_stocks_fa_est(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/est?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -250,9 +302,9 @@ def test_stocks_fa_est(params, headers):
),
(
{
"company_name": "Apple Inc",
"company_name_search": "AAPL",
"sic": "35719904",
"company_name": "Apple Inc.",
"company_name_search": "Apple Inc.",
"sic": "3571",
"include_sources": True,
"order": "asc",
"sort": "filing_date",
@@ -260,6 +312,33 @@ def test_stocks_fa_est(params, headers):
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2022-10-27",
"filing_date_lt": "2022-11-01",
"filing_date_lte": "2022-11-01",
"filing_date_gt": "2022-10-10",
"filing_date_gte": "2022-10-10",
"period_of_report_date": "2022-09-24",
"period_of_report_date_lt": "2022-11-01",
"period_of_report_date_lte": "2022-11-01",
"period_of_report_date_gt": "2022-10-10",
"period_of_report_date_gte": "2022-10-10",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "fmp",
"cik": "0000320193",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "yfinance",
}
),
],
@@ -270,7 +349,7 @@ def test_stocks_fa_income(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/income?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -285,7 +364,7 @@ def test_stocks_fa_income_growth(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/income_growth?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -310,7 +389,7 @@ def test_stocks_fa_ins(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/ins?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -325,7 +404,7 @@ def test_stocks_fa_ins_own(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/ins_own?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -340,7 +419,7 @@ def test_stocks_fa_metrics(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/metrics?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -355,7 +434,7 @@ def test_stocks_fa_mgmt(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/mgmt?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -370,7 +449,7 @@ def test_stocks_fa_overview(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/overview?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -385,7 +464,7 @@ def test_stocks_fa_own(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/own?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -400,7 +479,7 @@ def test_stocks_fa_pt(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/pt?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -415,7 +494,7 @@ def test_stocks_fa_pta(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/pta?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -430,7 +509,7 @@ def test_stocks_fa_ratios(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/ratios?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -445,7 +524,7 @@ def test_stocks_fa_revgeo(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/revgeo?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -460,7 +539,7 @@ def test_stocks_fa_revseg(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/revseg?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -475,7 +554,7 @@ def test_stocks_fa_filings(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/filings?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -490,7 +569,7 @@ def test_stocks_fa_shrs(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/shrs?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -505,7 +584,7 @@ def test_stocks_fa_split(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/split?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -520,7 +599,7 @@ def test_stocks_fa_transcript(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/fa/transcript?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -535,7 +614,7 @@ def test_stocks_ca_peers(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/ca/peers?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -545,6 +624,7 @@ def test_stocks_ca_peers(params, headers):
[
({"symbol": "AAPL"}),
({"date": "2023-01-01", "provider": "intrinio", "symbol": "AAPL"}),
({"provider": "cboe", "symbol": "AAPL"}),
],
)
@pytest.mark.integration
@@ -553,7 +633,7 @@ def test_stocks_options_chains(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/options/chains?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -574,6 +654,7 @@ def test_stocks_options_chains(params, headers):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"function_": "TIME_SERIES_DAILY",
}
),
(
@@ -601,6 +682,7 @@ def test_stocks_options_chains(params, headers):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"timeseries": 1,
}
),
(
@@ -610,16 +692,20 @@ def test_stocks_options_chains(params, headers):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
{
"timezone": "UTC",
"source": "realtime",
"interval_size": "30m",
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"start_time": "00:00:00",
"end_time": "23:59:59",
}
),
(
@@ -631,6 +717,8 @@ def test_stocks_options_chains(params, headers):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"start_time": "00:00:00",
"end_time": "23:59:59",
}
),
(
@@ -707,7 +795,7 @@ def test_stocks_load(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/load?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -746,6 +834,27 @@ def test_stocks_load(params, headers):
"limit": 20,
}
),
(
{
"provider": "fmp",
"symbols": "AAPL",
"limit": 20,
}
),
(
{
"provider": "yfinance",
"symbols": "AAPL",
"limit": 20,
}
),
(
{
"provider": "intrinio",
"symbols": "AAPL",
"limit": 20,
}
),
],
)
@pytest.mark.integration
@@ -754,7 +863,7 @@ def test_stocks_news(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/news?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -769,7 +878,7 @@ def test_stocks_multiples(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/multiples?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -784,7 +893,7 @@ def test_stocks_search(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/search?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -794,6 +903,7 @@ def test_stocks_search(params, headers):
[
({"symbol": "AAPL"}),
({"source": "iex", "provider": "intrinio", "symbol": "AAPL"}),
({"symbol": "AAPL", "provider": "fmp"}),
],
)
@pytest.mark.integration
@@ -802,7 +912,7 @@ def test_stocks_quote(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/quote?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@@ -817,6 +927,6 @@ def test_stocks_info(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/stocks/info?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -29,9 +29,9 @@ def obb(pytestconfig):
),
(
{
"company_name": "Apple Inc",
"company_name_search": "AAPL",
"sic": "35719904",
"company_name": "Apple Inc.",
"company_name_search": "Apple Inc.",
"sic": "3571",
"include_sources": True,
"order": "asc",
"sort": "filing_date",
@@ -39,6 +39,33 @@ def obb(pytestconfig):
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2022-10-27",
"filing_date_lt": "2022-11-01",
"filing_date_lte": "2022-11-01",
"filing_date_gt": "2022-10-10",
"filing_date_gte": "2022-10-10",
"period_of_report_date": "2022-09-24",
"period_of_report_date_lt": "2022-11-01",
"period_of_report_date_lte": "2022-11-01",
"period_of_report_date_gt": "2022-10-10",
"period_of_report_date_gte": "2022-10-10",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "fmp",
"cik": "0000320193",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "yfinance",
}
),
],
@@ -100,9 +127,9 @@ def test_stocks_fa_cal(params, obb):
),
(
{
"company_name": "Apple Inc",
"company_name_search": "AAPL",
"sic": "35719904",
"company_name": "Apple Inc.",
"company_name_search": "Apple Inc.",
"sic": "3571",
"include_sources": True,
"order": "asc",
"sort": "filing_date",
@@ -110,6 +137,33 @@ def test_stocks_fa_cal(params, obb):
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2022-10-27",
"filing_date_lt": "2022-11-01",
"filing_date_lte": "2022-11-01",
"filing_date_gt": "2022-10-10",
"filing_date_gte": "2022-10-10",
"period_of_report_date": "2022-09-24",
"period_of_report_date_lt": "2022-11-01",
"period_of_report_date_lte": "2022-11-01",
"period_of_report_date_gt": "2022-10-10",
"period_of_report_date_gte": "2022-10-10",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "fmp",
"cik": "0000320193",
}
),
(
{
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"provider": "yfinance",
}
),
],
@@ -241,9 +295,9 @@ def test_stocks_fa_est(params, obb):
),
(
{
"company_name": "Apple Inc",
"company_name_search": "AAPL",
"sic": "35719904",
"company_name": "Apple Inc.",
"company_name_search": "Apple Inc.",
"sic": "3571",
"include_sources": True,
"order": "asc",
"sort": "filing_date",
@@ -251,6 +305,33 @@ def test_stocks_fa_est(params, obb):
"symbol": "AAPL",
"period": "annual",
"limit": 12,
"filing_date": "2022-10-27",
"filing_date_lt": "2022-11-01",
"filing_date_lte": "2022-11-01",
"filing_date_gt": "2022-10-10",
"filing_date_gte": "2022-10-10",
"period_of_report_date": "2022-09-24",
"period_of_report_date_lt": "2022-11-01",
"period_of_report_date_lte": "2022-11-01",
"period_of_report_date_gt": "2022-10-10",
"period_of_report_date_gte": "2022-10-10",
}
),
(
{
"provider": "fmp",
"symbol": "AAPL",
"limit": 12,
"period": "annual",
"cik": "0000320193",
}
),
(
{
"provider": "yfinance",
"symbol": "AAPL",
"limit": 12,
"period": "annual",
}
),
],
@@ -265,9 +346,7 @@ def test_stocks_fa_income(params, obb):
@pytest.mark.parametrize(
"params",
[
({"symbol": "AAPL", "limit": 10, "period": "annual"}),
],
[({"symbol": "AAPL", "limit": 10, "period": "annual"})],
)
@pytest.mark.integration
def test_stocks_fa_income_growth(params, obb):
@@ -521,6 +600,7 @@ def test_stocks_ca_peers(params, obb):
[
({"symbol": "AAPL"}),
({"date": "2023-01-01", "provider": "intrinio", "symbol": "AAPL"}),
({"provider": "cboe", "symbol": "AAPL"}),
],
)
@pytest.mark.integration
@@ -553,6 +633,7 @@ def test_stocks_options_chains(params, obb):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"function_": "TIME_SERIES_DAILY",
}
),
(
@@ -580,6 +661,7 @@ def test_stocks_options_chains(params, obb):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"timeseries": 1,
}
),
(
@@ -589,16 +671,20 @@ def test_stocks_options_chains(params, obb):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"timeseries": 1,
}
),
(
{
"timezone": "UTC",
"source": "realtime",
"interval_size": "30m",
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"start_time": "00:00:00",
"end_time": "23:59:59",
}
),
(
@@ -610,6 +696,8 @@ def test_stocks_options_chains(params, obb):
"symbol": "AAPL",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"start_time": "00:00:00",
"end_time": "23:59:59",
}
),
(
@@ -722,6 +810,27 @@ def test_stocks_load(params, obb):
"limit": 20,
}
),
(
{
"provider": "fmp",
"symbols": "AAPL",
"limit": 20,
}
),
(
{
"provider": "yfinance",
"symbols": "AAPL",
"limit": 20,
}
),
(
{
"provider": "intrinio",
"symbols": "AAPL",
"limit": 20,
}
),
],
)
@pytest.mark.integration
@@ -764,6 +873,7 @@ def test_stocks_search(params, obb):
[
({"symbol": "AAPL"}),
({"source": "iex", "provider": "intrinio", "symbol": "AAPL"}),
({"symbol": "AAPL", "provider": "fmp"}),
],
)
@pytest.mark.integration

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,874 @@
"""Test ta extension."""
import random
from typing import Literal
import pytest
from openbb_core.app.model.obbject import OBBject
@pytest.fixture(scope="session")
def obb(pytestconfig):
"""Fixture to setup obb."""
if pytestconfig.getoption("markexpr") != "not integration":
import openbb
return openbb.obb
data = {}
def get_stocks_data():
import openbb # pylint:disable=import-outside-toplevel
if "stocks_data" in data:
return data["stocks_data"]
symbol = random.choice(["AAPL", "NVDA", "MSFT", "TSLA", "AMZN", "V"]) # noqa: S311
provider = random.choice(["fmp", "intrinio", "polygon", "yfinance"]) # noqa: S311
data["stocks_data"] = openbb.obb.stocks.load(
symbol=symbol, provider=provider
).results
return data["stocks_data"]
def get_crypto_data():
import openbb # pylint:disable=import-outside-toplevel
if "crypto_data" in data:
return data["crypto_data"]
# TODO : add more crypto providers and symbols
symbol = random.choice(["BTC"]) # noqa: S311
provider = random.choice(["fmp"]) # noqa: S311
data["crypto_data"] = openbb.obb.crypto.load(
symbol=symbol, provider=provider
).results
return data["crypto_data"]
def get_data(menu: Literal["stocks", "crypto"]):
funcs = {"stocks": get_stocks_data, "crypto": get_crypto_data}
return funcs[menu]()
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"length": "",
"mamode": "",
"drift": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"length": "15",
"mamode": "rma",
"drift": "2",
"offset": "1",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_atr(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.atr(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"close_column": "",
"period": "",
"start_date": "",
"end_date": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"close_column": "adj_close",
"period": "125",
"start_date": "",
"end_date": "",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_fib(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.fib(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "offset": ""}, "stocks"),
({"data": "", "index": "date", "offset": "1"}, "crypto"),
],
)
@pytest.mark.integration
def test_ta_obv(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.obv(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "length": "", "signal": ""}, "stocks"),
({"data": "", "index": "date", "length": "15", "signal": "2"}, "crypto"),
],
)
@pytest.mark.integration
def test_ta_fisher(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.fisher(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"fast": "",
"slow": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"fast": "5",
"slow": "15",
"offset": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_adosc(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.adosc(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"std": "",
"mamode": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "55",
"std": "3",
"mamode": "wma",
"offset": "1",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_bbands(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.bbands(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "55",
"offset": "5",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_zlma(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.zlma(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "length": "", "scalar": ""}, "stocks"),
(
{
"data": "",
"index": "date",
"length": "30",
"scalar": "110",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_aroon(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.aroon(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "55",
"offset": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_sma(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.sma(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"target": "",
"show_all": "",
"asint": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"target": "high",
"show_all": "true",
"asint": "true",
"offset": "5",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_demark(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.demark(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "anchor": "", "offset": ""}, "stocks"),
({"data": "", "index": "date", "anchor": "W", "offset": "5"}, "crypto"),
],
)
@pytest.mark.integration
def test_ta_vwap(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.vwap(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"fast": "",
"slow": "",
"signal": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"fast": "10",
"slow": "30",
"signal": "10",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_macd(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.macd(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "55",
"offset": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_hma(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.hma(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"lower_length": "",
"upper_length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"lower_length": "30",
"upper_length": "40",
"offset": "5",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_donchian(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.donchian(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"conversion": "",
"base": "",
"lagging": "",
"offset": "",
"lookahead": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"conversion": "10",
"base": "30",
"lagging": "50",
"offset": "30",
"lookahead": "true",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_ichimoku(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.ichimoku(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "target": "", "period": ""}, "stocks"),
(
{
"data": "",
"index": "date",
"target": "close",
"period": "95",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_clenow(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.clenow(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"length": "",
"scalar": "",
"drift": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"length": "60",
"scalar": "90.0",
"drift": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_adx(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.adx(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "60",
"offset": "10",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_wma(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.wma(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "length": "", "scalar": ""}, "stocks"),
(
{
"data": "",
"index": "date",
"length": "16",
"scalar": "0.02",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_cci(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.cci(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "",
"index": "",
"length": "",
"scalar": "",
"drift": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "date",
"length": "16",
"scalar": "90.0",
"drift": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_rsi(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.rsi(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"fast_k_period": "",
"slow_d_period": "",
"slow_k_period": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"fast_k_period": "12",
"slow_d_period": "2",
"slow_k_period": "2",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_stoch(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.stoch(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"length": "",
"scalar": "",
"mamode": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"length": "22",
"scalar": "24",
"mamode": "sma",
"offset": "5",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_kc(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.kc(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
({"data": "", "index": "", "length": ""}, "stocks"),
({"data": "", "index": "date", "length": "20"}, "crypto"),
],
)
@pytest.mark.integration
def test_ta_cg(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.cg(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"index": "",
"lower_q": "",
"upper_q": "",
"model": "",
"is_crypto": "",
},
"stocks",
),
(
{
"data": "",
"index": "date",
"lower_q": "0.3",
"upper_q": "0.7",
"model": "Parkinson",
"is_crypto": "true",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_cones(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.cones(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params, data_type",
[
(
{
"data": "",
"target": "close",
"index": "date",
"length": "",
"offset": "",
},
"stocks",
),
(
{
"data": "",
"target": "high",
"index": "",
"length": "60",
"offset": "10",
},
"crypto",
),
],
)
@pytest.mark.integration
def test_ta_ema(params, data_type, obb):
params = {p: v for p, v in params.items() if v}
params["data"] = get_data(data_type)
result = obb.ta.ema(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -0,0 +1,26 @@
"""Test the integration tests."""
from extensions.tests.utils.integration_tests_testers import (
check_missing_integration_test_params,
check_missing_integration_test_providers,
get_integration_tests,
get_module_functions,
)
def run_test(test_type: str, check_function) -> None:
"""Run tests helper function."""
integration_tests = get_integration_tests(test_type=test_type)
functions = get_module_functions(integration_tests)
missing_items = check_function(functions)
assert not missing_items, "\n".join(missing_items)
def test_api_interface_integration_test_providers() -> None:
"""Test if there are any missing providers for integration tests."""
run_test("api", check_missing_integration_test_providers)
def test_api_interface_integration_test_params() -> None:
"""Test if there are any missing params for integration tests."""
run_test("api", check_missing_integration_test_params)

View File

@@ -0,0 +1,26 @@
"""Test the integration tests."""
from extensions.tests.utils.integration_tests_testers import (
check_missing_integration_test_params,
check_missing_integration_test_providers,
get_integration_tests,
get_module_functions,
)
def run_test(test_type: str, check_function) -> None:
"""Run tests helper function."""
integration_tests = get_integration_tests(test_type=test_type)
functions = get_module_functions(integration_tests)
missing_items = check_function(functions)
assert not missing_items, "\n".join(missing_items)
def test_python_interface_integration_test_providers() -> None:
"""Test if there are any missing providers for integration tests."""
run_test("python", check_missing_integration_test_providers)
def test_python_interface_integration_test_params() -> None:
"""Test if there are any missing params for integration tests."""
run_test("python", check_missing_integration_test_params)

View File

@@ -0,0 +1,13 @@
import base64
from openbb_core.env import Env
def get_auth() -> str:
"""Returns the basic auth header."""
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return f"Basic {base64_bytes.decode('ascii')}"

View File

@@ -1,9 +1,10 @@
import os
from platform.core.openbb_core.app.provider_interface import ProviderInterface
from platform.core.openbb_core.app.router import CommandMap
from typing import Dict, List, Type, get_type_hints
import requests
from openbb_core.app.provider_interface import ProviderInterface
from openbb_core.app.router import CommandMap
from extensions.tests.utils.integration_tests_generator import get_test_params
@@ -25,20 +26,17 @@ def write_init_test_template(http_method: str, path: str):
import pytest
import requests
from openbb_provider.utils.helpers import get_querystring
def get_token():
return requests.post(
"http://0.0.0.0:8000/api/v1/account/token",
data={"username": "openbb", "password": "openbb"},
timeout=5,
)
import base64
from openbb_core.env import Env
@pytest.fixture(scope="session")
def headers():
access_token = get_token().json()["access_token"]
return {"Authorization": f"Bearer {access_token}"}
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
"""
with open(path, "w") as f:
@@ -51,11 +49,11 @@ def write_test_w_template(
params_str = ",\n".join([f"({params})" for params in params_list])
http_template_request = {
"get": "requests.get(url, headers=headers, timeout=5)",
"post": "requests.post(url, headers=headers, timeout=5, data=data)",
"get": "requests.get(url, headers=headers, timeout=10)",
"post": "requests.post(url, headers=headers, timeout=10, data=body)",
}
http_template_params = {"get": "", "post": "data = json.dumps(params.pop('data'))"}
http_template_params = {"get": "", "post": "body = json.dumps(params.pop('data'))"}
template = f"""
@pytest.mark.parametrize(
@@ -132,7 +130,7 @@ def write_integration_tests(
if __name__ == "__main__":
r = requests.get("http://0.0.0.0:8000/openapi.json", timeout=5).json()
r = requests.get("http://0.0.0.0:8000/openapi.json", timeout=10).json()
if not r:
raise Exception("Could not get openapi.json")

View File

@@ -1,18 +1,32 @@
"""Integration test generator."""
from pathlib import Path, PosixPath
from platform.core.openbb_core.app.provider_interface import ProviderInterface
from platform.core.openbb_core.app.router import CommandMap
from typing import Any, Dict, List, Literal, get_origin
from typing import Any, Dict, List, Literal, Tuple, Type, get_origin, get_type_hints
from openbb_core.app.provider_interface import ProviderInterface
from openbb_core.app.router import CommandMap
from pydantic.fields import FieldInfo
from pydantic_core import PydanticUndefined
cm = CommandMap(coverage_sep=".")
TEST_TEMPLATE = """\n\n@pytest.mark.parametrize(
"params",
[
{params}
],
)
@pytest.mark.integration
def test_{test_name}(params, obb):
params = {{p: v for p, v in params.items() if v}}
result = obb.{command_name}(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
"""
def find_extensions():
"""Find extensions."""
filter_ext = ["tests", "ta", "qa", "econometrics", "charting"]
filter_ext = ["tests", "charting", "__pycache__"]
extensions = [x for x in Path("openbb_platform/extensions").iterdir() if x.is_dir()]
extensions = [x for x in extensions if x.name not in filter_ext]
return extensions
@@ -70,7 +84,7 @@ def get_model_params(param_fields: Dict[str, FieldInfo]) -> Dict[str, Any]:
elif field.annotation == bool:
test_params[field_name] = True
elif get_origin(field.annotation) is Literal:
test_params[field_name] = field.annotation.__args__[0]
test_params[field_name] = field.annotation.__args__[0] # type: ignore
return test_params
@@ -103,83 +117,132 @@ def get_test_params(
return test_params_list
def get_test_params_data_processing(hints: Dict[str, Type]):
"""Get the test params for the data processing commands."""
return list(hints.keys())
def get_full_command_name_and_test_name(route: str) -> Tuple[str, str]:
"""Get the full command name and test name."""
cmd_parts = route.split("/")
del cmd_parts[0]
menu = cmd_parts[0]
command = cmd_parts[-1]
sub_menus = cmd_parts[1:-1]
sub_menus_str_test_name = f"_{'_'.join(sub_menus)}" if sub_menus else ""
sub_menu_str_cmd = f".{'.'.join(sub_menus)}" if sub_menus else ""
full_command = f"{menu}{sub_menu_str_cmd}.{command}"
test_name = f"{menu}{sub_menus_str_test_name}_{command}"
return test_name, full_command
def test_exists(command_name: str, path: str):
"""Check if test exists."""
with open(path) as f:
return command_name in f.read()
def write_to_file_w_template(test_file, params_list, full_command, test_name):
"""Write to file with template."""
params = ""
for test_params in params_list:
params += f"({test_params}),\n"
if not test_exists(command_name=full_command, path=test_file):
with open(test_file, "a", encoding="utf-8", newline="\n") as f:
f.write(
TEST_TEMPLATE.format(
test_name=test_name,
command_name=full_command,
params=params,
)
)
def write_test(
test_file: PosixPath,
commands_model: Dict[str, str],
extension_name: str,
provider_interface_map: Dict[str, Any],
):
"""Write test."""
for route, model in commands_model.items():
if extension_name in route and route.startswith(f"/{extension_name}/"):
test_name, full_command = get_full_command_name_and_test_name(route=route)
test_params_list = get_test_params(
model_name=model,
provider_interface_map=provider_interface_map,
)
write_to_file_w_template(
test_file=test_file,
params_list=test_params_list,
full_command=full_command,
test_name=test_name,
)
def write_test_data_processing(
test_file: PosixPath, commands_map: Dict[str, str], extension_name: str
):
"""Write test for data processing commands."""
for route, _ in commands_map.items():
if extension_name in route and route.startswith(f"/{extension_name}/"):
test_name, full_command = get_full_command_name_and_test_name(route=route)
hints = get_type_hints(commands_map[route])
hints.pop("cc", None)
hints.pop("return", None)
test_params_list = [{k: "" for k in get_test_params_data_processing(hints)}]
write_to_file_w_template(
test_file=test_file,
params_list=test_params_list,
full_command=full_command,
test_name=test_name,
)
def add_test_commands_to_file( # pylint: disable=W0102
extensions: List[PosixPath],
commands_model: Dict[str, str] = cm.commands_model,
) -> None:
"""Add test commands to file."""
provider_interface = ProviderInterface()
provider_interface_map = provider_interface.map
template = """\n\n@pytest.mark.parametrize(
"params",
[
{params}
],
)
@pytest.mark.integration
def test_{test_name}(**params, obb):
result = obb.{command_name}(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
"""
cm = CommandMap()
commands_model = cm.commands_model
commands_map = cm.map
extensions_names = [path.name for path in extensions]
extensions_w_models = list({route.split("/")[1] for route in commands_model})
extensions_data_processing = [
ext for ext in extensions_names if ext not in extensions_w_models
]
for extension in extensions:
extension_name = extension.name
test_file_name = f"test_{extension_name}_python.py"
test_file = extension / "integration" / test_file_name
with open(test_file, "a", encoding="utf-8", newline="\n") as f:
for command in commands_model:
if extension_name in command and command.startswith(
f".{extension_name}."
):
extension_name = command.split(".")[1]
if len(command.split(".")) > 3:
test_name = (
extension_name
+ "_"
+ command.split(".")[2]
+ "_"
+ command.split(".")[3]
)
elif len(command.split(".")) == 3:
test_name = extension_name + "_" + command.split(".")[2]
command_name = command.split(".")[-1]
if "_" in command_name:
full_command_name = test_name.replace("_", ".", 2)
# The code below double checks if the full command name is correct.
# This eliminates edge cases.
fix_full_command_name = full_command_name.split(".")
for i, part in enumerate(fix_full_command_name):
if part == command_name.split("_")[0]:
fix_full_command_name[i] = command_name
fix_full_command_name.pop()
full_command_name = ".".join(fix_full_command_name)
else:
full_command_name = test_name.replace("_", ".")
test_params_list = get_test_params(
model_name=commands_model[command],
provider_interface_map=provider_interface_map,
)
params = ""
for test_params in test_params_list:
params += f"({test_params}),\n"
read_file = open(test_file) # noqa
if full_command_name not in read_file.read():
f.write(
template.format(
test_name=test_name,
command_name=full_command_name,
params=params,
)
)
if extension_name in extensions_data_processing:
write_test_data_processing(
test_file=test_file,
commands_map=commands_map,
extension_name=extension_name,
)
else:
write_test(
test_file=test_file,
commands_model=commands_model,
extension_name=extension_name,
provider_interface_map=provider_interface_map,
)
def write_integration_test() -> None:

View File

@@ -0,0 +1,196 @@
"""Test if there are any missing providers for python interface integration tests."""
import importlib.util
import inspect
import os
from typing import Any, Callable, Dict, List, Literal, Tuple, Union, get_type_hints
from openbb_core.app.provider_interface import ProviderInterface
from openbb_core.app.router import CommandMap
from extensions.tests.utils.integration_tests_generator import (
find_extensions,
get_test_params_data_processing,
)
def get_integration_tests(test_type: Literal["api", "python"]) -> List[Any]:
"""Get integration tests for the OpenBB Platform."""
integration_tests: List[Any] = []
if test_type == "python":
file_end = "_python.py"
elif test_type == "api":
file_end = "_api.py"
for extension in find_extensions():
integration_folder = os.path.join(extension, "integration")
for file in os.listdir(integration_folder):
if file.endswith(file_end):
file_path = os.path.join(integration_folder, file)
module_name = file[:-3] # Remove .py from file name
spec = importlib.util.spec_from_file_location(module_name, file_path)
if spec:
module = importlib.util.module_from_spec(spec)
if spec.loader:
spec.loader.exec_module(module)
integration_tests.append(module)
return integration_tests
def get_module_functions(module_list: List[Any]) -> Dict[str, Any]:
"""Get all functions from a list of modules."""
functions = {}
for module in module_list:
for name, obj in inspect.getmembers(module):
if inspect.isfunction(obj):
functions[name] = obj
return functions
def check_missing_providers(
command_params: Union[Dict[str, Dict[str, dict]], List[Tuple[Dict[str, str], str]]],
function_params: List[dict],
function,
processing: bool = False,
) -> List[str]:
"""Check if there are any missing providers for a command."""
if processing or not isinstance(command_params, dict):
return []
missing_providers: List[str] = []
providers = list(command_params.keys())
providers.remove("openbb")
for test_params in function_params:
provider = test_params.get("provider", None)
if provider:
try: # noqa
providers.remove(provider)
except ValueError:
pass
if providers:
# if there is only one provider left and the length of the
# test_params is 1, we can ignore because it is picked up by default
if len(providers) == 1 and len(function_params) == 1:
pass
else:
missing_providers.append(f"Missing providers for {function}: {providers}")
return missing_providers
def check_missing_params(
command_params: Union[Dict[str, Dict[str, dict]], List[Tuple[Dict[str, str], str]]],
function_params: List[dict],
function,
processing: bool = False,
) -> List[str]:
"""Check if there are any missing params for a command."""
missing_params = []
if not processing:
for test_params in function_params:
if "provider" in test_params:
provider = test_params["provider"]
if provider in command_params:
for expected_param in command_params[provider]["QueryParams"][
"fields"
]:
if expected_param not in test_params:
missing_params.append(
f"Missing param {expected_param} for provider {provider} in function {function}"
)
elif isinstance(command_params, dict):
for expected_param in command_params["openbb"]["QueryParams"]["fields"]:
if expected_param not in test_params:
missing_params.append(
f"Missing standard param {expected_param} in function {function}"
)
else:
for test_params in function_params:
if isinstance(command_params, list):
try:
iter_commands_params = command_params[0][0]
except KeyError:
iter_commands_params = command_params[0] # type: ignore
for expected_param in iter_commands_params:
try:
used_params = test_params[0].keys()
except KeyError:
used_params = test_params.keys()
if expected_param not in used_params and expected_param != "return":
missing_params.append(
f"Missing param {expected_param} in function {function}"
)
return missing_params
def check_integration_tests(
functions: Dict[str, Any],
check_function: Callable[
[
Union[Dict[str, Dict[str, dict]], List[Tuple[Dict[str, str], str]]],
List[dict],
str,
bool,
],
List[str],
],
) -> List[str]:
"""Check if there are any missing items for integration tests."""
pi = ProviderInterface()
provider_interface_map = pi.map
cm = CommandMap(coverage_sep=".")
function_params: List[dict] = []
all_missing_items: List[str] = []
used_functions: List[str] = []
for command, model in cm.commands_model.items():
for function in functions:
if command[1:].replace(".", "_") == function.replace("test_", ""):
command_params: Dict[str, Dict[str, dict]] = provider_interface_map[
model
]
function_params = functions[function].pytestmark[1].args[1]
missing_items = check_function(
command_params, function_params, function, False
)
all_missing_items.extend(missing_items)
used_functions.append(function)
# the processing commands are the ones that are left
processing_functions = [
function for function in functions if function not in used_functions
]
for route, _ in cm.map.items():
for function in processing_functions:
if route.replace("/", "_")[1:] == function.replace("test_", ""):
hints = get_type_hints(cm.map[route])
processing_command_params = [
{k: "" for k in get_test_params_data_processing(hints)}
]
function_params = functions[function].pytestmark[1].args[1]
missing_items = check_function(
processing_command_params, function_params, function, True # type: ignore
)
all_missing_items.extend(missing_items)
return all_missing_items
def check_missing_integration_test_providers(functions: Dict[str, Any]) -> List[str]:
"""Check if there are any missing providers for integration tests."""
return check_integration_tests(functions, check_missing_providers)
def check_missing_integration_test_params(functions: Dict[str, Any]) -> List[str]:
"""Check if there are any missing params for integration tests."""
return check_integration_tests(functions, check_missing_params)

View File

@@ -12,9 +12,6 @@ from openbb_core.api.auth.user import (
)
# ruff: noqa: S105 S106
@pytest.mark.parametrize(
"error, correct, received",
[

View File

@@ -1,125 +0,0 @@
"""Test the Query class."""
# pylint: disable=redefined-outer-name
from dataclasses import dataclass
from unittest.mock import MagicMock, patch
import pytest
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.provider_interface import (
ExtraParams,
ProviderChoices,
StandardParams,
)
from openbb_core.app.query import Query
from pydantic import BaseModel, ConfigDict
class MockBaseModel(BaseModel):
"""Mock BaseModel class."""
model_config = ConfigDict(extra="allow", populate_by_name=True)
def create_mock_query():
"""Mock query."""
class StockHistorical:
"""Mock StockHistorical class."""
start_date = "2020-01-01"
end_date = "2020-01-05"
symbol = "AAPL"
return StockHistorical()
def create_mock_extra_params():
"""Mock ExtraParams dataclass."""
@dataclass
class StockHistorical:
"""Mock ExtraParams dataclass."""
sort: str = "desc"
return StockHistorical()
@pytest.fixture(scope="module")
def query():
"""Set up query."""
return Query(
cc=CommandContext(),
provider_choices=ProviderChoices(provider="fmp"),
standard_params=StandardParams(),
extra_params=ExtraParams(),
)
def test_init(query):
"""Test init."""
assert query
def test_filter_extra_params(query):
"""Test filter_extra_params."""
extra_params = create_mock_extra_params()
extra_params = query.filter_extra_params(extra_params, "fmp")
assert isinstance(extra_params, dict)
assert len(extra_params) == 0
def test_filter_extra_params_wrong_param(query):
"""Test filter_extra_params."""
@dataclass
class StockHistorical:
"""Mock ExtraParams dataclass."""
sort: str = "desc"
limit: int = 4
extra_params = StockHistorical()
assert not query.filter_extra_params(extra_params, "fmp")
@pytest.fixture
def mock_registry():
"""Mock registry."""
with patch(
"openbb_core.app.provider_interface.ProviderInterface"
) as mock_get_provider_interface:
mock_registry = MagicMock()
mock_get_provider_interface.return_value.build_registry.return_value = (
mock_registry
)
yield mock_registry
@pytest.fixture
def query_instance():
"""Set up query."""
standard_params = create_mock_query()
extra_params = create_mock_extra_params()
cc = CommandContext()
setattr(cc.user_settings.credentials, "fmp_api_key", "1234")
return Query(
cc=cc,
provider_choices=ProviderChoices(provider="fmp"),
standard_params=standard_params,
extra_params=extra_params,
)
def test_execute_method_fake_credentials(query_instance, mock_registry):
"""Test execute method without setting credentials."""
mock_fetch_result = MockBaseModel()
mock_registry.fetch.return_value = mock_fetch_result
with pytest.raises(Exception):
query_instance.execute()

View File

@@ -1,2 +1,3 @@
# TODO: See if we can dynamically import the test modules under the openbb_platform
# file structure.
# TODO: Add global fixture for headers here

1
pytest.ini vendored
View File

@@ -2,6 +2,7 @@
addopts = -p no:warnings
markers =
linux: tests that are not stable on Windows
integration: OpenBB Platform integration test marker
testpaths =
tests
openbb_platform/**/tests