Skip to content

Commit

Permalink
using pytest, todo: mistune vulnerability
Browse files Browse the repository at this point in the history
  • Loading branch information
Nelson-Gon committed Aug 5, 2022
1 parent e5f3963 commit 9cfcdf6
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: python -m pip install -e .

- name: Run tests and show coverage on the command line
run: coverage run tests.py && coverage report -m && coverage xml
run: python3 -m pytest --cov-report term --cov-report xml:coverage.xml --cov=pyfdc

- name: Upload reports to codecov
env:
Expand Down
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

**Version 0.2.3**

* Tests are now written with the `pytest` framework which means that this is now a dependency. We also now use `pytest_cov` for coverage reports. This also
introduces yet another dependency.

* Fixed an issue in `get_food_details` due to a change in column naming in the API interface. This is now automated backend.

**Version 0.2.2**
Expand Down
7 changes: 6 additions & 1 deletion docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ Welcome to pyfdc's changelog
**Version 0.2.3**


* Fixed an issue in ``get_food_details`` due to a change in column naming in the API interface. This is now automated backend.
*
Tests are now written with the ``pytest`` framework which means that this is now a dependency. We also now use ``pytest_cov`` for coverage reports. This also
introduces yet another dependency.

*
Fixed an issue in ``get_food_details`` due to a change in column naming in the API interface. This is now automated backend.

**Version 0.2.2**

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
mistune==2.0.3
# Known security issues but m2r won't work with anything above 0.8.4 for some reason
mistune==0.8.4
m2r==0.2.1
coverage==5.3.1
pytest==7.1.2
Expand Down
106 changes: 106 additions & 0 deletions test_pyfdc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from pyfdc.pyfdc import FoodDataCentral
from pandas import DataFrame
import os
from unittest.mock import patch
import requests
from unittest import mock
from pyfdc.utils import set_api_key
import pytest

# set API key from a users OS environ
# Only on Github actions
# TODO: Check that this only runs on GH Actions
set_api_key("EMgmhkxg9Jfp2N8zw6gQ29u5Oek1sHvsWmkFJycE")

@pytest.fixture
def my_search():
def _search(**kwargs):
return FoodDataCentral(**kwargs)
return _search


def test_instance(my_search):
assert isinstance(my_search(), FoodDataCentral)
assert isinstance(my_search().available_targets, dict)
with pytest.warns(Warning, match = "Providing an api_key is discouraged, please consider using set_api_key.") as wrng:
my_search(api_key = "fakekey")



# This mocks what set_api_key does.
# TODO: use an actual mock, this looks like a poor mxn's mock?
def test_api_key_mocks():
with patch.dict('os.environ', {"pyfdc_key": "EMgmhkxg9Jfp2N8zw6gQ29u5Oek1sHvsWmkFJycE"}):
assert os.environ["pyfdc_key"] == "EMgmhkxg9Jfp2N8zw6gQ29u5Oek1sHvsWmkFJycE"
assert "pyfdc_key" in os.environ
pass

def test_get_food_info(my_search):
with pytest.warns(UserWarning, match = "No target_fields were provided, returning fdc_id, ingredients, and description.") as uwarn:
my_search().get_food_info(search_phrase="cheese")

with pytest.raises(TypeError, match ="target should be a list or tuple not int") as err:
my_search().get_food_info(search_phrase="cheese", target_fields=1234)

# Check that we indeed get cheese
res = my_search().get_food_info(search_phrase="cheese", target_fields=["description"])
say_cheese = res["description"].iloc[0]
assert say_cheese == "CHEESE"

# Check that we raise a KeyError
with pytest.raises(KeyError):
# Need to figure out how to test the actual error
my_search().get_food_info(search_phrase="cheese", target_fields=["not_in"])

# Check that we get an HTTPError if we have the wrong api_key
with pytest.raises(requests.exceptions.HTTPError):
FoodDataCentral(api_key="fakekey").get_food_info(search_phrase="cheese")

def test_get_food_details(my_search):
with pytest.raises(AssertionError, match ="fdc_id should not be None") as err:
my_search().get_food_details()

with pytest.raises(AssertionError, match = "fdc_id should be an int not str") as err:
my_search().get_food_details(fdc_id="string_id")

with pytest.warns(UserWarning, match = "No target_field was provided, returning low level results.") as uwarn2:
my_search().get_food_details(fdc_id=496446)


# Check that we get the expected result

food_details = my_search().get_food_details(fdc_id=496446, target_field="nutrients")

assert isinstance(food_details, DataFrame)

# Expect HTTP Errors if we have fake api keys for instance
# https://docs.pytest.org/en/6.2.x/reference.html#pytest._code.ExceptionInfo
with pytest.raises(requests.HTTPError) as exc_info:
FoodDataCentral(api_key="fake").get_food_details(fdc_id=496446,
target_field="description")

# Fake API Key --> I will not let you in :)
assert exc_info.value.response.status_code == 403

with pytest.raises(KeyError):
my_search().get_food_details(fdc_id=496446, target_field="some_fake_key")

# Check that we get the same fdc_id as we sent

assert my_search().get_food_details(fdc_id=496446, target_field="fdcId") == 496446

assert isinstance(my_search().get_food_details(fdc_id=496446, target_field="label_nutrients"),
DataFrame)
# Check that we can raise a KeyError if no label nutrients are present
# print(my_search.get_food_details(fdc_id=168977, target_field="label_nutrients"))
with pytest.raises(KeyError, match="FDC ID 168977 has no label nutrients."):
my_search().get_food_details(fdc_id=168977, target_field="label_nutrients")
# @mock.patch("pyfdc.utils.input")
# def test_utils(self, mock_input):
# mock_input.side_effect = "False"
# with self.assertRaises(ValueError):
# set_api_key()




0 comments on commit 9cfcdf6

Please sign in to comment.