[california/wip/725792-quick-add: 2/5] Test harness and tests for Component.DetailsParser



commit 96c19cf2de5f7c521faff830003fb5741bb3a3e2
Author: Jim Nelson <jim yorba org>
Date:   Tue Apr 22 15:58:22 2014 -0700

    Test harness and tests for Component.DetailsParser

 src/Makefile.am                      |    5 +
 src/application/main.vala            |    2 +-
 src/tests/tests-quick-add.vala       |  136 ++++++++++++++++++++++++++++++++
 src/tests/tests.vala                 |   16 ++++
 src/unit-test/unit-test-harness.vala |  143 ++++++++++++++++++++++++++++++++++
 5 files changed, 301 insertions(+), 1 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 65d5e0e..57105f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -98,6 +98,9 @@ california_VALASOURCES = \
        manager/manager-calendar-list-item.vala \
        manager/manager-window.vala \
        \
+       tests/tests.vala \
+       tests/tests-quick-add.vala \
+       \
        toolkit/toolkit.vala \
        toolkit/toolkit-calendar-popup.vala \
        toolkit/toolkit-card.vala \
@@ -113,6 +116,8 @@ california_VALASOURCES = \
        util/util-string.vala \
        util/util-uri.vala \
        \
+       unit-test/unit-test-harness.vala \
+       \
        view/view.vala \
        view/view-controllable.vala \
        \
diff --git a/src/application/main.vala b/src/application/main.vala
index 1211e0a..61e5a77 100644
--- a/src/application/main.vala
+++ b/src/application/main.vala
@@ -5,6 +5,6 @@
  */
 
 int main(string[] args) {
-    return California.Application.instance.run(args);
+    return args[1] != "--tests" ? California.Application.instance.run(args) : California.Tests.run(args);
 }
 
