From 16a510366872bc960a15b84c2cb723bae639e726 Mon Sep 17 00:00:00 2001 From: Emil Sit Date: Sat, 11 Apr 2009 09:49:11 -0400 Subject: [PATCH 1/4] tests: Make test writing simpler and add two new tests. Add a test_todo_session function to test-lib.sh that enables easy recording of input and output from todo.sh (including annotation of exit status for testing error cases). Begin to port and re-factor testsuite.txt into smaller test cases, starting with basic add list functionality and replace functionality. Thanks to Philippe Teuwen for feedback and improvements. Signed-off-by: Emil Sit --- tests/t1000-addlist.sh | 58 ++++++++++++++++++++++++++++++++++ tests/t1100-replace.sh | 71 ++++++++++++++++++++++++++++++++++++++++++ tests/test-lib.sh | 54 ++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100755 tests/t1000-addlist.sh create mode 100755 tests/t1100-replace.sh diff --git a/tests/t1000-addlist.sh b/tests/t1000-addlist.sh new file mode 100755 index 0000000..123a1f8 --- /dev/null +++ b/tests/t1000-addlist.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +test_description='basic add and list functionality + +This test just makes sure the basic add and list +command work, including support for filtering. +' +. ./test-lib.sh + +# +# Add and list +# +test_todo_session 'basic add/list' <>> todo.sh add notice the daisies +TODO: 'notice the daisies' added on line 1. + +>>> todo.sh list +1 notice the daisies +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh add smell the roses +TODO: 'smell the roses' added on line 2. + +>>> todo.sh list +1 notice the daisies +2 smell the roses +-- +TODO: 2 of 2 tasks shown from $HOME/todo.txt +EOF + +# +# Filter +# +test_todo_session 'basic list filtering' <>> todo.sh list daisies +1 notice the daisies +-- +TODO: 1 of 2 tasks shown from $HOME/todo.txt + +>>> todo.sh list smell +2 smell the roses +-- +TODO: 1 of 2 tasks shown from $HOME/todo.txt +EOF + +test_todo_session 'case-insensitive filtering' <>> todo.sh add smell the uppercase Roses +TODO: 'smell the uppercase Roses' added on line 3. + +>>> todo.sh list roses +2 smell the roses +3 smell the uppercase Roses +-- +TODO: 2 of 3 tasks shown from $HOME/todo.txt +EOF + +test_done diff --git a/tests/t1100-replace.sh b/tests/t1100-replace.sh new file mode 100755 index 0000000..d198bd7 --- /dev/null +++ b/tests/t1100-replace.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='basic replace functionality + +Ensure we can replace items successfully. +' +. ./test-lib.sh + +# +# Set up the basic todo.txt +# +todo.sh add notice the daisies > /dev/null + +test_todo_session 'replace usage' <>> todo.sh replace adf asdfa +=== 1 +usage: $(which todo.sh) replace ITEM# "UPDATED ITEM" +EOF + +test_todo_session 'basic replace' <>> todo.sh replace 1 "smell the cows" +1: notice the daisies +replaced with +1: smell the cows + +>>> todo.sh list +1 smell the cows +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh replace 1 smell the roses +1: smell the cows +replaced with +1: smell the roses + +>>> todo.sh list +1 smell the roses +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt +EOF + +cat > todo.txt <>> todo.sh replace 1 smell the cheese +1: smell the cows +replaced with +1: smell the cheese + +>>> todo.sh replace 3 jump on hay +3: thrash some hay +replaced with +3: jump on hay + +>>> todo.sh replace 4 collect the eggs +4: chase the chickens +replaced with +4: collect the eggs +EOF + +test_todo_session 'replace error' << EOF +>>> todo.sh replace 10 "hej!" +=== 1 +10: No such todo. +EOF + +test_done diff --git a/tests/test-lib.sh b/tests/test-lib.sh index 086d12c..300f1e5 100644 --- a/tests/test-lib.sh +++ b/tests/test-lib.sh @@ -434,6 +434,60 @@ test_init_todo () { cd "$owd" } +# Generate and run a series of tests based on a transcript. +# Usage: test_todo_session "description" <>> command +# output1 +# output2 +# >>> command +# === exit status +# output3 +# output4 +# EOF +test_todo_session () { + test "$#" = 1 || + error "bug in the test script: extra args to test_todo_session" + subnum=0 + cmd="" + status=0 + > expect + while read line + do + case $line in + ">>> "*) + test -z "$cmd" || error "bug in the test script: missing blank line separator in test_todo_session" + cmd=${line#>>> } + ;; + "=== "*) + status=${line#=== } + ;; + "") + if [ ! -z "$cmd" ]; then + if [ $status = 0 ]; then + test_expect_success "$1 $subnum" "$cmd > output && test_cmp expect output" + else + test_expect_success "$1 $subnum" "$cmd > output || test $? = $status && test_cmp expect output" + fi + + subnum=$(($subnum + 1)) + cmd="" + status=0 + > expect + fi + ;; + *) + echo $line >> expect + ;; + esac + done + if [ ! -z "$cmd" ]; then + if [ $status = 0 ]; then + test_expect_success "$1 $subnum" "$cmd > output && test_cmp expect output" + else + test_expect_success "$1 $subnum" "$cmd > output || test $? = $status && test_cmp expect output" + fi + fi +} test_init_todo "$test" # Use -P to resolve symlinks in our working directory so that the cwd From b238a29430f0cf45b3af5dfef30329b497d3a399 Mon Sep 17 00:00:00 2001 From: Emil Sit Date: Sat, 11 Apr 2009 21:48:40 -0400 Subject: [PATCH 2/4] tests: Explicitly control the date for todo.sh. Create a custom date view for todo.sh tests -- the time is set in TODO_TEST_TIME as seconds since the Unix epoch and a custom wrapper in the testing directory is put at the front of the path to intercept todo.sh calls to date for date formatting. This will only work as long as todo.sh calls $(date) for date formatting. It also assumes a date command that supports the -d flag (such as the one in GNU coreutils.) Add a test for TODOTXT_DATE_ON_ADD to exercise this functionality. Signed-off-by: Emil Sit --- tests/t1010-add-date.sh | 69 +++++++++++++++++++++++++++++++++++++++++ tests/test-lib.sh | 28 +++++++++++++++-- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100755 tests/t1010-add-date.sh diff --git a/tests/t1010-add-date.sh b/tests/t1010-add-date.sh new file mode 100755 index 0000000..910ba51 --- /dev/null +++ b/tests/t1010-add-date.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='test the date on add feature + +Tests paths by which we might automatically add +a date to each item. +' +. ./test-lib.sh + +# +# Add and list +# +test_todo_session 'cmd line first day' <>> todo.sh -t add notice the daisies +TODO: '2009-02-13 notice the daisies' added on line 1. + +>>> todo.sh list +1 2009-02-13 notice the daisies +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt +EOF + +test_tick + +test_todo_session 'cmd line second day' <>> todo.sh -t add smell the roses +TODO: '2009-02-14 smell the roses' added on line 2. + +>>> todo.sh list +1 2009-02-13 notice the daisies +2 2009-02-14 smell the roses +-- +TODO: 2 of 2 tasks shown from $HOME/todo.txt +EOF + +test_tick + +test_todo_session 'cmd line third day' <>> todo.sh -t add mow the lawn +TODO: '2009-02-15 mow the lawn' added on line 3. + +>>> todo.sh list +1 2009-02-13 notice the daisies +2 2009-02-14 smell the roses +3 2009-02-15 mow the lawn +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt +EOF + +# Switch to config file +echo "export TODOTXT_DATE_ON_ADD=1" >> todo.cfg + +# Bump the clock, for good measure. +test_tick 3600 + +test_todo_session 'config file third day' <>> todo.sh add take out the trash +TODO: '2009-02-15 take out the trash' added on line 4. + +>>> todo.sh list +1 2009-02-13 notice the daisies +2 2009-02-14 smell the roses +3 2009-02-15 mow the lawn +4 2009-02-15 take out the trash +-- +TODO: 4 of 4 tasks shown from $HOME/todo.txt +EOF + +test_done diff --git a/tests/test-lib.sh b/tests/test-lib.sh index 300f1e5..3767c9e 100644 --- a/tests/test-lib.sh +++ b/tests/test-lib.sh @@ -407,9 +407,8 @@ test_done () { esac } -# Make sure we are testing the latest version. +# Record our location for reference. TEST_DIRECTORY=$(pwd) -PATH=$TEST_DIRECTORY/..:$PATH # Test repository test="trash directory.$(basename "$0" .sh)" @@ -431,9 +430,34 @@ test_init_todo () { cd "$root" || error "Cannot setup todo dir in $root" # Initialize the configuration file. Carefully quoted. sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' $TEST_DIRECTORY/../todo.cfg > todo.cfg + + # Install latest todo.sh + mkdir bin + ln -s "$TEST_DIRECTORY/../todo.sh" bin/todo.sh + + # Initialize a hack date script + TODO_TEST_REAL_DATE=$(which date) + TODO_TEST_TIME=1234500000 + export PATH TODO_TEST_REAL_DATE TODO_TEST_TIME + cat > bin/date <<-EOF + #!/bin/sh + # Assumes GNU date. + exec "$TODO_TEST_REAL_DATE" -d @\$TODO_TEST_TIME \$@ + EOF + chmod 755 bin/date + + # Ensure a correct PATH for testing. + PATH=$owd/$root/bin:$PATH + export PATH + cd "$owd" } +# Usage: test_tick [increment] +test_tick () { + TODO_TEST_TIME=$(($TODO_TEST_TIME + ${1:-86400})) +} + # Generate and run a series of tests based on a transcript. # Usage: test_todo_session "description" <>> command From d6c57e42301f4c314441a274db7bb73d2a715c6a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 8 Apr 2009 01:19:16 +0200 Subject: [PATCH 3/4] tests: add testshell.sh and port old testsuite.txt Add a simple helper script testshell.sh that can be called to set up an environment for generating test case transcripts that can then be pasted into an actual test script. Port old testsuite.txt into t9999-testsuite_example.sh with the aim of refactoring it later into smaller tests. Also, change test_todo_session to count from one instead of zero when autogenerating tests. Signed-off-by: Emil Sit --- tests/README_generate-test | 15 ++ tests/t9999-testsuite_example.sh | 312 +++++++++++++++++++++++++++++++ tests/test-lib.sh | 14 +- tests/testshell.sh | 6 + 4 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 tests/README_generate-test create mode 100755 tests/t9999-testsuite_example.sh create mode 100755 tests/testshell.sh diff --git a/tests/README_generate-test b/tests/README_generate-test new file mode 100644 index 0000000..55acfbe --- /dev/null +++ b/tests/README_generate-test @@ -0,0 +1,15 @@ +You can generate test scripts from screenshots as following: + +$ ./testshell.sh + +You'll be in a special test environment with an empty todo.txt +and the dates and timestamps will be artificially fixed. + +Then the session can be used to make a unit test thanks to test_todo_session, +see the existing tests as examples. + +Be careful to replace all occurences of the full path to the test directory +by $HOME as testshell.sh will explain you when you execute it otherwise the +tests will work properly only on your own computer. + +Don't use "script" as this would log every keystroke, not only what's visible!! diff --git a/tests/t9999-testsuite_example.sh b/tests/t9999-testsuite_example.sh new file mode 100755 index 0000000..c36c4ad --- /dev/null +++ b/tests/t9999-testsuite_example.sh @@ -0,0 +1,312 @@ +#!/bin/sh + +test_description='basic tests imported from previous framework +' +. ./test-lib.sh + +test_todo_session 'basic tests' <>> todo.sh add "notice the daisies" +TODO: 'notice the daisies' added on line 1. + +>>> todo.sh list +1 notice the daisies +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh replace adf asdfa +usage: $HOME/bin/todo.sh replace ITEM# "UPDATED ITEM" +=== 1 + +>>> todo.sh replace 1 "smell the cows" +1: notice the daisies +replaced with +1: smell the cows + +>>> todo.sh list +1 smell the cows +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh replace 1 smell the roses +1: smell the cows +replaced with +1: smell the roses + +>>> todo.sh list +1 smell the roses +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh replace 1 smell the uppercase Roses +1: smell the roses +replaced with +1: smell the uppercase Roses + +>>> todo.sh list +1 smell the uppercase Roses +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh list roses +1 smell the uppercase Roses +-- +TODO: 1 of 1 tasks shown from $HOME/todo.txt + +>>> todo.sh add notice the sunflowers +TODO: 'notice the sunflowers' added on line 2. + +>>> todo.sh list +2 notice the sunflowers +1 smell the uppercase Roses +-- +TODO: 2 of 2 tasks shown from $HOME/todo.txt + +>>> todo.sh append 1 +flowers @outside +1: smell the uppercase Roses +flowers @outside + +>>> todo.sh list +2 notice the sunflowers +1 smell the uppercase Roses +flowers @outside +-- +TODO: 2 of 2 tasks shown from $HOME/todo.txt + +>>> todo.sh add "stop" +TODO: 'stop' added on line 3. + +>>> todo.sh list +2 notice the sunflowers +1 smell the uppercase Roses +flowers @outside +3 stop +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh pri B B +usage: $HOME/bin/todo.sh pri ITEM# PRIORITY +note: PRIORITY must be anywhere from A to Z. +=== 1 + +>>> todo.sh pri 1 B +1: (B) smell the uppercase Roses +flowers @outside +TODO: 1 prioritized (B). + +>>> todo.sh list +1 (B) smell the uppercase Roses +flowers @outside +2 notice the sunflowers +3 stop +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 notice the sunflowers +3 stop +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh pri 2 C +2: (C) notice the sunflowers +TODO: 2 prioritized (C). + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) notice the sunflowers +3 stop +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh pri 2 A +2: (A) notice the sunflowers +TODO: 2 prioritized (A). + +>>> todo.sh -p list +2 (A) notice the sunflowers +1 (B) smell the uppercase Roses +flowers @outside +3 stop +-- +TODO: 3 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh pri 2 a +2: (A) notice the sunflowers +TODO: 2 prioritized (A). + +>>> todo.sh -p listpri +2 (A) notice the sunflowers +1 (B) smell the uppercase Roses +flowers @outside +-- +TODO: 2 of 3 tasks shown from $HOME/todo.txt + +>>> todo.sh add "smell the coffee +wakeup" +TODO: 'smell the coffee +wakeup' added on line 4. + +>>> todo.sh -p list +2 (A) notice the sunflowers +1 (B) smell the uppercase Roses +flowers @outside +4 smell the coffee +wakeup +3 stop +-- +TODO: 4 of 4 tasks shown from $HOME/todo.txt + +>>> todo.sh -p list +flowers +1 (B) smell the uppercase Roses +flowers @outside +-- +TODO: 1 of 4 tasks shown from $HOME/todo.txt + +>>> todo.sh -p list flowers +2 (A) notice the sunflowers +1 (B) smell the uppercase Roses +flowers @outside +-- +TODO: 2 of 4 tasks shown from $HOME/todo.txt + +>>> todo.sh -p list flowers out +1 (B) smell the uppercase Roses +flowers @outside +-- +TODO: 1 of 4 tasks shown from $HOME/todo.txt + +>>> todo.sh -a do 2 +2: x 2009-02-13 notice the sunflowers +TODO: 2 marked as done. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +4 smell the coffee +wakeup +3 stop +2 x 2009-02-13 notice the sunflowers +-- +TODO: 4 of 4 tasks shown from $HOME/todo.txt + +>>> todo.sh add "make the coffee +wakeup" +TODO: 'make the coffee +wakeup' added on line 5. + +>>> todo.sh -p list coffee +5 make the coffee +wakeup +4 smell the coffee +wakeup +-- +TODO: 2 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh add "visit http://example.com" +TODO: 'visit http://example.com' added on line 6. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +5 make the coffee +wakeup +4 smell the coffee +wakeup +3 stop +6 visit http://example.com +2 x 2009-02-13 notice the sunflowers +-- +TODO: 6 of 6 tasks shown from $HOME/todo.txt + +>>> todo.sh archive +x 2009-02-13 notice the sunflowers +TODO: $HOME/todo.txt archived. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +4 make the coffee +wakeup +3 smell the coffee +wakeup +2 stop +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh report +TODO: Report file updated. +2009-02-13-04:40:00 5 1 + +>>> todo.sh report +TODO: Report file updated. +2009-02-13-04:40:00 5 1 +2009-02-13-04:40:00 5 1 + +>>> todo.sh append g a +usage: $HOME/bin/todo.sh append ITEM# "TEXT TO APPEND" +=== 1 + +>>> todo.sh append 2 and think +2: stop and think + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +4 make the coffee +wakeup +3 smell the coffee +wakeup +2 stop and think +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh pri 2 C +2: (C) stop and think +TODO: 2 prioritized (C). + +>>> todo.sh replace 10 "hej!" +10: No such todo. +=== 1 + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) stop and think +4 make the coffee +wakeup +3 smell the coffee +wakeup +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh append 10 "hej!" +10: No such todo. +=== 1 + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) stop and think +4 make the coffee +wakeup +3 smell the coffee +wakeup +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh do 10 +10: No such todo. +=== 1 + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) stop and think +4 make the coffee +wakeup +3 smell the coffee +wakeup +5 visit http://example.com +-- +TODO: 5 of 5 tasks shown from $HOME/todo.txt + +>>> todo.sh add "the coffee +wakeup" +TODO: 'the coffee +wakeup' added on line 6. + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) stop and think +4 make the coffee +wakeup +3 smell the coffee +wakeup +6 the coffee +wakeup +5 visit http://example.com +-- +TODO: 6 of 6 tasks shown from $HOME/todo.txt + +>>> todo.sh prepend 6 "make" +6: make the coffee +wakeup + +>>> todo.sh -p list +1 (B) smell the uppercase Roses +flowers @outside +2 (C) stop and think +4 make the coffee +wakeup +6 make the coffee +wakeup +3 smell the coffee +wakeup +5 visit http://example.com +-- +TODO: 6 of 6 tasks shown from $HOME/todo.txt + +>>> todo.sh remdup +Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] +Try 'todo.sh -h' for more information. +=== 1 +EOF + +test_done diff --git a/tests/test-lib.sh b/tests/test-lib.sh index 3767c9e..553e512 100644 --- a/tests/test-lib.sh +++ b/tests/test-lib.sh @@ -471,7 +471,7 @@ test_tick () { test_todo_session () { test "$#" = 1 || error "bug in the test script: extra args to test_todo_session" - subnum=0 + subnum=1 cmd="" status=0 > expect @@ -513,6 +513,18 @@ test_todo_session () { fi } +test_shell () { + trap - EXIT + export PS1='$(ret_val=$?; [ "$ret_val" != "0" ] && echo -e "=== $ret_val\n\n>>> "||echo "\n>>> ")' + cat < \$HOME/todo.txt +EOF + bash --noprofile --norc + exit 0 +} + test_init_todo "$test" # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses equals our $PWD (for pathname comparisons). diff --git a/tests/testshell.sh b/tests/testshell.sh new file mode 100755 index 0000000..aae7caa --- /dev/null +++ b/tests/testshell.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +test_description='Providing an interactive shell in the proper environment' +. ./test-lib.sh + +test_shell From 10bca653a0e4da2b8fc0d82f3011f2eb98871ada Mon Sep 17 00:00:00 2001 From: Emil Sit Date: Sun, 12 Apr 2009 10:14:09 -0400 Subject: [PATCH 4/4] tests: Update documentation to reflect recent changes. Merge Phil's README_generate-test into the main README and also update the test library documentation to reflect test_todo_session and test_tick. Signed-off-by: Emil Sit --- tests/README | 41 +++++++++++++++++++++++++++++++++++++- tests/README_generate-test | 15 -------------- 2 files changed, 40 insertions(+), 16 deletions(-) delete mode 100644 tests/README_generate-test diff --git a/tests/README b/tests/README index 514c0a5..7e748fa 100644 --- a/tests/README +++ b/tests/README @@ -176,6 +176,23 @@ Test harness library There are a handful helper functions defined in the test harness library for your script to use. + - test_todo_session < transcript + + This takes a single string as a parameter, which is treated + as a base description of what is being tested, and then + reads from standard input a transcript of todo.sh commands + and expected output. Each command is run in the current + test environment and the output is compared with the + expected output. (See below for how to generate transcripts + easily.) + + - test_tick [interval] + + The test harness has an internal view of time which is + implemented by wrapping the date command. This takes a single + optional positive integer parameter which indicates how much + to advance the internal time. The default value is one day. + - test_expect_success