diff --git a/.travis.yml b/.travis.yml index ef770b0..2c59935 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ deploy: provider: pypi user: hydrosquall -install: +install: - python setup.py develop - - pip install -U pytest-cov codecov + - pip install -U pytest-cov codecov vcrpy # - pip install -U tox-travis pytest language: python @@ -23,12 +23,12 @@ python: - 2.7 # - 2.6 -script: - - export TIINGO_API_KEY=$TIINGO_API_KEY +script: + - export TIINGO_API_KEY=0000000000000000000000000000000000000000 - py.test --cov=./tiingo matrix: fast_finish: true -after_success: -- codecov \ No newline at end of file +after_success: +- codecov diff --git a/requirements_dev.txt b/requirements_dev.txt index 7b45fb2..860f19e 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -10,3 +10,4 @@ cryptography==2.0.3 PyYAML==3.12 pytest==3.2.2 pytest-runner==2.12.1 +vcrpy==1.11.1 diff --git a/setup.py b/setup.py index 7c3b8a7..71a43d3 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,7 @@ setup_requirements = [ test_requirements = [ 'pytest', + 'vcrpy', ] # Metadata about the module diff --git a/tests/fixtures/invalid_url.yaml b/tests/fixtures/invalid_url.yaml new file mode 100644 index 0000000..9c33629 --- /dev/null +++ b/tests/fixtures/invalid_url.yaml @@ -0,0 +1,33 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + User-Agent: [python-requests/2.18.4] + method: GET + uri: http://www.google.com/bing_is_great + response: + body: {string: "\n\n \n \n + \ Error 404 (Not Found)!!1\n \n \n + \

404. That\u2019s an error.\n

