22# -*- coding: utf-8 -*-
33
44import pytest
5+ from collections import OrderedDict
56from uszipcode .searchengine import Zipcode , ZipcodeSearchEngine
67from uszipcode .packages .haversine import great_circle
78
@@ -11,17 +12,19 @@ def is_all_ascending(array):
1112 """
1213 for i , j in zip (array [1 :], array [:- 1 ]):
1314 if (i is not None ) and (j is not None ):
14- assert i - j >= 0
15+ assert i >= j
16+
1517
1618def is_all_descending (array ):
1719 """Assert that this is a strictly desceding array.
1820 """
1921 for i , j in zip (array [1 :], array [:- 1 ]):
2022 if (i is not None ) and (j is not None ):
21- assert i - j <= 0
23+ assert i <= j
2224
2325
2426class TestZipcode (object ):
27+
2528 def test_init (self ):
2629 z = Zipcode (Zipcode = "10001" )
2730 assert z .Zipcode == "10001"
@@ -69,6 +72,7 @@ def test_output(self):
6972
7073
7174class TestZipcodeSearchEngine (object ):
75+
7276 def test_sql_create_order_by (self ):
7377 with ZipcodeSearchEngine () as search :
7478 sql = search ._sql_create_order_by ("Zipcode" , True )
@@ -94,17 +98,18 @@ def test_sql_create_lower_upper(self):
9498 with pytest .raises (ValueError ):
9599 sql = search ._sql_create_lower_upper ("Population" , None , None )
96100 with pytest .raises (ValueError ):
97- sql = search ._sql_create_lower_upper ("Population" , "SQL" , "SQL" )
98-
101+ sql = search ._sql_create_lower_upper (
102+ "Population" , "SQL" , "SQL" )
103+
99104 sql = search ._sql_create_lower_upper ("Population" , 0 , None )
100105 assert sql == "Population >= 0"
101-
106+
102107 sql = search ._sql_create_lower_upper ("Population" , None , 999999 )
103108 assert sql == "Population <= 999999"
104-
109+
105110 sql = search ._sql_create_lower_upper ("Population" , 0 , 999999 )
106111 assert sql == "Population >= 0 AND Population <= 999999"
107-
112+
108113 def test_search_by_zipcode (self ):
109114 with ZipcodeSearchEngine () as search :
110115 for zipcode in [10001 , "10001" ]:
@@ -120,50 +125,59 @@ def test_search_by_coordinate(self):
120125 with ZipcodeSearchEngine () as search :
121126 # 在马里兰选一个坐标, 返回1000条, 但实际上不到1000条
122127 lat , lng = 39.114407 , - 77.205758
123-
128+
124129 # 返回的结果必须按照距离是从小到大的
125130 res1 = search .by_coordinate (lat , lng , ascending = True , returns = 1000 )
126131 len (res1 ) < 1000
127- dist_array = [great_circle ((lat , lng ), (z .Latitude , z .Longitude ), miles = True ) for z in res1 ]
132+ dist_array = [
133+ great_circle ((lat , lng ), (z .Latitude , z .Longitude ), miles = True ) for z in res1 ]
128134 is_all_ascending (dist_array )
129-
130- res2 = search .by_coordinate (lat , lng , ascending = False , returns = 1000 )
131- dist_array = [great_circle ((lat , lng ), (z .Latitude , z .Longitude ), miles = True ) for z in res2 ]
135+
136+ res2 = search .by_coordinate (
137+ lat , lng , ascending = False , returns = 1000 )
138+ dist_array = [
139+ great_circle ((lat , lng ), (z .Latitude , z .Longitude ), miles = True ) for z in res2 ]
132140 is_all_descending (dist_array )
133-
141+
134142 # 当returns = 0时, 返回所有符合条件的
135143 res3 = search .by_coordinate (lat , lng , returns = 0 )
136144 assert len (res1 ) == len (res3 )
137145
138146 # 当没有符合条件的zipcode时, 返回空列表
139147 res3 = search .by_coordinate (lat , lng , radius = - 1 )
140148 assert len (res3 ) == 0
141-
149+
142150 def test_find_state (self ):
143151 with ZipcodeSearchEngine () as search :
144152 assert search ._find_state ("mary" , best_match = True ) == ["MD" , ]
145-
153+
146154 result = set (search ._find_state ("virgin" , best_match = False ))
147155 assert result == set (["VI" , "WV" , "VA" ])
148-
156+
149157 assert search ._find_state ("newyork" , best_match = False ) == ["NY" , ]
150-
158+
151159 with pytest .raises (ValueError ):
152160 search ._find_state ("THIS IS NOT A STATE!" , best_match = True )
153-
161+
154162 with pytest .raises (ValueError ):
155163 search ._find_state ("THIS IS NOT A STATE!" , best_match = False )
156-
164+
157165 def test_find_city (self ):
158166 with ZipcodeSearchEngine () as search :
159- assert search ._find_city ("phonix" , best_match = True ) == [
160- "Phoenix" , ]
161- assert search ._find_city ("kerson" , best_match = False ) == [
162- "Dickerson Run" , "Dickerson" , "Nickerson" , "Emerson" , "Everson"
163- ]
164- assert search ._find_city ("kersen" , state = "kensas" , best_match = False ) == [
165- "Nickerson" , ]
166-
167+ city_result = search ._find_city ("phonix" , best_match = True )
168+ city_expected = ["Phoenix" , ]
169+ assert city_result == city_expected
170+
171+ city_result = search ._find_city ("kerson" , best_match = False )
172+ city_result .sort ()
173+ city_expected = ["Dickerson" , "Dickerson Run" , "Emerson" , "Ericson" , "Everson" , "Nickerson" ]
174+ for city in city_result :
175+ assert city in city_expected
176+
177+ city_result = search ._find_city ("kersen" , state = "kensas" , best_match = False )
178+ city_expected = ["Nickerson" , ]
179+ assert city_result == city_expected
180+
167181 def test_by_city_and_state (self ):
168182 with ZipcodeSearchEngine () as search :
169183 # Arlington, VA
@@ -172,11 +186,11 @@ def test_by_city_and_state(self):
172186 z .City == "Arlington"
173187 z .State == "VA"
174188 assert len (res ) == 5
175-
189+
176190 # There's no city in VI
177191 with pytest .raises (ValueError ):
178192 search .by_city_and_state (city = "Arlington" , state = "vi" )
179-
193+
180194 def test_by_city (self ):
181195 with ZipcodeSearchEngine () as search :
182196 res = search .by_city ("vienna" )
@@ -185,7 +199,7 @@ def test_by_city(self):
185199 assert z .City == "Vienna"
186200 s .add (z .State )
187201 assert s == set (["ME" , "MD" , "VA" ])
188-
202+
189203 def test_by_state (self ):
190204 with ZipcodeSearchEngine () as search :
191205 res = search .by_state ("RI" )
@@ -204,7 +218,7 @@ def test_by_prefix(self):
204218 sort_by = sort_key , ascending = True , returns = 0 )
205219 l = list ()
206220 for z in res :
207- assert z .Zipcode .startswith (prefix ) # example prefix
221+ assert z .Zipcode .startswith (prefix ) # example prefix
208222 l .append (z [sort_key ])
209223 l_sorted = list (l )
210224 l_sorted .sort ()
@@ -253,16 +267,33 @@ def test_by_house(self):
253267 res = search .by_house (lower = 20000 ,
254268 sort_by = "HouseOfUnits" , ascending = False , returns = 0 )
255269 assert len (res ) == 741
256-
257- def test_find (self ):
270+
271+ def test_sort_by_multiple_keywords (self ):
272+ with ZipcodeSearchEngine () as search :
273+ res = search .by_state (
274+ state = "CA" , sort_by = ["City" , "Zipcode" ], ascending = [True , True ], returns = 1000 )
275+
276+ stat = OrderedDict ()
277+ for zipcode in res :
278+ try :
279+ stat [zipcode .City ].append (zipcode .Zipcode )
280+ except :
281+ stat [zipcode .City ] = [zipcode .Zipcode , ]
282+
283+ city_list = list (stat .keys ())
284+ is_all_ascending (city_list )
285+ for zipcode_list in stat .values ():
286+ is_all_ascending (list (zipcode_list ))
287+
288+ def test_find (self ):
258289 with ZipcodeSearchEngine () as search :
259290 # Find most people living zipcode in New York
260291 res = search .find (
261292 city = "new york" ,
262293 sort_by = "Population" , ascending = False ,
263294 )
264295 is_all_descending ([z .Population for z in res ])
265-
296+
266297 # Find all zipcode in California that prefix is "999"
267298 res = search .find (
268299 state = "califor" ,
@@ -275,28 +306,29 @@ def test_find(self):
275306 assert z .State == "CA"
276307 assert z .Zipcode .startswith ("95" )
277308 is_all_descending ([z .HouseOfUnits for z in res ])
278-
309+
279310 # Find top 10 richest zipcode near Silicon Valley
280311 lat , lng = 37.391184 , - 122.082235
281312 radius = 100
282313 res = search .find (
283- lat = lat ,
314+ lat = lat ,
284315 lng = lng ,
285316 radius = radius ,
286317 sort_by = "Wealthy" , ascending = False ,
287318 returns = 10 ,
288319 )
289320 assert len (res ) == 10
290321 for z in res :
291- assert great_circle ((lat , lng ), (z .Latitude , z .Longitude )) <= radius
322+ assert great_circle (
323+ (lat , lng ), (z .Latitude , z .Longitude )) <= radius
292324 is_all_descending ([z .Wealthy for z in res ])
293-
294- # Find zipcode that average personal annual income greater than
295- # 100000 near Silicon Valley, order by distance
325+
326+ # Find zipcode that average personal annual income greater than
327+ # 100000 near Silicon Valley, order by distance
296328 lat , lng = 37.391184 , - 122.082235
297329 radius = 100
298330 res = search .find (
299- lat = lat ,
331+ lat = lat ,
300332 lng = lng ,
301333 radius = radius ,
302334 wealthy_lower = 60000 ,
@@ -309,7 +341,7 @@ def test_find(self):
309341 is_all_ascending ([
310342 great_circle ((lat , lng ), (z .Latitude , z .Longitude )) for z in res
311343 ])
312-
344+
313345 def test_edge_case (self ):
314346 with ZipcodeSearchEngine () as search :
315347 zipcode = search .by_zipcode (00000 )
0 commit comments