diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d977e32
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# ignore test artifacts
+/tmp
diff --git a/test/helper b/test/helper
new file mode 100644
index 0000000..4ef4631
--- /dev/null
+++ b/test/helper
@@ -0,0 +1,6 @@
+# Shared test setup goes here...
+
+# Mock this out so the harness can be demonstrated
+core_init_defines () {
+ true
+}
diff --git a/test/suite b/test/suite
new file mode 100755
index 0000000..d06a85e
--- /dev/null
+++ b/test/suite
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+#
+# Run like:
+#
+# ./test/suite
+#
+# To run individual tests, run the test file:
+#
+# ./test/variable/variable.test.functions
+#
+# Use `-v` to see stderr on failing tests. Use the test name to run just one test.
+#
+# ./test/variable/variable.test.functions -v test_core_variable_startsWith
+#
+
+find . -type f -name '*.test.*' |
+grep -v -E '(helper|suite)' |
+xargs ts "$@"
diff --git a/variable/variable.test.functions b/variable/variable.test.functions
new file mode 100755
index 0000000..035e23b
--- /dev/null
+++ b/variable/variable.test.functions
@@ -0,0 +1,63 @@
+#!/bin/bash
+. test/helper
+. variable/variable.functions
+
+setup () {
+ true # replace as needed
+}
+
+teardown () {
+ true # replace as needed
+}
+
+#
+# Example testing with assert_status - good for multipart tests because
+# you can add a comment and go off of various exit statuses
+#
+
+test_core_variable_startsWith () {
+ core_variable_startsWith "/etc/path/to/file" "/home/"
+ assert_status 1 $? "variable does not start with prefix"
+
+ core_variable_startsWith "/etc/path/to/file" "/etc/"
+ assert_status 0 $? "variable does start with prefix"
+}
+
+#
+# Examples testing with assert_output - simply makes sure stdout is the same.
+# Stderr is not checked but you can of course use redirections. Not good for
+# multipart testing (see the docs, it's because of the pipelines) but in
+# truth I use these more than I use assert_status.
+#
+
+test_core_variable_firstCharacter()
+{
+ core_variable_firstCharacter "abc" | assert_output "a"
+}
+
+test_core_variable_lastCharacter()
+{
+ core_variable_lastCharacter "abc" | assert_output "c"
+}
+
+#
+# The other useful thing ts provides is $ts_test_dir - the path to a test-
+# specific directory where you can make files, nearby where some ts-related
+# files are placed in `./tmp`. The files are left after tests complete so you
+# can inspect them, but cleaned up prior to each run. I don't see a function
+# in this module that could use it rationally, but to illustrate...
+#
+
+test_core_variable_trimWhitespace () {
+ mkdir -p "$ts_test_dir"
+ file_with_whitespace="$ts_test_dir/file"
+ cat > "$file_with_whitespace" <