The requested URL + /bing_is_great was not found on this server. That\u2019s + all we know.\n"} + headers: + Content-Length: ['1574'] + Content-Type: [text/html; charset=UTF-8] + Date: ['Sun, 08 Oct 2017 10:13:15 GMT'] + Referrer-Policy: [no-referrer] + status: {code: 404, message: Not Found} +version: 1 diff --git a/tests/fixtures/list_stock_tickers.yaml b/tests/fixtures/list_stock_tickers.yaml new file mode 100644 index 0000000..b9d8ffe --- /dev/null +++ b/tests/fixtures/list_stock_tickers.yaml @@ -0,0 +1,34 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + User-Agent: [python-requests/2.18.4] + method: GET + uri: https://apimedia.tiingo.com/docs/tiingo/daily/supported_tickers.zip + response: + body: + string: !!binary | + UEsDBBQAAAAIANlmSEvFDDeNdAAAAJMAAAAVABwAc3VwcG9ydGVkX3RpY2tlcnMuY3N2VVQJAAP6 + A9pZ+gPaWXV4CwABBPUBAAAEFAAAAG3KwQrCMAyA4fueJYG0iG7HYmEXcUr1AUoMOgbdSCO4t1dv + HoQf/stnI0+iIC9+5HIXyLWKXdZFYNGRZf9UlcIrVMtqMZuAlNv3TQinAxxDiuEMyWae4JoiuK4l + dP4TeHI7dIS0bfph6P9gT7RBatF1v/gNUEsBAh4DFAAAAAgA2WZIS8UMN410AAAAkwAAABUAGAAA + AAAAAQAAAICBAAAAAHN1cHBvcnRlZF90aWNrZXJzLmNzdlVUBQAD+gPaWXV4CwABBPUBAAAEFAAA + AFBLBQYAAAAAAQABAFsAAADDAAAAAAA= + headers: + Accept-Ranges: [bytes] + Age: ['820'] + Connection: [keep-alive] + Content-Length: ['2709436'] + Content-Type: [application/zip] + Date: ['Sun, 08 Oct 2017 10:17:38 GMT'] + ETag: ['"aa6b2d0623735374b5c471305911fbac"'] + Last-Modified: ['Sat, 07 Oct 2017 23:28:33 GMT'] + Server: [AmazonS3] + Via: [1.1 5d4ff22febf83d261f03aa068f5bdc04.cloudfront.net (CloudFront)] + X-Amz-Cf-Id: [Eo3QEjB2WELpsXJhXHqylxkoU2G3DVFXCa6Ka7d0sDhOh2JG3HA08w==] + X-Cache: [Hit from cloudfront] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/news.yaml b/tests/fixtures/news.yaml new file mode 100644 index 0000000..e1d6464 --- /dev/null +++ b/tests/fixtures/news.yaml @@ -0,0 +1,35 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/news?limit=1&offset=0&sortBy=publishedDate&tickers=aapl&tickers=googl&sources=washingtonpost.com&sources=altcointoday.com&tags=Technology&tags=Bitcoin&startDate=2016-01-01&endDate=2017-08-31 + response: + body: {string: '[{ + "publishedDate": "2016-01-11T23:13:00Z", + "title": "Tech giants may be stronger than you think", + "url": "http://www.cnbc.com/2016/01/11/tech-giants-may-be-stronger-than-you-think.html", + "description": "Technology companies could soon rebound from the dip that China’s markets caused them as earnings season approaches, according to experts.", + "source": "cnbc.com", + "sourceDate": "2016-01-12T21:07:28.073309+00:00", + "tickers": ["googl", "aapl", "amzn", "msft", "nflx", "fb"], + "tags": ["Internet", "Investing", "Business", "Economic Reports", "Finance", "Economics", "Computing", "Asia", "Gdp", "Wireless", "China", "Technology", "Places", "Tiingo Top", "Information Technology", "Consumer Discretionary"], + "crawlDate": "2016-01-12T21:07:28.073309+00:00", + "id": 0 +}]'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['62'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:17:17 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/news_bulk.yaml b/tests/fixtures/news_bulk.yaml new file mode 100644 index 0000000..7f964a0 --- /dev/null +++ b/tests/fixtures/news_bulk.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/news/bulk_download/1 + response: + body: {string: '{"detail":"You do not have permission to access the News API"}'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['62'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:21:32 GMT'] + Server: [nginx/1.10.1] + Vary: [Cookie] + X-Frame-Options: [SAMEORIGIN] + status: {code: 403, message: Forbidden} +version: 1 diff --git a/tests/fixtures/news_bulk_file_ids.yaml b/tests/fixtures/news_bulk_file_ids.yaml new file mode 100644 index 0000000..6f324f9 --- /dev/null +++ b/tests/fixtures/news_bulk_file_ids.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/news/bulk_download + response: + body: {string: '{"detail":"You do not have permission to access the News API"}'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['62'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:21:33 GMT'] + Server: [nginx/1.10.1] + Vary: [Cookie] + X-Frame-Options: [SAMEORIGIN] + status: {code: 403, message: Forbidden} +version: 1 diff --git a/tests/fixtures/ticker_metadata.yaml b/tests/fixtures/ticker_metadata.yaml new file mode 100644 index 0000000..6db7477 --- /dev/null +++ b/tests/fixtures/ticker_metadata.yaml @@ -0,0 +1,36 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL + response: + body: {string: '{"endDate":"2017-10-06","startDate":"2004-08-19","exchangeCode":"NASDAQ","name":"Alphabet + Inc.(\"Google\") - Class A","description":"Google Inc. (Google) is a global + technology company. The Company''s business is primarily focused around key + areas, such as search, advertising, operating systems and platforms, enterprise + and hardware products. The Company generates revenue primarily by delivering + online advertising. The Company also generates revenues from Motorola by selling + hardware products. The Company provides its products and services in more + than 100 languages and in more than 50 countries, regions, and territories. + Effective May 16, 2014, Google Inc acquired Quest Visual Inc. Effective May + 20, 2014, Google Inc acquired Enterproid Inc, doing business as Divide. In + June 2014, Google Inc acquired mDialog Corp. Effective June 25, 2014, Google + Inc acquired Appurify Inc, a San Francisco-based developer of mobile bugging + application software.","ticker":"GOOGL"}'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['974'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:17:19 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/ticker_price.yaml b/tests/fixtures/ticker_price.yaml new file mode 100644 index 0000000..a69a2ff --- /dev/null +++ b/tests/fixtures/ticker_price.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=json&frequency=daily + response: + body: {string: '[{"adjClose":993.64,"adjHigh":994.26,"adjLow":978.51,"adjOpen":980.0,"adjVolume":1490744,"close":993.64,"date":"2017-10-06T00:00:00+00:00","divCash":0.0,"high":994.26,"low":978.51,"open":980.0,"splitFactor":1.0,"volume":1490744}]'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['229'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:17:18 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/ticker_price_with_date.yaml b/tests/fixtures/ticker_price_with_date.yaml new file mode 100644 index 0000000..0af3fef --- /dev/null +++ b/tests/fixtures/ticker_price_with_date.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=json&frequency=daily&startDate=2015-01-01&endDate=2015-01-05 + response: + body: {string: '[{"date":"2015-01-02T00:00:00.000Z","close":529.55,"high":535.8,"low":527.88,"open":532.6,"volume":1327870,"adjClose":529.55,"adjHigh":535.8,"adjLow":527.88,"adjOpen":532.6,"adjVolume":1327870,"divCash":0.0,"splitFactor":1.0},{"date":"2015-01-05T00:00:00.000Z","close":519.46,"high":527.9899,"low":517.75,"open":527.15,"volume":2059119,"adjClose":519.46,"adjHigh":527.9899,"adjLow":517.75,"adjOpen":527.15,"adjVolume":2059119,"divCash":0.0,"splitFactor":1.0}]'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['459'] + Content-Type: [application/json] + Date: ['Sun, 08 Oct 2017 10:17:25 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/ticker_price_with_date_csv.yaml b/tests/fixtures/ticker_price_with_date_csv.yaml new file mode 100644 index 0000000..b91d0a6 --- /dev/null +++ b/tests/fixtures/ticker_price_with_date_csv.yaml @@ -0,0 +1,30 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.3.2] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=csv&frequency=daily&startDate=2015-01-01&endDate=2015-01-05 + response: + body: {string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2015-01-02,529.55,535.8,527.88,532.6,1327870,529.55,535.8,527.88,532.6,1327870,0.0,1.0 + + 2015-01-05,519.46,527.9899,517.75,527.15,2059119,519.46,527.9899,517.75,527.15,2059119,0.0,1.0 + +'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['276'] + Content-Type: [text/csv] + Date: ['Sun, 08 Oct 2017 10:17:24 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/fixtures/valid_url.yaml b/tests/fixtures/valid_url.yaml new file mode 100644 index 0000000..ae1b21c --- /dev/null +++ b/tests/fixtures/valid_url.yaml @@ -0,0 +1,145 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + User-Agent: [python-requests/2.18.4] + method: GET + uri: http://www.google.com/ + response: + body: {string: "\n302 + Moved\n

