#9 TI-1: Add testsuite

- Simple test for each undoable interval command
- Refactored assertions
This commit is contained in:
Thomas Lauf 2018-07-23 22:15:01 +02:00
parent cd7755bc6c
commit 9d29a14d64
3 changed files with 418 additions and 29 deletions

View file

@ -2,7 +2,7 @@
import sys
import unittest
import datetime
class BaseTestCase(unittest.TestCase):
def tap(self, out):
@ -17,8 +17,8 @@ class TestCase(BaseTestCase):
expectedStart=None,
expectedTags=None,
description="interval"):
self.assertTrue("start" in interval, "{} does not contain a start date".format(description))
self.assertFalse("end" in interval, "{} does contain an end date".format(description))
self.assertKeyExists(interval, "start", description, "{} does not contain a start date")
self.assertKeyNotExists(interval, "end", description, "{} does contain an end date")
return self.assertInterval(interval,
expectedStart=expectedStart,
@ -31,8 +31,8 @@ class TestCase(BaseTestCase):
expectedEnd=None,
expectedTags=None,
description="interval"):
self.assertTrue("start" in interval, "{} does not contain a start date".format(description))
self.assertTrue("end" in interval, "{} does not contain an end date".format(description))
self.assertKeyExists(interval, "start", description, "{} does not contain a start date")
self.assertKeyExists(interval, "end", description, "{} does not contain an end date")
return self.assertInterval(interval,
expectedStart=expectedStart,
@ -46,29 +46,39 @@ class TestCase(BaseTestCase):
expectedTags=None,
description="interval"):
if expectedStart:
self.assertEqual(
interval["start"],
expectedStart,
"start time of {} does not match (expected: {}, actual: {})".format(description,
expectedStart,
interval["start"]))
self.assertIntervalTimestamp(interval, "start", expectedStart, description)
if expectedEnd:
self.assertEqual(
interval["end"],
expectedEnd,
"end time of {} does not match (expected: {}, actual: {})".format(description,
expectedEnd,
interval["end"]))
self.assertIntervalTimestamp(interval, "end", expectedEnd, description)
if expectedTags:
self.assertTrue("tags" in interval)
self.assertEqual(
interval["tags"],
expectedTags,
"tags of {} do not match (expected: {}, actual: {})". format(description,
expectedTags,
interval["tags"]))
self.assertKeyExists(interval, "tags", description, "{} does not contain tags")
self.assertIntervalValue(interval,
"tags",
expectedTags,
description,
"{} of {} do not match (expected: {}, actual: {})")
def assertKeyExists(self, interval, key, description, message):
self.assertTrue(key in interval, message.format(description))
def assertKeyNotExists(self, interval, key, description, message):
self.assertFalse(key in interval, message.format(description))
def assertIntervalTimestamp(self, interval, key, expected, description):
if isinstance(expected, datetime.datetime):
expected = "{:%Y%m%dT%H%M%SZ}".format(expected)
self.assertIntervalValue(interval,
key,
expected,
description,
"{} time of {} does not match (expected: {}, actual: {})")
def assertIntervalValue(self, interval, key, expected, description, message):
actual = interval[key]
self.assertEqual(actual,
expected,
message.format(key, description, expected, actual))
# vim: ai sts=4 et sw=4

View file

