Files
OpenBB/tests
didierlopes.eth f1ecd1fe90 Add logging w decorators (#1173)
* Example of adding logging

* make log possible with decorators

* remove lineno since we'll have logging at start and end

* rename log_decorator to log_execution

* add lineno and let it be 0 for log_start_end

* Decrease logging level (#1150)

* reset different coin from dd controller on crypto (#1118)

* Fix to dcf command (#1115)

* Fix to dcf command

* Forgot to take out a comment

* Dider change

* user data patch for now

* revert DD report with pickle dataframe being stored (#1120)

* Discordbot/expiry reactions (#1114)

* added load extension for options menu

* options menu: oi, iv, unusual options

* Update opt_menu.py

* Update unu.py

if no num requested set default to 10

* Update opt_menu.py

+ !oi ticker expiry request added without inputting date format. accepts 0-9 up to 10 weeks
+ added option volume plot (works same as oi)

* Create vol.py

* Create reaction_helper.py

* Cleaned up, added historical options

Cleaned up
+ added historical options data
+ added expiry reaction helper function

* Create hist.py

* cleanup

* added min/max strike price

* cleanup

* cleanup, added min/max strike price

* Update opt_menu.py

* added yfinance if no tradier token

* Update vol.py

* Update opt_menu.py

* Create oi_tradier.py

* Update oi.py

* Update opt_menu.py

* Update oi.py

* Update opt_menu.py

* Update oi.py

* Update iv.py

* Update unu.py

* Update oi_tradier.py

* Update hist.py

* Update opt_menu.py

* Update reaction_helper.py

* Create options_menu.py

* Update run_discordbot.py

* Update vol.py

* Rename discordbot/options_menu.py to discordbot/stocks/options/options_menu.py

* Delete opt_menu.py

* Update oi.py

+ min strike/max strike

* Delete oi_tradier.py

* Update options_menu.py

* Update hist.py

* Update vol.py

* Update oi.py

* Update options_menu.py

* Update options_menu.py

* Update options_menu.py

* Linting/Pre-Commit Fixes

* linting

* Linting

* linting

* pylint fixes

* Update iv.py

* Update options_menu.py

* Update reaction_helper.py

* Improved Code

- removed 148 lines same function

* Update run_discordbot.py

* Update reaction_helper.py

* Updated Options Menu

+ reaction expiry lookup
+ added unu, iv, oi, vol ,hist

* mypy fix

* msg delete delay

* Update options_menu.py

* fix

seems bot doesn't like when last emoji is empty.
added an X when strike c/p empty

* Update opt_cmd.py

* Update options_menu.py

* better handling

* Update options_menu.py

* Update opt_cmd.py

* fix stocks.opt indention

* hist.py token/error handling

* Update hist.py

* Update options_menu.py

* Update hist.py

* Add whatif scenario feature (#1122)

* Add whatif scenario feature

* fix tests

* Mutual funds (#1106)

* Add mutual fund menu based primarily on investpy (investment.com)

* Add start/end date for loading + some bug fixes

* hugo

* poetry add investpy rich dnspython  then poetry update

* fix reset (need to load country) and dim yfinance commands when country not US

* Fix search and add better error handling

* Catch yfinance commands when country not US.  Improve loading to change country if symbol found but not in matching country.  Changed main menu printing.

* Fix poetry / reqs merge conflict

* review comments

* Once again update poetry

* Clean up poetry to match conda (numpy was culprit)

* cvxpy down

* Think i goofed on generating reqs full

* update poetry metadata

* cleanup after review 2

* move space

* another deps try

* bump pygmnets in yaml

* try something different

* rename console -> t_console (terminal_console) for mypy

* Handle KeyboardInterrupt on user input read (#1124)

Co-authored-by: David Khouya <david.khouya@leddartech.com>

* Improve hugo docs (#1113)

* added gitignore to website, fix portfolio toggle and website path

* updating styles and homepage

* added index page, removed dark mode, updated styling

* fixed colors

* updated urls (removed /GamestonkTerminal after url)

* added new hr feature (#1128)

* fix assets on hugo server and revert url (#1129)

* fix darkmode issues (#1130)

* Tests : Stocks > Options (#1125)

* Update tests : conftest

* Updating tests : stocks/options

* Updating tests : fix typing

* Updating tests : black

* Updating tests : pyupgrade

* Updating tests : black

* Updating tests : mock dates in cassettes

* Updating tests : conftest

* Updating tests : black

* Updating tests : force single threading

* Updating tests : skip

* Updating tests : black

* Updating tests : conftest

* Update tests : skip stocks/options/controller

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : fixing issue

* Updating tests : add init

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : conftest

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Updating tests : skip

* Tests : Stocks > Research + Screener (#1131)

* Updating tests : stocks/research

* Updating tests : stocks/screener

* Updating tests : stocks/screener

* improve usage of timezone in terminal (#1126)

* improve usage of timezone in terminal

* lint

* update dependencies

* address James review comments

* remove seconds from time on cmd line

* skip test

* Add insider presets (#1127)

* Add prediction to economy/fred (#1133)

* Fixing tradier (#1135)

* improve additional info of stocks (#1137)

* improve additional info of stocks

* unnecessary code

* Qa update (#1139)

* Add line option to common - qa

* rich to controller + lower case for pick

* Change qa_view to rich + hugo

* Update _index.md

* fix test

* fix test pt 2

* change menu print

* Refactored Reports (#1123)

* First working program

* added Voila support

* Attempt to fix requirements

* Revert depen

* Another dependency test

* Fixed errors

* Small changes

* Fixed help

* Added port warning

* Fixed continued terminal use

* Last change, we good fam

* Added placeholder so we can have stored

* Didier changes

* Fixed exit

* Fixed issue

* Update stocks : ta > tradingview (#1144)

* Tests : Stocks > Option + Technical Analysis + Screener (#1145)

* Updating tests : stocks/ta

* Updating tests : conftest

* Updating tests : stocks/screener/finviz

* Updating tests : stocks/options

* interactive line chart and annotation (#1140)

* interactive line chart and annotation

* add drawing flag

* New alternative data context + first sub context (Covid) (#1142)

* Crypto menu refactor (#1119)

* enabled some crypto commands in dd to be called independent of source loaded

* support for coin_map_df in all dd functions + load ta and plot chart refactor

* updated tests and removed coingecko scrapping where possible

* removed ref of command from hugo

* updated pycoingecko version

* refactoring load

* refactored load to fetch prices; pred can run independent of source now

* load by default usd on cp/cg and usdt on cb/bin

* updated to rich for formatting and updated dependencies

* fixed changes requested

* update docs

* revert discord requirements

* removed absolute from calculate change for price

* fixing pr issues

* fix loading issue when similar coins exist, move coins to home, fill n/a

* update docs for coins

* adds load to ta and pred menu

* Fix library loggers always setting DEBUG verbosity

* Set default log level to INFO

Co-authored-by: Didier Rodrigues Lopes <dro.lopes@campus.fct.unl.pt>
Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com>
Co-authored-by: teh_coderer <me@tehcoderer.com>
Co-authored-by: jmaslek <jmaslek11@gmail.com>
Co-authored-by: David Khouya <dakhouya@gmail.com>
Co-authored-by: David Khouya <david.khouya@leddartech.com>
Co-authored-by: jose-donato <43375532+jose-donato@users.noreply.github.com>
Co-authored-by: Chavithra <chavithra@gmail.com>

* Fix linting errors

* Move log decorator to the decorators.py file

* Revert test assertion so that windows tests don't hang up

* Fix pylint exception

* Bump pylint version in CI

* Skip test that hangs on windows

Co-authored-by: Artem Veremey <artem@veremey.net>
Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com>
Co-authored-by: teh_coderer <me@tehcoderer.com>
Co-authored-by: jmaslek <jmaslek11@gmail.com>
Co-authored-by: David Khouya <dakhouya@gmail.com>
Co-authored-by: David Khouya <david.khouya@leddartech.com>
Co-authored-by: jose-donato <43375532+jose-donato@users.noreply.github.com>
Co-authored-by: Chavithra <chavithra@gmail.com>
2022-01-11 19:01:46 +03:00
..
2022-01-11 19:01:46 +03:00
2021-12-21 15:19:23 +03:00

1. Gamestonk Terminal : Unit Testing

This document is part of the Gamestonk Terminal library documentation.

It aims to provide necessary information in order :

  • Run unit tests
  • Build unit tests
  • Maintain unit tests

1.1. Why having unit tests ?

Here Unit tests purpose is to allow : update without fear.

Insuring with enough confidence that : addition, removal or update of a module/function won't break other parts of the code.

To do that we need unit tests to be :

  • fast to write
  • fast to run

FAST TO WRITE

The unit tests will only tests the most common cases.

FAST TO RUN

Slow part of the code like network or database access should be either mocked or marked as slow.

2. Run unit tests

In this section we will explain everything you need to run the unit tests on Gamestonk Terminal.

2.1. How to install tests dependencies ?

To run the tests you will need the dev-dependencies.

By default poetry installs the dev-dependencies when you run this command :

poetry install

If you dont want to install the dev-dependencies you will have to add the option --no-dev like this :

poetry install --no-dev

2.2. How to run tests : by module ?

You can run tests on a specific package/module by specifying the path of this package/module, like this :

pytest tests/gamestonk_terminal/some_package
pytest tests/gamestonk_terminal/some_package/some_module.py

2.3. How to run tests : by name ?

You can run tests by their name :

pytest -k "test_function1"

2.4. How to run tests : by markers ?

You can run tests only on specific markers, like this :

pytest -m slow
pytest -k "not slow"
pytest -k "not slow and not network"

You can list the available markers using this command :

pytest --markers

2.5. How to skip tests function ?

import pytest

@pytest.skip
def test_some_function(mocker):
    pass

@pytest.skip("This time with a comment")
def test_another_function(mocker):
    pass

2.6. How to skip tests modules ?

import pytest

pytest.skip(msg="Some optional comment.", allow_module_level=True)

def test_some_function(mocker):
    pass

3. Build unit tests

3.1. Where to add my test module ?

All the unit tests should be insides the tests folder.

There should be at most one test module for each module of Gamestonk Terminal.

Each test module should follow the same path than the module it is testing.

For instance to test the following module :

  • gamestonk_terminal/stocks/due_diligence/dd_controller.py

A test module should be added here :

  • tests/gamestonk_terminal/stocks/due_diligence/test_dd_controller.py

3.2. How to record network ?

Network exchange can be recording inside a test function using the @pytest.mark.vcr marker.

Here is an example :

@pytest.mark.vcr
def test_single():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'

You can choose the cassette name using the @pytest.mark.default_cassette marker. Here is an example :

@pytest.mark.default_cassette("example.yaml")
@pytest.mark.vcr
def test_default():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'

3.2. Where to put data files ?

Each data file should be related exactly to one test module.

The purpose is to have each test module as self-contained as possible.

Data related to a test module should be stored within the same folder than this test module.

Example with tests/gamestonk_terminal/some_package/some_module.py :

  • tests/gamestonk_terminal/some_package/cassettes/some_module/test_function1.yaml
  • tests/gamestonk_terminal/some_package/txt/some_module/test_function1.csv
  • tests/gamestonk_terminal/some_package/csv/some_module/test_function1.csv
  • tests/gamestonk_terminal/some_package/json/some_module/test_function1.json

3.3. How to filter api keys on cassettes ?

The filtering of api keys from a cassette should be done directly inside the test module using this cassette.

The purpose is to have each test module as self-contained as possible.

To filter api keys from a cassettes you can define a vcr_config fixture inside your test module.

Here is an example of filtering :

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_query_parameters": [
            ("token", "MOCK_TOKEN"),
        ]
    }

More information about vcr_config fixture in the documentation of pytest-recording :

3.4. How to mock ?

PYTEST-MOCK

A mocker fixture is available through the package pytest-mock.

Here is an example on how to mocker fixture can be used :

def test_something(mocker):
    mocker.patch("some_package.some_module")

More information about pytest-mock are available here :

MOCKEYPATCH

There is also a monkeypatch fixture available by default inside pytest.

def test_double(monkeypatch):
    monkeypatch.setattr("some_package.some_module", "Some value")

More information about monkeypatch are available here :

3.5. Which helpers are available ?

You can find the available helpers inside the following package/module :

  • tests/helpers/
  • tests/conftest.py

See also the pytest fixtures which are autoloaded helpers.

3.6. Which fixtures are available ?

You can list all the available pytest fixtures using the following command :

pytest --fixtures

More on custom fixtures here :

3.7. Which markers are available ?

You can list the available markers using this command :

pytest --markers

More information on markers location are available in pytest documentation :

3.8. Known issue / solution

YFINANCE

If a method is using the yfinance library but do not let you pick the start/end dates it will pick the current date each time.

So your test might fail the next days.

To solve that you can filter the start/end date like this :

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_query_parameters": [
            ("period1", "1598220000"),
            ("period2", "1635980400"),
        ]
    }

You can also refactor this method to let access to stard/end dates.

USER-AGENT

Some function uses a random User-Agent on the HTTP HEADER when fetching data from an API.

Here is how to filter this random User-Agent.

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_headers": [("User-Agent", None)],
    }

YFINANCE

If you do something like this with yfinance library.

import yfinance as yf

yf.download(tickers="VCYT QSI")

Chances are you requests will be multi-threaded.

Issues : as for now vcrpy seems to be incompatible with multi-threading.

The library vcrpy is used to record cassettes (network calls into yaml files).

Here is a solution to still combine yfinance and vcrpy :

import pytest
import yfinance

yf_download = yf.download
def mock_yf_download(*args, **kwargs):
    kwargs["threads"] = False
    return yf_download(*args, **kwargs)

@pytest.mark.vcr
def test_ark_orders_view(kwargs_dict, mocker, use_color):
    mocker.patch("yfinance.download", side_effect=mock_yf_download)

    yf.download(tickers="VCYT QSI")

3.9. List of useful vscode tools for unit tests

VSCODE TESTING

The default testing tool from vscode should let you add breakpoints and run debug on a specific test.

It's a convenient way to see what's inside your test while running.

More information on this tool are available here :

3.10. How to handle dev-dependencies ?

UPDATE PYPROJECT

If a library need to be added or removed from dev-dependencies this can be done directly in the pyproject.toml file.

All the dev-dependencies should be under the tool.poetry.dev-dependencies section, like in this example :

[tool.poetry.dev-dependencies]
pytest = "^6.2.2"
pylint = "^2.7.2"
flake8 = "^3.9.0"
...

EXPORT REQUIREMENTS

After updating the pyproject.toml you will have to export the requirements files using the following commands :

poetry export -f requirements.txt  -o requirements.txt --without-hashes --dev
poetry export -f requirements.txt  -o requirements-full.txt --extras prediction --without-hashes --dev
poetry export -f requirements.txt  -o discordbot/requirements.txt --extras discord --without-hashes --dev

4. Maintain unit tests

4.1. What is the PR process ? (in progress)

Here are the steps to write proper tests for Gamestonk :

A. Find right place
B. Verify coverage is above 90%
C. Set the right markers

A. Find right place

Put the code following the same module and package structure than gamestonk_terminal package.

B. Verify coverage is above 90%

Once you made your PullRequest an automation will let you know whether or not you have the proper amount of tests coverage.

You can also run the following command to check your coverage manually :

  • pytest --cov --cov-fail-under=90

C. Set the right markers

If parts of your have specificities like :

  • being slow
  • requiring network connectivity
  • requiring authentication to APIs

Then the proper markers should be sent on each test.

The rests of this document is there to provide a deeper comprehension of this steps.

A tests update might be asked whenever the answer to one of the following question is yes :

A. Is this PR fixing bug which was not detected by the current tests ?
B. Is this PR reducing code coverage ?
C. Is this PR adding features ?
D. Is this PR updating features ?

4.2. Which automations are available ?

PULL REQUEST

A github action should comment every Pull Request with the code coverage.

This automation will not enforce any rules regarding tests.

4.3. How to check code coverage ?

PULL REQUEST AUTOMATION

You should be able to see the code coverage on comment of your Pull Requests.

MANUALLY

This is how to manually check code coverage.

pytest --cov=gamestonk_terminal --cov=terminal --cov-report term-missing

You can also select a specific package/module with the option --cov.

Here is an example where we select only the package stocks\due_diligence :

pytest --cov=gamestonk_terminal\stocks\due_diligence --cov-report term-missing

PRE-COMMIT

Code coverage and unit tests are not run on pre-commit hooks since it will slow down each commit.