From 8b5266b2999e4a18372c41c718044a44e089c525 Mon Sep 17 00:00:00 2001 From: Markus Holtermann Date: Sat, 26 Jan 2013 01:30:49 +0100 Subject: Finally fix the remaining seconds behaviour of ``bvggrabber.api.Departure`` and add appropriate test cases --- bvggrabber/api/__init__.py | 28 ++++--- tests/test_api.py | 182 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 157 insertions(+), 53 deletions(-) diff --git a/bvggrabber/api/__init__.py b/bvggrabber/api/__init__.py index 81c4980..c6ad86a 100644 --- a/bvggrabber/api/__init__.py +++ b/bvggrabber/api/__init__.py @@ -11,6 +11,15 @@ fullformat = lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S') hourformat = lambda dt: dt.strftime('%H:%M') +def compute_remaining(start, end): + if not isinstance(start, datetime.datetime): + raise ValueError("start needs to be a datetime.datetime") + if not isinstance(end, datetime.datetime): + raise ValueError("start needs to be a datetime.datetime") + seconds = (end - start).total_seconds() + return datetime.timedelta(minutes=floor(seconds / 60)).total_seconds() + + class QueryApi(object): def __init__(self): @@ -41,24 +50,19 @@ class Departure(object): elif isinstance(when, datetime.datetime): self.when = when else: - ValueError("when must be a valid datetime, timestamp or string!") + raise TypeError("when must be a valid datetime, timestamp or " + "string!") def __str__(self): return "Start: %s, End: %s, when: %s, now: %s, line: %s" % ( - self.start, self.end, hourformat(self.when), hourformat(self.now), - self.line) + self.start.decode('iso-8859-1'), self.end, hourformat(self.when), + hourformat(self.now), self.line) @property def remaining(self): - td = self.when - self.now - seconds = (td / 60).total_seconds() - if td < datetime.timedelta(seconds=0): - return datetime.timedelta(minutes=floor(seconds)) - elif td > datetime.timedelta(seconds=0): - return datetime.timedelta(minutes=ceil(seconds)) - else: - return datetime.timedelta(seconds=0) + return compute_remaining(self.now, self.when) + @property def to_json(self): return json.dumps({'start': self.start.decode('iso-8859-1'), 'end': self.end, @@ -67,4 +71,4 @@ class Departure(object): 'now_hour': hourformat(self.now), 'when_full': fullformat(self.when), 'when_hour': hourformat(self.when), - 'remaining': round(self.remaining.total_seconds())}) + 'remaining': round(self.remaining)}) diff --git a/tests/test_api.py b/tests/test_api.py index bd8e0ca..c4cd445 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,9 +1,46 @@ # -*- coding: utf-8 -*- -import unittest - import datetime +import json +import unittest -from bvggrabber.api import QueryApi, Departure, fullformat +from bvggrabber.api import QueryApi, Departure, fullformat, \ + compute_remaining + + +class TestFunctions(unittest.TestCase): + + def test_compute_remaining(self): + dates = [datetime.datetime(2013, 1, 2, 3, 4, 0), + datetime.datetime(2013, 1, 2, 3, 4, 1), + datetime.datetime(2013, 1, 2, 3, 4, 59), + datetime.datetime(2013, 1, 2, 3, 5, 0), + datetime.datetime(2013, 1, 2, 3, 5, 1), + datetime.datetime(2013, 1, 2, 3, 5, 59)] + + target = [[0, 0, 0, 60, 60, 60], + [-60, 0, 0, 0, 60, 60], + [-60, -60, 0, 0, 0, 60], + [-60, -60, -60, 0, 0, 0], + [-120, -60, -60, -60, 0, 0], + [-120, -120, -60, -60, -60, 0]] + for start in range(len(dates)): + for end in range(len(dates)): + s = dates[start] + e = dates[end] + t = target[start][end] + self.assertEqual(compute_remaining(s, e), + target[start][end], + "Start: %s; End: %s; target: %d" % ( + fullformat(s), fullformat(e), t)) + + def test_compute_remaining_error(self): + self.assertRaises(ValueError, compute_remaining, 1357092240, + datetime.datetime(2013, 1, 2, 3, 4, 1)) + self.assertRaises(ValueError, compute_remaining, + datetime.datetime(2013, 1, 2, 3, 4, 0), 1357092241) + self.assertRaises(ValueError, compute_remaining, + datetime.datetime(2013, 1, 2, 3, 4, 0), + datetime.datetime(2013, 1, 2, 3, 4, 1)) class TestQueryApi(unittest.TestCase): @@ -13,96 +50,159 @@ class TestQueryApi(unittest.TestCase): self.assertRaises(NotImplementedError, q.call) -class TestDeparture(unittest.TestCase): +class BaseTestDeparture(unittest.TestCase): def setUp(self): self.since = datetime.datetime(2013, 1, 2, 3, 4, 0) - self.delta1 = datetime.timedelta(seconds=60) + self.delta1 = datetime.timedelta(seconds=45) self.delta2 = datetime.timedelta(seconds=80) + self.delta3 = datetime.timedelta(seconds=150) + + +class TestDepartureTimestamp(BaseTestDeparture): + + def setUp(self): + super(TestDepartureTimestamp, self).setUp() + self.sincets = 1357092240 + self.delta1 = self.delta1.total_seconds() + self.delta2 = self.delta2.total_seconds() + self.delta3 = self.delta3.total_seconds() def test_timestamp_futur(self): - when = self.since + self.delta1 + when = self.sincets + self.delta1 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 60) + self.assertEqual(dep.remaining, 0) - when = self.since + self.delta2 + when = self.sincets + self.delta2 + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, 60) + + when = self.sincets + self.delta3 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 120) + self.assertEqual(dep.remaining, 120) def test_timestamp_now(self): - when = self.since + when = self.sincets dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 0) + self.assertEqual(dep.remaining, 0) def test_timestamp_past(self): - when = self.since - self.delta1 + when = self.sincets - self.delta1 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -60) + self.assertEqual(dep.remaining, -60) - when = self.since - self.delta2 + when = self.sincets - self.delta2 + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, -120) + + when = self.sincets - self.delta3 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -120) + self.assertEqual(dep.remaining, -180) + + +class TestDepartureString(BaseTestDeparture): def test_string_futur(self): when = fullformat(self.since + self.delta1) dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 60) + self.assertEqual(dep.remaining, 0) when = fullformat(self.since + self.delta2) dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 120) + self.assertEqual(dep.remaining, 60) + + when = fullformat(self.since + self.delta3) + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, 120) def test_string_now(self): when = fullformat(self.since) dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 0) + self.assertEqual(dep.remaining, 0) def test_string_past(self): when = fullformat(self.since - self.delta1) dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -60) + self.assertEqual(dep.remaining, -60) when = fullformat(self.since - self.delta2) dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -120) + self.assertEqual(dep.remaining, -120) + + when = fullformat(self.since - self.delta3) + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, -180) + + +class TestDepartureDatetime(BaseTestDeparture): def test_datetime_futur(self): when = self.since + self.delta1 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 60) + self.assertEqual(dep.remaining, 0) when = self.since + self.delta2 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 120) + self.assertEqual(dep.remaining, 60) + + when = self.since + self.delta3 + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, 120) def test_datetime_now(self): when = self.since dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, 0) + self.assertEqual(dep.remaining, 0) def test_datetime_past(self): when = self.since - self.delta1 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -60) + self.assertEqual(dep.remaining, -60) when = self.since - self.delta2 dep = Departure("from", "to", when, "line", since=self.since) - diff = dep.remaining.total_seconds() - self.assertEqual(diff, -120) + self.assertEqual(dep.remaining, -120) + + when = self.since - self.delta3 + dep = Departure("from", "to", when, "line", since=self.since) + self.assertEqual(dep.remaining, -180) + + +class TestDeparture(BaseTestDeparture): def test_error(self): - self.assertRaises(ValueError, Departure, "from", "to", "foo", "line") + self.assertRaises(ValueError, Departure, "from", "to", "when", "line") + self.assertRaises(TypeError, Departure, "from", "to", ["when"], "line") + self.assertIsInstance(Departure("from", "to", "16:15\n \t*", "line"), + Departure) + + def test_json(self): + json1 = {'start': "From My Station", + 'end': "To Your Station", + 'line': "A Line", + 'now_full': "2013-01-02 03:04:00", + 'now_hour': "03:04", + 'when_full': "2013-01-02 03:04:45", + 'when_hour': "03:04", + 'remaining': 0} + dep1 = Departure(b"From My Station", "To Your Station", + self.since + self.delta1, "A Line", since=self.since) + self.assertEqual(json1, json.loads(dep1.to_json)) + str1 = "Start: From My Station, End: To Your Station, when: 03:04, " \ + "now: 03:04, line: A Line" + self.assertEqual(str1, str(dep1)) + + json2 = {'start': "From My Station", + 'end': "To Your Station", + 'line': "A Line", + 'now_full': "2013-01-02 03:04:00", + 'now_hour': "03:04", + 'when_full': "2013-01-02 03:05:20", + 'when_hour': "03:05", + 'remaining': 60} + dep2 = Departure(b"From My Station", "To Your Station", + self.since + self.delta2, "A Line", since=self.since) + self.assertEqual(json2, json.loads(dep2.to_json)) + str2 = "Start: From My Station, End: To Your Station, when: 03:05, " \ + "now: 03:04, line: A Line" + self.assertEqual(str2, str(dep2)) -- cgit v1.2.3