From a00cfd3d1c28c7978e178ce4ebb73af3949646cb Mon Sep 17 00:00:00 2001 From: Margaret Sy Date: Sat, 19 Dec 2015 13:44:28 -0800 Subject: [PATCH 1/3] add basic tests for ISS-pass and error handling when no passes found --- iss.py | 15 ++++++--------- testsuite/api.py | 31 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/iss.py b/iss.py index 044b370..62aaa12 100644 --- a/iss.py +++ b/iss.py @@ -43,30 +43,29 @@ def get_tle_update(): def get_passes(lon, lat, alt, n): - """Compute n number of passes of the ISS for a location""" - + """Compute up to n number of passes of the ISS for a location""" # Get latest TLE from redis tle = json.loads(r.get("iss_tle")) iss = ephem.readtle(str(tle[0]), str(tle[1]), str(tle[2])) - # Set location location = ephem.Observer() location.lat = str(lat) location.long = str(lon) location.elevation = alt - # Override refration calculation location.pressure = 0 location.horizon = '10:00' - # Set time now now = datetime.datetime.utcnow() location.date = now - # Predict passes passes = [] for p in xrange(n): - tr, azr, tt, altt, ts, azs = location.next_pass(iss) + try: + tr, azr, tt, altt, ts, azs = location.next_pass(iss) + except ValueError as e: + # next_pass returns "that satellite seems to stay always below your horizon" + continue duration = int((ts - tr) * 60 * 60 * 24) year, month, day, hour, minute, second = tr.tuple() dt = datetime.datetime(year, month, day, hour, minute, int(second)) @@ -76,7 +75,6 @@ def get_passes(lon, lat, alt, n): # Increase the time by more than a pass and less than an orbit location.date = tr + 25*ephem.minute - # Return object obj = {"request": { "datetime": timegm(now.timetuple()), @@ -87,5 +85,4 @@ def get_passes(lon, lat, alt, n): }, "response": passes, } - return obj diff --git a/testsuite/api.py b/testsuite/api.py index 7c5de08..de4ec85 100644 --- a/testsuite/api.py +++ b/testsuite/api.py @@ -3,6 +3,35 @@ import json from app import app +class IssPassTest(TestCase): + """Test ISS-pass API""" + def setUp(self): + self.app = app + self.w = TestApp(self.app) + self.endpoint = '/iss-pass.json' + + def format_uri(self, lat, lon): + return self.endpoint + '?lat={0}&lon={1}'.format(lat, lon) + + def test_berkeley(self): + berkeley = self.format_uri(37.8715926, -122.27274699999998) + r = self.w.get(berkeley) + r.charset = 'utf8' + data = json.loads(r.text) + self.assertEqual(r.status_code, 200) + + def test_no_passes_found(self): + mcmurdo_station = self.format_uri(-77.8418779, 166.6863449) + r = self.w.get(mcmurdo_station) + self.assertEqual(r.status_code, 200) + data = r.json + self.assertEqual(len(data['response']), 0) + + def test_bad_lat(self): + bad_lat = self.format_uri(-91, 50) + r = self.w.get(bad_lat, expect_errors=True) + self.assertEqual(r.status_code, 400) + class IssNowTest(TestCase): """Test the ISS-now API""" @@ -26,7 +55,7 @@ def test_data(self): try: data = json.loads(r.text) except: - self.fail("ISS API not a valid JSON responce") + self.fail("ISS API not a valid JSON response") # Success message self.assertEqual(data['message'], "success", "ISS API Did not return 'sucess' message") From 0233e23e8dcf4fec252cd9463d3acbbbf7e3230e Mon Sep 17 00:00:00 2001 From: Margaret Sy Date: Mon, 21 Dec 2015 17:56:24 -0800 Subject: [PATCH 2/3] refactor iss_pass error handling --- app.py | 67 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/app.py b/app.py index e0f40e8..bc00501 100644 --- a/app.py +++ b/app.py @@ -74,39 +74,40 @@ def tle_info(): @jsonp @json def iss_pass(): - - # Sanitize inputs - lat = request.args.get('lat', False) - if lat: - lat = safe_float(lat, (-90.0, 90.0)) - if not lat: - return {"message": "failure", "reason": "Latitude must be number between -90.0 and 90.0"}, 400 - else: - return {"message": "failure", "reason": "Latitude must be specified"}, 400 - - lon = request.args.get('lon', False) - if lon: - lon = safe_float(lon, (-180.0, 180.0)) - if not lon: - return {"message": "failure", "reason": "Longitue must be number between -180.0 and 180.0"}, 400 - else: - return {"message": "failure", "reason": "Longitude must be specified"}, 400 - - alt = request.args.get('alt', False) - if alt: - alt = safe_float(alt, (0, 10000)) - if not alt: - return {"message": "failure", "reason": "Altitude must be number between 0 and 10,000"}, 400 - else: - alt = 100 - - n = request.args.get('n', False) - if n: - n = safe_float(n, (1, 100)) - if not n: - return {"message": "failure", "reason": "Number of passes must be number between 1 and 100"}, 400 - else: - n = 5 + try: + # Sanitize inputs + lat = request.args.get('lat', False) + if lat: + lat = safe_float(lat, (-90.0, 90.0)) + if not lat: + raise ValueError("Latitude must be number between -90.0 and 90.0") + else: + raise ValueError("Latitude must be specified.") + lon = request.args.get('lon', False) + if lon: + lon = safe_float(lon, (-180.0, 180.0)) + if not lon: + ValueError("Longitude must be number between -180.0 and 180.0") + else: + raise ValueError("Longitude must be specified.") + alt = request.args.get('alt', False) + if alt: + alt = safe_float(alt, (0, 10000)) + if not alt: + raise ValueError("Altitude must be number between 0 and 10,000") + else: + alt = 100 + + n = request.args.get('n', False) + if n: + n = safe_float(n, (1, 100)) + if not n: + raise ValueError("Number of passes must be number between 1 and 100") + else: + n = 5 + except ValueError as e: + error_response = {"message": "failure", "reason": e.message, "request": request.args} + return error_response, 400 # Calculate data and return d = iss.get_passes(lon, lat, alt, int(n)) From d15059a7d0dce071ad1f863f16c5ac99f0dfda8d Mon Sep 17 00:00:00 2001 From: Margaret Sy Date: Mon, 21 Dec 2015 18:06:44 -0800 Subject: [PATCH 3/3] break instead of continue in get_passes failure --- iss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iss.py b/iss.py index 62aaa12..c5ce8b8 100644 --- a/iss.py +++ b/iss.py @@ -65,7 +65,7 @@ def get_passes(lon, lat, alt, n): tr, azr, tt, altt, ts, azs = location.next_pass(iss) except ValueError as e: # next_pass returns "that satellite seems to stay always below your horizon" - continue + break duration = int((ts - tr) * 60 * 60 * 24) year, month, day, hour, minute, second = tr.tuple() dt = datetime.datetime(year, month, day, hour, minute, int(second))