class PerformanceTest(object): def __init__(self, number_of_requests=10000): self.number_of_requests = number_of_requests self.client = Client(MY_OAUTH_KEY, MY_OAUTH_SECRET, API_VERSION, API_HOST, API_PORT) print self.client self.responses = [] def run(self): requests_completed = 0 requests_failed = 0 for i in range(self.number_of_requests): try: print 'Trying request %s' % i timed_response = self._timed_response() requests_completed += 1 self.responses.append(timed_response) except APIError: requests_failed += 1 print self.responses print '%s requests completed, %s requests failed' % (requests_completed, requests_failed) times = [response['time_elapsed'] for response in self.responses] print '\n\nmin: %s max: %s avg: %s\n\n' % (min(times), max(times), (sum(times) / len(times))) bins = [i * 0.1 for i in range(20)] + [2.0] + [10.0] histogram = numpy.histogram(times, bins=bins) frequencies = [frequency for frequency in histogram[0]] bins = [bin for bin in histogram[1]] for (i, bin) in enumerate(bins): print '%ss' % bin try: print '\t' + str(frequencies[i]) + '\t' + '=' * frequencies[i] except: pass def _timed_response(self): (lat, lon) = self._random_lat_lon() print 'Timing client.get_context(%s, %s)' % (lat, lon) start_time = time.time() response = self.client.get_context(lat, lon) time_elapsed = time.time() - start_time print time_elapsed return {'lat': lat, 'lon': lon, 'response': response, 'time_elapsed': time_elapsed} def _random_lat_lon(self): return (random.uniform(-90.0, 90.0), random.uniform(-180.0, 180.0))
class ClientTest(unittest.TestCase): def setUp(self): self.client = Client(MY_OAUTH_KEY, MY_OAUTH_SECRET, API_VERSION, API_HOST, API_PORT) self.query_lat = D('37.8016') self.query_lon = D('-122.4783') def _record(self): self.record_id += 1 self.record_lat = (self.record_lat + 10) % 90 self.record_lon = (self.record_lon + 10) % 180 return Feature( layer=TESTING_LAYER, id=str(self.record_id), coordinates=(self.record_lat, self.record_lon) ) def test_wrong_endpoint(self): self.assertRaises(Exception, self.client._endpoint, 'wrongwrong') def test_missing_argument(self): self.assertRaises(Exception, self.client._endpoint, 'context') def test_get_context(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp res = self.client.get_context(self.query_lat, self.query_lon) self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/%s,%s.json' % (API_VERSION, self.query_lat, self.query_lon)) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET') # the code under test is required to have json-decoded this before handing it back self.failUnless(isinstance(res, dict), (type(res), repr(res))) @mock.patch('oauth2.Request.make_timestamp') @mock.patch('oauth2.Request.make_nonce') def test_oauth(self, mock_make_nonce, mock_make_timestamp): mock_make_nonce.return_value = 5 mock_make_timestamp.return_value = 6 mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp self.client.get_context(self.query_lat, self.query_lon) self.assertEqual(mockhttp.method_calls[0][2]['body'], None) self.assertEqual(mockhttp.method_calls[0][2]['headers']['Authorization'], 'OAuth realm="http://api.simplegeo.com", oauth_nonce="5", oauth_timestamp="6", oauth_consumer_key="MY_OAUTH_KEY", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="AObXFB%2BqjwC20j5guAprkiREfIg%3D"') def test_get_context_by_address(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp addr = '41 Decatur St, San Francisco, CA' self.client.get_context_by_address(addr) self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/address.json?address=%s' % (API_VERSION, urllib.quote_plus(addr))) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET') def test_get_context_by_my_ip(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp self.client.get_context_by_my_ip() self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/ip.json' % (API_VERSION,)) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET') def test_get_context_by_ip(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp ipaddr = '192.0.32.10' self.client.get_context_by_ip(ipaddr=ipaddr) self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/%s.json' % (API_VERSION, ipaddr)) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET') def test_get_context_by_ip_invalid(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp self.failUnlessRaises(AssertionError, self.client.get_context_by_ip, '40.1,127.999') def test_get_context_invalid(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY) self.client.http = mockhttp self.failUnlessRaises(AssertionError, self.client.get_context, -91, 100) self.failUnlessRaises(AssertionError, self.client.get_context, -11, 361) def test_get_context_no_body(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, None) self.client.http = mockhttp self.failUnlessRaises(DecodeError, self.client.get_context, self.query_lat, self.query_lon) self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/%s,%s.json' % (API_VERSION, self.query_lat, self.query_lon)) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET') def test_get_context_bad_json(self): mockhttp = mock.Mock() mockhttp.request.return_value = ({'status': '200', 'content-type': 'application/json', }, EXAMPLE_BODY + 'some crap') self.client.http = mockhttp try: self.client.get_context(self.query_lat, self.query_lon) except DecodeError, e: self.failUnlessEqual(e.code,None,repr(e.code)) self.failUnless("Could not decode" in e.msg, repr(e.msg)) repr(e) self.assertEqual(mockhttp.method_calls[0][0], 'request') self.assertEqual(mockhttp.method_calls[0][1][0], 'http://api.simplegeo.com:80/%s/context/%s,%s.json' % (API_VERSION, self.query_lat, self.query_lon)) self.assertEqual(mockhttp.method_calls[0][1][1], 'GET')
class ConsumptionTest(unittest.TestCase): def setUp(self): self.client = Client(MY_OAUTH_KEY, MY_OAUTH_SECRET, API_VERSION, API_HOST, API_PORT) self.known_points = { 'darrell_k_royal_stadium': { 'lat': 30.283863, 'lon': -97.732519, 'expected_response': EXPECTED_RESPONSES['darrell_k_royal_stadium'] }, 'att_park': { 'lat': 37.778434, 'lon': -122.389146, 'expected_response': EXPECTED_RESPONSES['att_park'] }, 'invesco_field': { 'lat': 39.744026, 'lon': -105.019893, 'expected_response': EXPECTED_RESPONSES['invesco_field'] } } # Request known points. self.known_requests = [] for (point_name, point) in self.known_points.iteritems(): point['name'] = point_name response = self.client.get_context(point['lat'], point['lon']) self.known_points[point_name]['response'] = response self.known_requests.append((point, response)) # Request random points. self.random_requests = [] for i in range(10): (lat, lon) = random_lat_lon() point = {'lat': lat, 'lon': lon} response = self.client.get_context(lat, lon) self.random_requests.append((point, response)) def test_weather(self): # Invesco Field should have the weather data. point = self.known_points['invesco_field'] response = point['response'] self.assertTrue('weather' in response, 'Weather not contained in response for point %s,%s' % (point['lat'], point['lon'])) self.assertTrue('temperature' in response['weather'], 'Temperature not found in weather in response for point %s,%s' % (point['lat'], point['lon'])) self.assertEqual(response['weather']['temperature'][-1:], 'F', 'Temperature value %s does not end in F in response for %s,%s' % (response['weather']['temperature'], point['lat'], point['lon'])) def test_demographics(self): # Invesco Field should have the demographic data. point = self.known_points['invesco_field'] response = point['response'] self.assertTrue('demographics' in response, 'Demographics not found in response for point %s,%s' % (point['lat'], point['lon'])) self.assertTrue('metro_score' in response['demographics'], 'metro_score not found in demographics section for point %s,%s' % (point['lat'], point['lon'])) self.assertTrue(0 <= int(response['demographics']['metro_score']) <= 10, 'Invalid value "%s" for metro_score in response for point %s,%s' % (response['demographics']['metro_score'], point['lat'], point['lon'])) def test_expected_features_are_received(self): # Test that all features expected are received for (point, response) in self.known_requests: for expected_feature in point['expected_response']['features']: found_expected_feature = False for received_feature in response['features']: if expected_feature == received_feature: found_expected_feature = True self.assertTrue(found_expected_feature, 'Could not find expected feature in response for point %s,%s:\n%s' % (point['lat'], point['lon'], expected_feature)) def test_received_features_are_expected(self): # Test that all features received are expected for (point, response) in self.known_requests: for received_feature in response['features']: found_received_feature = False for expected_feature in point['expected_response']['features']: if received_feature == expected_feature: found_received_feature = True self.assertTrue(found_received_feature, 'Could not find received feature in response for point %s,%s:\n%s' % (point['lat'], point['lon'], received_feature)) def test_duplicate_handles(self): # Tests random requests and known requests. for (point, response) in self.known_requests + self.random_requests: for (i, feature) in enumerate(response['features']): for (j, possible_duplicate_feature) in enumerate(response['features']): if i != j: self.assertNotEqual(feature['handle'], possible_duplicate_feature['handle'], 'Found duplicate handle %s for point %s,%s' % (feature['handle'], point['lat'], point['lon'])) # Test for dupes in the first 25 characters of the self.assertNotEqual(feature['handle'][:25], possible_duplicate_feature['handle'][:25], 'Found duplicate *base* handle %s for point %s,%s' % (feature['handle'][:25], point['lat'], point['lon'])) def test_duplicate_categories(self): # Ensure that we don't have multiple features with specified type/category/subcategory configurations. dupe_classifiers = [{'type': 'Region', 'category': 'Subnational', 'subcategory': 'State'}, {'type': 'Region', 'category': 'Time Zone', 'subcategory': ''}, {'type': 'Region', 'category': 'National', 'subcategory': ''}, {'type': 'Region', 'category': 'Urban Area', 'subcategory': ''}, {'type': 'Region', 'category': 'US Census', 'subcategory': 'Tract'}, {'type': 'Region', 'category': 'Neighborhood', 'subcategory': ''}, {'type': 'Region', 'category': 'Administrative', 'subcategory': 'County'}, {'type': 'Region', 'category': 'Municiple', 'subcategory': 'City'}, {'type': 'Region', 'category': 'School District', 'subcategory': 'Unified'}] for (point, response) in self.known_requests: for dupe_classifier in dupe_classifiers: instances_found = 0 for feature in response['features']: for classifier in feature['classifiers']: if 'type' in classifier and 'category' in classifier and 'subcategory' in classifier: if dupe_classifier['type'] == classifier['type'] and dupe_classifier['category'] == classifier['category'] and dupe_classifier['subcategory'] == classifier['subcategory']: instances_found += 1 self.assertTrue(instances_found <= 1, 'Found dupe for type/categories %s/%s/%s for point %s,%s' % (dupe['type'], dupe['category'], dupe['subcategory'], point['lat'], point['lon']))