Skip to content

Commit a95926a

Browse files
committed
Initial tests. using mocked response objects. and 2 more
remove pdb move exceptions to separate import namespace s
1 parent c11d1da commit a95926a

10 files changed

Lines changed: 156 additions & 16 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
*.DS_Store
33
*~
44
docs/_build
5+
*.egg-info

‎fitbit/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
:copyright: (c) 2012 by Issac Kelly.
77
:license: BSD, see LICENSE for more details.
88
"""
9-
from .exceptions import BadResponse
9+
1010
from .api import Fitbit, FitbitConsumer, FitbitOauthClient
1111

1212
# Meta.

‎fitbit/api.py‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import urlparse
55
import json
66
import datetime
7-
import pdb #REMOVE!
87
import urllib
98

109
from fitbit.exceptions import (BadResponse, DeleteError, HTTPBadRequest,
@@ -137,20 +136,20 @@ class Fitbit(object):
137136
'frequent',
138137
]
139138

140-
def __init__(self, system=US, *kwargs):
141-
self.client = FitbitOauthClient(*kwargs)
139+
def __init__(self, system=US, **kwargs):
140+
self.client = FitbitOauthClient(**kwargs)
142141
self.SYSTEM = system
143142

144143
# All of these use the same patterns, define the method for accessing
145144
# creating and deleting records once, and use curry to make individual
146145
# Methods for each
147146
for resource in self._resource_list:
148-
setattr(self, resource, curry(self._COLLECTION_RESOURCE,
149-
resource=resource))
147+
setattr(self, resource, curry(self._COLLECTION_RESOURCE, resource))
150148

151149
if resource not in ['body', 'glucose']:
152150
# Body and Glucose entries are not currently able to be deleted
153-
setattr(self, 'delete_%s' % resource, curry(self._DELETE_COLLECTION_RESOURCE, resource=resource))
151+
setattr(self, 'delete_%s' % resource, curry(
152+
self._DELETE_COLLECTION_RESOURCE, resource))
154153

155154
for qualifier in self._qualifiers:
156155
setattr(self, '%s_activities' % qualifier, curry(self.activity_stats, qualifier=qualifier))
@@ -163,18 +162,23 @@ def make_request(self, *args, **kwargs):
163162
headers = kwargs.get('headers', {})
164163
headers.update({'Accept-Language': self.SYSTEM})
165164
kwargs['headers'] = headers
165+
166+
method = kwargs.get('method', 'GET')
166167
response = self.client.make_request(*args, **kwargs)
167-
if response.status_code in [202, 204]:
168+
169+
170+
if response.status_code == 202:
168171
return True
172+
if method == 'DELETE':
173+
if response.status_code == 204:
174+
return True
175+
else:
176+
raise DeleteError(response)
169177
try:
170178
rep = json.loads(response.content)
171179
except ValueError:
172-
if self.DEBUG:
173-
pdb.set_trace()
174180
raise BadResponse
175181

176-
if rep.get('errors', None) and self.DEBUG:
177-
pdb.set_trace()
178182
return rep
179183

180184
def user_profile(self, user_id=None, data=None):
@@ -271,8 +275,6 @@ def _DELETE_COLLECTION_RESOURCE(self, resource, log_id):
271275
log_id,
272276
)
273277
response = self.make_request(url, method='DELETE')
274-
if response.status_code != 204:
275-
raise DeleteError(response)
276278
return response
277279

278280
def time_series(self, resource, user_id=None, base_date='today',

‎fitbit/exceptions.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ class DeleteError(Exception):
1414

1515
class HTTPException(Exception):
1616
def __init__(self, response, *args, **kwargs):
17-
import pdb
18-
pdb.set_trace()
1917
super(HTTPException, self).__init__(*args, **kwargs)
2018

2119
class HTTPBadRequest(HTTPException):

‎requirements-test.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mock==0.8.0

‎requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
## We're using the best maintained fork of python-oauth2
12
https://github.com/dgouldin/python-oauth2/tarball/master
23
requests
34
python-dateutil==1.5

‎setup.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
include_package_data=True,
2525
install_requires=required,
2626
license='Apache 2.0',
27+
test_suite='tests.all_tests',
2728
classifiers=(
2829
'Intended Audience :: Developers',
2930
'Natural Language :: English',

‎tests/__init__.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import unittest
2+
from test_exceptions import ExceptionTest
3+
4+
5+
def all_tests(consumer_key="", consumer_secret="", user_key=None, user_secret=None):
6+
kwargs = {
7+
"consumer_key": consumer_key,
8+
"consumer_secret": consumer_secret,
9+
"user_key": user_key,
10+
"user_secret": user_secret,
11+
}
12+
suite = unittest.TestSuite()
13+
suite.addTest(unittest.makeSuite(ExceptionTest))
14+
return suite

‎tests/base.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import unittest
2+
3+
class APITestCase(unittest.TestCase):
4+
5+
6+
def __init__(self, consumer_key="", consumer_secret="", client_key=None, client_secret=None, *args, **kwargs):
7+
self.consumer_key = consumer_key
8+
self.consumer_secret = consumer_secret
9+
self.client_key = client_key
10+
self.client_secret = client_secret
11+
12+
self.client_kwargs = {
13+
"consumer_key": consumer_key,
14+
"consumer_secret": consumer_secret,
15+
"client_key": client_key,
16+
"client_secret": client_secret,
17+
}
18+
super(APITestCase, self).__init__(*args, **kwargs)

‎tests/test_exceptions.py‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import unittest
2+
import mock
3+
import requests
4+
from fitbit import Fitbit
5+
from fitbit import exceptions
6+
7+
class ExceptionTest(unittest.TestCase):
8+
"""
9+
Tests that certain response codes raise certain exceptions
10+
"""
11+
client_kwargs = {
12+
"consumer_key": "",
13+
"consumer_secret": "",
14+
"user_key": None,
15+
"user_secret": None,
16+
}
17+
18+
19+
def test_response_ok(self):
20+
"""
21+
This mocks a pretty normal resource, that the request was authenticated,
22+
and data was returned. This test should just run and not raise any
23+
exceptions
24+
"""
25+
r = mock.Mock(spec=requests.Response)
26+
r.status_code = 200
27+
r.content = '{"normal": "resource"}'
28+
29+
f = Fitbit(**self.client_kwargs)
30+
f.client._request = lambda *args, **kwargs: r
31+
f.user_profile()
32+
33+
r.status_code = 202
34+
f.user_profile()
35+
36+
r.status_code = 204
37+
f.user_profile()
38+
39+
40+
def test_response_auth(self):
41+
"""
42+
This test checks how the client handles different auth responses, and
43+
the exceptions raised by the client.
44+
"""
45+
r = mock.Mock(spec=requests.Response)
46+
r.status_code = 401
47+
r.content = "{'normal': 'resource'}"
48+
49+
f = Fitbit(**self.client_kwargs)
50+
f.client._request = lambda *args, **kwargs: r
51+
52+
self.assertRaises(exceptions.HTTPUnauthorized, f.user_profile)
53+
54+
r.status_code = 403
55+
self.assertRaises(exceptions.HTTPForbidden, f.user_profile)
56+
57+
58+
def test_response_error(self):
59+
"""
60+
Tests other HTTP errors
61+
"""
62+
r = mock.Mock(spec=requests.Response)
63+
r.content = "{'normal': 'resource'}"
64+
65+
f = Fitbit(**self.client_kwargs)
66+
f.client._request = lambda *args, **kwargs: r
67+
68+
r.status_code = 404
69+
self.assertRaises(exceptions.HTTPNotFound, f.user_profile)
70+
71+
r.status_code = 409
72+
self.assertRaises(exceptions.HTTPConflict, f.user_profile)
73+
74+
r.status_code = 500
75+
self.assertRaises(exceptions.HTTPServerError, f.user_profile)
76+
77+
r.status_code = 499
78+
self.assertRaises(exceptions.HTTPBadRequest, f.user_profile)
79+
80+
81+
def test_serialization(self):
82+
"""
83+
Tests non-json data returned
84+
"""
85+
r = mock.Mock(spec=requests.Response)
86+
r.status_code = 200
87+
r.content = "iyam not jason"
88+
89+
f = Fitbit(**self.client_kwargs)
90+
f.client._request = lambda *args, **kwargs: r
91+
self.assertRaises(exceptions.BadResponse, f.user_profile)
92+
93+
def test_delete_error(self):
94+
"""
95+
Delete requests should return 204
96+
"""
97+
r = mock.Mock(spec=requests.Response)
98+
r.status_code = 201
99+
r.content = '{"it\'s all": "ok"}'
100+
101+
f = Fitbit(**self.client_kwargs)
102+
f.client._request = lambda *args, **kwargs: r
103+
self.assertRaises(exceptions.DeleteError, f.delete_activities, 12345)
104+

0 commit comments

Comments
 (0)