diff --git a/src/tests/tests-quick-add.vala b/src/tests/tests-quick-add.vala
new file mode 100644
index 0000000..065e4a6
--- /dev/null
+++ b/src/tests/tests-quick-add.vala
@@ -0,0 +1,136 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+namespace California.Tests {
+
+private class QuickAdd : UnitTest.Harness {
+    public QuickAdd() {
+        add_case("summary", summary);
+        add_case("summary-location", summary_location);
+        add_case("with-12hr-time", with_12hr_time);
+        add_case("with-24hr-time", with_24hr_time);
+        add_case("with-day-of-week", with_day_of_week);
+        add_case("with-delay", with_delay);
+        add_case("with-duration", with_duration);
+        add_case("with-delay-and-duration", with_delay_and_duration);
+        add_case("indeterminate-time", indeterminate_time);
+        add_case("dialog-example", dialog_example);
+    }
+    
+    protected override void setup() throws Error {
+        Component.init();
+        Calendar.init();
+    }
+    
+    protected override void teardown() {
+        Component.terminate();
+        Calendar.terminate();
+    }
+    
+    private bool summary() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet with Alice");
+        
+        return parser.event.summary == "meet with Alice"
+            && parser.event.location == null
+            && parser.event.exact_time_span == null
+            && parser.event.date_span == null;
+    }
+    
+    private bool summary_location() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet with Alice at Bob's");
+        
+        return parser.event.summary == "meet with Alice at Bob's"
+            && parser.event.location == "Bob's"
+            && parser.event.exact_time_span == null
+            && parser.event.date_span == null;
+    }
+    
+    private bool with_12hr_time() throws Error {
+        return with_time(new Component.DetailsParser("dinner at 7pm with Alice"));
+    }
+    
+    private bool with_24hr_time() throws Error {
+        return with_time(new Component.DetailsParser("dinner at 1900 with Alice"));
+    }
+    
+    private bool with_time(Component.DetailsParser parser) {
+        Calendar.ExactTime time = new Calendar.ExactTime(
+            Calendar.System.timezone,
+            Calendar.System.today,
+            new Calendar.WallTime(19, 0, 0)
+        );
+        
+        return parser.event.summary == "dinner with Alice"
+            && parser.event.location == null
+            && parser.event.exact_time_span.start_exact_time.equal_to(time)
+            && parser.event.exact_time_span.end_exact_time.equal_to(time.adjust_time(1, 
Calendar.TimeUnit.HOUR));
+    }
+    
+    private bool with_day_of_week() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("dinner Monday at Bob's with Alice");
+        
+        return parser.event.summary == "dinner at Bob's with Alice"
+            && parser.event.location == "Bob's with Alice"
+            && parser.event.date_span.start_date.day_of_week == Calendar.DayOfWeek.MON;
+    }
+    
+    private bool with_delay() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet Alice in 3 hours");
+        
+        Calendar.ExactTime time = Calendar.System.now.adjust_time(3, Calendar.TimeUnit.HOUR);
+        
+        return parser.event.summary == "meet Alice"
+            && parser.event.exact_time_span.start_exact_time.equal_to(time)
+            && parser.event.exact_time_span.end_exact_time.equal_to(time.adjust_time(3, 
Calendar.TimeUnit.HOUR));
+    }
+    
+    private bool with_duration() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet Alice for 2 hrs");
+        
+        Calendar.ExactTime time = Calendar.System.now.adjust_time(2, Calendar.TimeUnit.HOUR);
+        
+        return parser.event.summary == "meet Alice"
+            && parser.event.exact_time_span.start_exact_time.equal_to(Calendar.System.now)
+            && parser.event.exact_time_span.end_exact_time.equal_to(time);
+    }
+    
+    private bool with_delay_and_duration() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet Alice in 3 hours for 30 min");
+        
+        Calendar.ExactTime time = Calendar.System.now.adjust_time(3, Calendar.TimeUnit.HOUR);
+        
+        return parser.event.summary == "meet Alice"
+            && parser.event.exact_time_span.start_exact_time.equal_to(time)
+            && parser.event.exact_time_span.end_exact_time.equal_to(time.adjust_time(30, 
Calendar.TimeUnit.MINUTE));
+    }
+    
+    private bool indeterminate_time() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser("meet Alice 4");
+        
+        return parser.event.summary == "meet Alice 4"
+            && parser.event.exact_time_span == null
+            && parser.event.date_span == null;
+    }
+    
+    private bool dialog_example() throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser(
+            "Dinner at Tadich Grill 7:30pm tomorrow");
+        
+        Calendar.ExactTime time = new Calendar.ExactTime(
+            Calendar.System.timezone,
+            Calendar.System.today.next(),
+            new Calendar.WallTime(19, 30, 0)
+        );
+        
+        return parser.event.summary == "Dinner at Tadich Grill"
+            && parser.event.location == "Tadich Grill"
+            && parser.event.exact_time_span.start_exact_time.equal_to(time)
+            && parser.event.exact_time_span.end_exact_time.equal_to(time.adjust_time(1, 
Calendar.TimeUnit.HOUR));
+    }
+}
+
+}
+
diff --git a/src/tests/tests.vala b/src/tests/tests.vala
new file mode 100644
index 0000000..327609f
--- /dev/null
+++ b/src/tests/tests.vala
@@ -0,0 +1,16 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+namespace California.Tests {
+
+public int run(string[] args) {
+    UnitTest.Harness.register(new QuickAdd());
+    
+    return UnitTest.Harness.exec_all();
+}
+
+}
+
diff --git a/src/unit-test/unit-test-harness.vala b/src/unit-test/unit-test-harness.vala
new file mode 100644
index 0000000..249aae9
--- /dev/null
+++ b/src/unit-test/unit-test-harness.vala
@@ -0,0 +1,143 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+namespace California.UnitTest {
+
+/**
+ * Base class for suites of related tests.
+ */
+
+public abstract class Harness : BaseObject {
+    public delegate bool Case() throws Error;
+    
+    private class TestCase : BaseObject {
+        public string name;
+        public unowned Case unit_test;
+        
+        public TestCase(string name, Case unit_test) {
+            this.name = name;
+            this.unit_test = unit_test;
+        }
+        
+        public override string to_string() {
+            return name;
+        }
+    }
+    
+    private static Gee.ArrayList<Harness>? harnesses = null;
+    
+    /**
+     * Name of the { link Harness}.
+     */
+    public string name { get; private set; }
+    
+    private Gee.ArrayList<TestCase> test_cases = new Gee.ArrayList<TestCase>();
+    
+    protected Harness(string? name = null) {
+        this.name = name ?? get_class().get_type().name();
+    }
+    
+    /**
+     * Register a { link Harness} to the total list of Harneses.
+     */
+    public static void register(Harness harness) {
+        if (harnesses == null)
+            harnesses = new Gee.ArrayList<Harness>();
+        
+        harnesses.add(harness);
+    }
+    
+    /**
+     * Execute all { link register}ed { link Harness}es.
+     */
+    public static int exec_all() {
+        if (harnesses == null || harnesses.size == 0)
+            return 0;
+        
+        foreach (Harness harness in harnesses) {
+            try {
+                harness.setup();
+            } catch (Error err) {
+                stdout.printf("Unable to setup harness %s: %s", harness.name, err.message);
+                Posix.exit(Posix.EXIT_FAILURE);
+            }
+            
+            harness.exec();
+            harness.teardown();
+        }
+        
+        return 0;
+    }
+    
+    /**
+     * Executed before running any test cases.
+     */
+    protected abstract void setup() throws Error;
+    
+    /**
+     * Executed after all test cases have completed.
+     */
+    protected abstract void teardown();
+    
+    /**
+     * Executed prior to each test case.
+     */
+    protected virtual void prepare() throws Error {
+    }
+    
+    /**
+     * Executed after each test case.
+     */
+    protected virtual void cleanup() {
+    }
+    
+    /**
+     * Add a test case to the { link Harness}.
+     */
+    protected void add_case(string name, Case unit_test) {
+        test_cases.add(new TestCase(name, unit_test));
+    }
+    
+    private void exec() {
+        foreach (TestCase test_case in test_cases) {
+            stdout.printf("Executing test: %s.%s...", name, test_case.name);
+            
+            try {
+                prepare();
+            } catch (Error err) {
+                stdout.printf("prepare failed: %s\n", err.message);
+                Posix.exit(Posix.EXIT_FAILURE);
+            }
+            
+            bool success = false;
+            Error? err = null;
+            try {
+                success = test_case.unit_test();
+            } catch (Error caught) {
+                err = caught;
+            }
+            
+            if (err != null)
+                stdout.printf("\nFailed: %s.%s\n\t%s\n", name, test_case.name, err.message);
+            else if (!success)
+                stdout.printf("\nFailed: %s.%s\n", name, test_case.name);
+            
+            if (err != null || !success)
+                Posix.exit(Posix.EXIT_FAILURE);
+            
+            cleanup();
+            
+            stdout.printf("success\n");
+        }
+    }
+    
+    public override string to_string() {
+        return name;
+    }
+}
+
+}
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]