@ -92,12 +92,11 @@ class Timew(object):
return f.readlines()
def export(self, export_filter=None):
"""Run "task export", return JSON array of exported intervals."""
"""Run "timew export", return JSON array of exported intervals."""
if export_filter is None:
export_filter = ""
code, out, err = self.runSuccess("{0} export"
"".format(export_filter))
code, out, err = self.runSuccess("{0} export".format(export_filter))
return json.loads(out)
@ -112,8 +111,7 @@ class Timew(object):
return args
def runSuccess(self, args="", input=None, merge_streams=False,
timeout=5):
def runSuccess(self, args="", input=None, merge_streams=False, timeout=5):
"""Invoke timew with given arguments and fail if exit code != 0
Use runError if you want exit_code to be tested automatically and

View file

@ -43,6 +43,387 @@ class TestUndo(TestCase):
"""Executed before each test in the class"""
self.t = Timew()
def test_undo_cancel(self):
"""Test undo of command 'cancel'"""
one_hour_before_utc = datetime.now().utcnow() - timedelta(hours=1)
self.t("start {:%Y%m%dT%H%M%SZ} foo".format(one_hour_before_utc))
self.t("cancel")
j = self.t.export()
self.assertEqual(len(j), 0, msg="Expected 0 interval before, got {}".format(len(j)))
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertOpenInterval(j[0],
expectedStart=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_continue(self):
"""Test undo of command 'continue'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(two_hours_before_utc, one_hour_before_utc))
self.t("continue @1 {:%Y%m%dT%H%M%SZ}".format(now_utc))
j = self.t.export()
self.assertEqual(len(j), 2, msg="Expected 2 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
self.assertOpenInterval(j[1],
expectedStart=now_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_delete(self):
"""Test undo of command 'delete'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(two_hours_before_utc, one_hour_before_utc))
self.t("delete @1")
j = self.t.export()
self.assertEqual(len(j), 0, msg="Expected 0 intervals before, got {}".format(len(j)))
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
# def test_undo_fill(self):
# """Test undo of command 'fill 'Not yet implemented
# self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo bar")
# self.t("untag @1 bar")
#
# j = self.t.export()
# self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
# self.assertClosedInterval(j[0],
# expectedStart="20180101T060000",
# expectedEnd="20180101T070000",
# expectedTags=["foo"])
#
# self.t("undo")
#
# j = self.t.export()
# self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
# self.assertClosedInterval(j[0],
# expectedStart="20180101T060000",
# expectedEnd="20180101T070000",
# expectedTags=["foo bar"])
def test_undo_join(self):
"""Test undo of command 'join'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
four_hours_before_utc = now_utc - timedelta(hours=4)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} bar".format(four_hours_before_utc, three_hours_before_utc))
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(two_hours_before_utc, one_hour_before_utc))
self.t("join @1 @2")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=four_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["bar"],
description="joined interval")
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 2, msg="Expected 2 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=four_hours_before_utc,
expectedEnd=three_hours_before_utc,
expectedTags=["bar"],
description="first interval")
self.assertClosedInterval(j[1],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"],
description="second interval")
def test_undo_lengthen(self):
"""Test undo of command 'lengthen'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(three_hours_before_utc, two_hours_before_utc))
self.t("lengthen @1 1h")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=two_hours_before_utc,
expectedTags=["foo"])
def test_undo_move(self):
"""Test undo of command 'move'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(two_hours_before_utc, one_hour_before_utc))
self.t("move @1 {:%Y%m%dT%H%M%SZ}".format(three_hours_before_utc))
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=two_hours_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_resize(self):
"""Test undo of command 'resize'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(three_hours_before_utc, one_hour_before_utc))
self.t("resize @1 1h")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=two_hours_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_shorten(self):
"""Test undo of command 'shorten'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(three_hours_before_utc, one_hour_before_utc))
self.t("shorten @1 1h")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=two_hours_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_split(self):
"""Test undo of command 'split'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(three_hours_before_utc, one_hour_before_utc))
self.t("split @1")
j = self.t.export()
self.assertEqual(len(j), 2, msg="Expected 2 intervals before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=two_hours_before_utc,
expectedTags=["foo"])
self.assertClosedInterval(j[1],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=three_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_start(self):
"""Test undo of command 'start'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
self.t("start {:%Y%m%dT%H%M%SZ} foo".format(one_hour_before_utc))
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertOpenInterval(j[0],
expectedStart=one_hour_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 0, msg="Expected 1 interval afterwards, got {}".format(len(j)))
def test_undo_stop(self):
"""Test undo of command 'stop'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
self.t("start {:%Y%m%dT%H%M%SZ} foo".format(one_hour_before_utc))
self.t("stop {:%Y%m%dT%H%M%SZ}".format(now_utc))
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=one_hour_before_utc,
expectedEnd=now_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertOpenInterval(j[0],
expectedStart=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_tag(self):
"""Test undo of command 'tag'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(two_hours_before_utc, one_hour_before_utc))
self.t("tag @1 bar")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["bar", "foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
def test_undo_track(self):
"""Test undo of command 'track'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
three_hours_before_utc = now_utc - timedelta(hours=3)
four_hours_before_utc = now_utc - timedelta(hours=4)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo".format(four_hours_before_utc, three_hours_before_utc))
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} bar".format(two_hours_before_utc, one_hour_before_utc))
j = self.t.export()
self.assertEqual(len(j), 2, msg="Expected 2 intervals before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=four_hours_before_utc,
expectedEnd=three_hours_before_utc,
expectedTags=["foo"])
self.assertClosedInterval(j[1],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["bar"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=four_hours_before_utc,
expectedEnd=three_hours_before_utc,
expectedTags=["foo"])
def test_undo_untag(self):
"""Test undo of command 'untag'"""
now_utc = datetime.now().utcnow()
one_hour_before_utc = now_utc - timedelta(hours=1)
two_hours_before_utc = now_utc - timedelta(hours=2)
self.t("track {:%Y%m%dT%H%M%SZ} - {:%Y%m%dT%H%M%SZ} foo bar".format(two_hours_before_utc, one_hour_before_utc))
self.t("untag @1 bar")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval before, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["foo"])
self.t("undo")
j = self.t.export()
self.assertEqual(len(j), 1, msg="Expected 1 interval afterwards, got {}".format(len(j)))
self.assertClosedInterval(j[0],
expectedStart=two_hours_before_utc,
expectedEnd=one_hour_before_utc,
expectedTags=["bar", "foo"])
if __name__ == "__main__":
from simpletap import TAPTestRunner