302 Moved

\nThe document has moved\nhere.\r\n\r\n"} + headers: + Cache-Control: [private] + Content-Length: ['268'] + Content-Type: [text/html; charset=UTF-8] + Date: ['Sun, 08 Oct 2017 10:11:31 GMT'] + Location: ['http://www.google.nl/?gfe_rd=cr&dcr=0&ei=0_nZWYb9Fo2C4gS9_YigDw'] + Referrer-Policy: [no-referrer] + status: {code: 302, message: Found} +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + User-Agent: [python-requests/2.18.4] + method: GET + uri: http://www.google.nl/?gfe_rd=cr&dcr=0&ei=0_nZWYb9Fo2C4gS9_YigDw + response: + body: + string: !!binary | + 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 + X7OdudtWMAAA + headers: + Cache-Control: ['private, max-age=0'] + Content-Encoding: [gzip] + Content-Length: ['5367'] + Content-Type: [text/html; charset=ISO-8859-1] + Date: ['Sun, 08 Oct 2017 10:11:31 GMT'] + Expires: ['-1'] + P3P: [CP="This is not a P3P policy! See g.co/p3phelp for more info."] + Server: [gws] + Set-Cookie: ['1P_JAR=2017-10-08-10; expires=Sun, 15-Oct-2017 10:11:31 GMT; path=/; + domain=.google.nl', 'NID=113=TN5uytNu4s1c92yAaK_qNDYZd9fU0SIG6_1wuK-l-8dRT1vVtw9CHhD6OD_tZgGcJkdZwmFAfq5UZCg3oYdXKqePy8WOBqrLybJLNuACUouEGdJ0GSUBMpLBzMFgVUzm; + expires=Mon, 09-Apr-2018 10:11:31 GMT; path=/; domain=.google.nl; HttpOnly'] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/test_restclient.py b/tests/test_restclient.py index 1015ee0..247abd1 100644 --- a/tests/test_restclient.py +++ b/tests/test_restclient.py @@ -3,6 +3,9 @@ from unittest import TestCase + +import vcr + from tiingo.restclient import (RestClient, RestClientError) # Tests of basic REST API functionality @@ -25,12 +28,14 @@ class TestRestClient(TestCase): # Test valid page def test_valid_url(self): - response = self._client._request('GET', "") + with vcr.use_cassette('tests/fixtures/valid_url.yaml'): + response = self._client._request('GET', "") self.assertEqual(response.status_code, 200) # Test 404 error def test_invalid_url(self): - with self.assertRaisesRegexp(RestClientError, "404"): + with self.assertRaisesRegexp(RestClientError, "404"),\ + vcr.use_cassette('tests/fixtures/invalid_url.yaml'): # Should return 404 error self._client._request('GET', "bing_is_great") @@ -55,11 +60,13 @@ class TestRestClientWithSession(TestCase): # Test valid page def test_valid_url(self): - response = self._client._request('GET', "") + with vcr.use_cassette('tests/fixtures/valid_url.yaml'): + response = self._client._request('GET', "") self.assertEqual(response.status_code, 200) # Test 404 error def test_invalid_url(self): - with self.assertRaisesRegexp(RestClientError, "404"): + with self.assertRaisesRegexp(RestClientError, "404"),\ + vcr.use_cassette('tests/fixtures/invalid_url.yaml'): # Should return 404 error self._client._request('GET', "bing_is_great") diff --git a/tests/test_tiingo.py b/tests/test_tiingo.py index a7978d8..4a35af2 100644 --- a/tests/test_tiingo.py +++ b/tests/test_tiingo.py @@ -5,6 +5,9 @@ import csv from unittest import TestCase + +import vcr + from tiingo import TiingoClient from tiingo.restclient import RestClientError @@ -33,9 +36,12 @@ class TestTickerPrices(TestCase): def setUp(self): self._client = TiingoClient() # Stub all endpoints that get reused - self._ticker_price_response = self._client.get_ticker_price("GOOGL") - self._ticker_metadata_response = \ - self._client.get_ticker_metadata("GOOGL") + with vcr.use_cassette('tests/fixtures/ticker_price.yaml'): + self._ticker_price_response = \ + self._client.get_ticker_price("GOOGL") + with vcr.use_cassette('tests/fixtures/ticker_metadata.yaml'): + self._ticker_metadata_response = \ + self._client.get_ticker_metadata("GOOGL") def test_ticker_price(self): """Test the EOD Prices Endpoint""" @@ -44,17 +50,19 @@ class TestTickerPrices(TestCase): def test_ticker_price_with_date(self): """Test the EOD Prices Endpoint with data param""" - prices = self._client.get_ticker_price("GOOGL", - startDate="2015-01-01", - endDate="2015-01-05") + with vcr.use_cassette('tests/fixtures/ticker_price_with_date.yaml'): + prices = self._client.get_ticker_price("GOOGL", + startDate="2015-01-01", + endDate="2015-01-05") self.assertGreater(len(prices), 1) def test_ticker_price_with_csv(self): """Confirm that CSV endpoint works""" - prices_csv = self._client.get_ticker_price("GOOGL", - startDate="2015-01-01", - endDate="2015-01-05", - fmt='csv') + with vcr.use_cassette('tests/fixtures/ticker_price_with_date_csv.yaml'): + prices_csv = self._client.get_ticker_price("GOOGL", + startDate="2015-01-01", + endDate="2015-01-05", + fmt='csv') reader = csv.reader(prices_csv.splitlines(), delimiter=",") rows = list(reader) assert len(rows) > 2 # more than 1 day of data @@ -66,7 +74,8 @@ class TestTickerPrices(TestCase): def test_list_stock_tickers(self): """Update this test when the method is added.""" - tickers = self._client.list_stock_tickers() + with vcr.use_cassette('tests/fixtures/list_stock_tickers.yaml'): + tickers = self._client.list_stock_tickers() assert len(tickers) > 1 assert all(ticker['assetType'] == 'Stock' for ticker in tickers) @@ -90,7 +99,7 @@ class TestNews(TestCase): def test_get_news_articles(self): """Confirm that news article work""" - NUM_ARTICLES = 10 + NUM_ARTICLES = 1 search_params = { "tickers": ["aapl", "googl"], @@ -101,7 +110,8 @@ class TestNews(TestCase): "limit": NUM_ARTICLES } - articles = self._client.get_news(**search_params) + with vcr.use_cassette('tests/fixtures/news.yaml'): + articles = self._client.get_news(**search_params) assert len(articles) == NUM_ARTICLES for article in articles: assert all(key in article for key in self.article_keys) @@ -109,13 +119,15 @@ class TestNews(TestCase): def test_get_news_bulk(self): """Fails because this API key lacks institutional license""" - with self.assertRaises(RestClientError): + with self.assertRaises(RestClientError),\ + vcr.use_cassette('tests/fixtures/news_bulk.yaml'): value = self._client.get_bulk_news(file_id="1") assert value def test_get_news_bulk_ids(self): """Fails because this API key lacks institutional license""" - with self.assertRaises(RestClientError): + with self.assertRaises(RestClientError),\ + vcr.use_cassette('tests/fixtures/news_bulk_file_ids.yaml'): value = self._client.get_bulk_news() assert value