Compare commits
	
		
			37 Commits
		
	
	
		
			update-rea
			...
			tlevine-20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 96ab43c233 | ||
|  | 2be0151213 | ||
|  | 655daf4b74 | ||
|  | 31023bce21 | ||
|  | d96f3707e9 | ||
|  | 3f05794d7e | ||
|  | d7c8549206 | ||
|  | bc74b20c5c | ||
|  | 8bdd00c3e9 | ||
|  | 42dd0947e8 | ||
|  | da6d89aa56 | ||
|  | 3ea035d188 | ||
|  | 8e669c40a6 | ||
|  | 66c010b694 | ||
|  | 7339e84d7c | ||
|  | e364d40f3a | ||
|  | 13e748d684 | ||
|  | bb42d27917 | ||
|  | c1ec06c6fe | ||
|  | 5382946639 | ||
|  | 144013c71c | ||
|  | 009fd7ea05 | ||
|  | c3901fe175 | ||
|  | 538c8437a7 | ||
|  | cd124e09ee | ||
|  | d963f10be1 | ||
|  | 0ca55d155b | ||
|  | 8d55550248 | ||
|  | 0f86778d79 | ||
|  | 92cb735bb7 | ||
|  | c817355e94 | ||
|  | d4bedbbfcf | ||
|  | f6b57772f2 | ||
|  | 72fa30e787 | ||
|  | eda4a6e42c | ||
|  | df80586d79 | ||
|  | d525c1793b | 
							
								
								
									
										9
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| Authors | ||||
| ------- | ||||
| David Jones | ||||
| Michael Klement | ||||
| Thomas Levine | ||||
|  | ||||
| Maintainer | ||||
| ------- | ||||
| Thomas Levine <_@thomaslevine.com> | ||||
							
								
								
									
										20
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -1,5 +1,23 @@ | ||||
| HISTORY | ||||
| ------- | ||||
| ======= | ||||
|  | ||||
| Version 0.0.6 | ||||
| --------------------- | ||||
|  | ||||
| * Produce TAP output with the -t flag. | ||||
| * Add a + sign in front of directories in the normal output so that they | ||||
|   line up with non-directories. | ||||
| * Display skipped tests in the normal output and in the TAP output. | ||||
| * Correct some things in the documentation. | ||||
| * Rearrange things in the documentation to be more clear. | ||||
| * Pass the -e flag to exit urchin if any single test fails. | ||||
| * Remove the undocumented, experimental -x flag now that shall exists. | ||||
| * Display version number with the -v flag. | ||||
| * Document why Urchin is called "Urchin" | ||||
|  | ||||
| These changes are made somewhat separately in the branches "exit-on-fail", | ||||
| "remove-urchin-x", "tap", and "update-readme". They are rebased into one | ||||
| branch, "tlevine-2016-02", for merging into "master". | ||||
|  | ||||
| Version 0.0.5 | ||||
| --------------------- | ||||
|   | ||||
| @@ -6,7 +6,7 @@ for shell in dash bash ksh zsh; do | ||||
|   if which $shell > /dev/null 2> /dev/null; then | ||||
|     echo | ||||
|     echo Running urchin tests in $shell | ||||
|     $shell urchin tests | tail -n 3 | ||||
|     $shell urchin -s $shell tests | tail -n 4 | ||||
|   else | ||||
|     echo | ||||
|     echo Skipping $shell because it is not in the PATH | ||||
|   | ||||
| @@ -8,6 +8,10 @@ Urchin is a file-based test harness, normally used for testing shell programs. | ||||
| It is written in portable shell and should thus work on GNU/Linux, BSD | ||||
| (including Mac OS X), and other Unix-like platforms. | ||||
|  | ||||
| Urchin is called "Urchin" because | ||||
| [sea urchins](https://en.wikipedia.org/wiki/Sea_urchin) | ||||
| have shells called "tests". | ||||
|  | ||||
| ## Try it out | ||||
| Urchin's tests are written in Urchin, so you can run them to see what Urchin | ||||
| is like. Clone the repository | ||||
|   | ||||
							
								
								
									
										0
									
								
								tests/.die-on-fail/1 should run.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										0
									
								
								tests/.die-on-fail/1 should run.
									
									
									
									
									
										Executable file
									
								
							
							
								
								
									
										1
									
								
								tests/.die-on-fail/2 should run.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								tests/.die-on-fail/2 should run.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| false | ||||
							
								
								
									
										1
									
								
								tests/.die-on-fail/3 should not run.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								tests/.die-on-fail/3 should not run.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| false | ||||
							
								
								
									
										1
									
								
								tests/.die-on-fail/4 should not run.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								tests/.die-on-fail/4 should not run.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| false | ||||
| @@ -1,5 +1,3 @@ | ||||
| #!/usr/bin/awk -f | ||||
|  | ||||
| # This script will only succeed if it is indeed processed by awk. | ||||
|  | ||||
| BEGIN { print "ok" } | ||||
| #!/usr/bin/env true | ||||
| true will processed the contents of this script, but that | ||||
| means that nothing will happen and the script will exit 0  | ||||
|   | ||||
| @@ -3,6 +3,5 @@ | ||||
| # Tests the `-s <shell> option, which invokes shebang-less and sh-shebang-line test scripts with the specified shell (for testing *sourced* shell code). | ||||
|  | ||||
| which bash >/dev/null || { echo "Cannot test -s option: bash cannot be located." >&2; exit 2; } | ||||
| which /usr/bin/awk >/dev/null || { echo "Cannot test -s option: /usr/bin/awk not found." >&2; exit 2; } | ||||
|  | ||||
| ../../urchin -s bash ./.test-run-by-specified-shell | ||||
|   | ||||
							
								
								
									
										11
									
								
								tests/Exit on fail if -e is passed.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								tests/Exit on fail if -e is passed.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| tmp=$(mktemp) | ||||
| ../urchin -e -f ./.die-on-fail > $tmp | ||||
| result=$? | ||||
|  | ||||
| grep '1 should run.' $tmp | ||||
| grep '2 should run.' $tmp | ||||
| grep -v '3 should not run.' $tmp | ||||
| grep -v '4 should not run.' $tmp | ||||
|  | ||||
| rm $tmp | ||||
| exit $result | ||||
							
								
								
									
										2
									
								
								tests/Print version on -v.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								tests/Print version on -v.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| #!/bin/sh | ||||
| ../urchin -v | grep '[0-9.]\{3,\}' | ||||
							
								
								
									
										10
									
								
								tests/TAP/.expected-output
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/TAP/.expected-output
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| # Begin - .testsuite/ | ||||
| not ok 1 - a | ||||
| # ------------ Begin output ------------ | ||||
| # This is stdout from a. | ||||
| # ------------ End output ------------ | ||||
| ok 2 - b | ||||
| ok 3 - # SKIP c | ||||
| # End - .testsuite/ | ||||
| # Took 0 seconds. | ||||
| 1..3 | ||||
							
								
								
									
										4
									
								
								tests/TAP/.testsuite/a
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								tests/TAP/.testsuite/a
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| #!/bin/sh | ||||
| echo This is stderr from a. > /dev/stderr | ||||
| echo This is stdout from a. > /dev/stdout | ||||
| false | ||||
							
								
								
									
										4
									
								
								tests/TAP/.testsuite/b
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								tests/TAP/.testsuite/b
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| #!/bin/sh | ||||
| echo This is stderr from b. > /dev/stderr | ||||
| echo This is stdout from b. > /dev/stdout | ||||
| true | ||||
							
								
								
									
										1
									
								
								tests/TAP/.testsuite/c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/TAP/.testsuite/c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| This should not be run. | ||||
							
								
								
									
										4
									
								
								tests/TAP/Running with -t should produce TAP output.
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								tests/TAP/Running with -t should produce TAP output.
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| tmp=$(mktemp) | ||||
|  | ||||
| ../../urchin -t .testsuite/ | sed 1d > $tmp | ||||
| diff $tmp .expected-output | ||||
| @@ -1,3 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| test c = $(../urchin -x .print-arg-3 a 'b b b b' c d e) | ||||
							
								
								
									
										128
									
								
								urchin
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								urchin
									
									
									
									
									
								
							| @@ -4,6 +4,9 @@ | ||||
| # which breaks fullpath(). | ||||
| unset CDPATH | ||||
|  | ||||
| # Urchin version number | ||||
| VERSION=0.0.6 | ||||
|  | ||||
| fullpath() { | ||||
|   ( | ||||
|     cd -- "$1" | ||||
| @@ -30,9 +33,16 @@ recurse() { | ||||
|  | ||||
|   if [ -d "$potential_test" ] | ||||
|     then | ||||
|     ( | ||||
|  | ||||
|     if $tap_format; then | ||||
|       indent $indent_level | sed 's/  /#/g' | ||||
|       echo "# Begin - ${potential_test}" | ||||
|     else | ||||
|       indent $indent_level | ||||
|       echo "  ${potential_test}" | ||||
|       echo "+ ${potential_test}" | ||||
|     fi | ||||
|  | ||||
|     ( | ||||
|       cd -- "$potential_test" | ||||
|       [ -f setup_dir ] && [ -x setup_dir ] && ./setup_dir >> "$stdout_file" | ||||
|  | ||||
| @@ -47,15 +57,27 @@ recurse() { | ||||
|  | ||||
|         # $2 instead of $indent_level so it doesn't clash | ||||
|         recurse "${test}" $(( $2 + 1 )) "$shell_for_sh_tests" | ||||
|         exit_code=$? | ||||
|  | ||||
|         if $exit_on_fail && test $exit_code -ne 0; then | ||||
|           [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" | ||||
|           [ -f teardown_dir ] && [ -x teardown_dir ] && ./teardown_dir >> "$stdout_file" | ||||
|           return 1 | ||||
|         fi | ||||
|  | ||||
|         [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" | ||||
|       done | ||||
|       [ -f teardown_dir ] && [ -x teardown_dir ] && ./teardown_dir >> "$stdout_file" | ||||
|       echo | ||||
|     ) | ||||
|   elif [ -x "$potential_test" ] | ||||
|     if $tap_format; then | ||||
|       indent $indent_level | sed 's/  /#/g' | ||||
|       echo "# End - ${potential_test}" | ||||
|     else | ||||
|       echo | ||||
|     fi | ||||
|   else | ||||
|     if [ -x "$potential_test" ] | ||||
|       then | ||||
|  | ||||
|       [ -f setup ] && [ -x setup ] && ./setup >> "$stdout_file" | ||||
|  | ||||
|       # Run the test | ||||
| @@ -67,24 +89,60 @@ recurse() { | ||||
|       fi | ||||
|       exit_code="$?" | ||||
|  | ||||
|  | ||||
|       [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" | ||||
|       if [ $exit_code -eq 0 ]; then | ||||
|         result=success | ||||
|       else | ||||
|         result=fail | ||||
|       fi | ||||
|     else | ||||
|       result=skip | ||||
|     fi | ||||
|  | ||||
|     echo "${result}" >> "$logfile" | ||||
|     if $tap_format; then | ||||
|       n=$(grep -ce '^\(success\|fail\|skip\)' "$logfile") | ||||
|  | ||||
|       if [ "$result" == fail ]; then | ||||
|         not='not ' | ||||
|       else | ||||
|         not='' | ||||
|       fi | ||||
|       if [ "$result" == skip ]; then | ||||
|         skip='# SKIP ' | ||||
|       else | ||||
|         skip='' | ||||
|       fi | ||||
|       echo "${not}ok $n - ${skip}${potential_test}" | ||||
|       if [ "$result" == fail ]; then | ||||
|         echo '# ------------ Begin output ------------' | ||||
|         sed 's/^/# /' "$stdout_file" | ||||
|         echo '# ------------ End output ------------' | ||||
|       fi | ||||
|     else | ||||
|       indent $indent_level | ||||
|     if [ $exit_code -eq 0 ] | ||||
|       then | ||||
|       case "$result" in | ||||
|         success) | ||||
|           # On success, print a green '✓' | ||||
|           printf '\033[32m✓ \033[0m' | ||||
|           printf '%s\n' "${potential_test}" | ||||
|       printf '%s\n' "${potential_test} passed" >> "$logfile" | ||||
|     else | ||||
|         ;; | ||||
|         fail) | ||||
|           # On fail, print a red '✗' | ||||
|           printf '\033[31m✗ \033[0m' | ||||
|           printf '%s\n' "${potential_test}" | ||||
|       printf '%s\n' "${potential_test} failed" >> "$logfile" | ||||
|           printf '\033[31m' # Print output captured from failed test in red. | ||||
|           cat "$stdout_file" | ||||
|           printf '\033[0m' | ||||
|         ;; | ||||
|         skip) | ||||
|           printf '  %s\n' "${potential_test}" | ||||
|         ;; | ||||
|       esac | ||||
|     fi | ||||
|  | ||||
|     if $exit_on_fail && test 0 -ne $exit_code; then | ||||
|       return 1 | ||||
|     fi | ||||
|   fi | ||||
|   [ $indent_level -eq 0 ] && rm "$stdout_file" | ||||
| @@ -105,17 +163,18 @@ $USAGE | ||||
|  | ||||
| -s <shell>  Invoke test scripts that either have no shebang line at all or | ||||
|             have shebang line "#!/bin/sh" with the specified shell. | ||||
| -e          Stop running if any single test fails. This is helpful if you want | ||||
|             to use Urchin to run things other than tests, such as a set of | ||||
|             configuration scripts. | ||||
| -f          Force running even if the test directory's name does not | ||||
|             contain the word "test". | ||||
| -h          This help. | ||||
| -t          Format output in Test Anything Protocol (TAP) | ||||
| -h, --help  This help. | ||||
| -v          Display the version number. | ||||
|  | ||||
| Go to https://github.com/tlevine/urchin for documentation on writing tests. | ||||
|  | ||||
| EOF | ||||
|   # [Experimental -x option left undocumented for now.] | ||||
|   # -x          [Experimental; not meant for direct invocation, but for use in | ||||
|   #             the shebang line of test scripts] | ||||
|   #             Run with "\$TEST_SHELL", falling back on /bin/sh. | ||||
| } | ||||
|  | ||||
| plural () { | ||||
| @@ -131,7 +190,11 @@ plural () { | ||||
| } | ||||
|  | ||||
| urchin_go() { | ||||
|   echo Running tests at $(date +%Y-%m-%dT%H:%M:%S) | tee "$logfile" | ||||
|   rm -f "$logfile" | ||||
|   if "$tap_format"; then | ||||
|     printf \#\  | ||||
|   fi | ||||
|   echo Running tests at $(date +%Y-%m-%dT%H:%M:%S) | ||||
|   start=$(date +%s) | ||||
|  | ||||
|   # Determine the environment variable to define for test scripts | ||||
| @@ -151,13 +214,23 @@ urchin_go() { | ||||
|  | ||||
|   finish=$(date +%s) | ||||
|   elapsed=$(($finish - $start)) | ||||
|  | ||||
|   passed=$(grep -c '^success' "$logfile") | ||||
|   failed=$(grep -c '^fail' "$logfile") | ||||
|   skipped=$(grep -c '^skip' "$logfile") | ||||
|   if $tap_format; then | ||||
|     echo "# Took $elapsed $(plural second $elapsed)." | ||||
|     echo 1..$(($passed + $failed + $skipped)) | ||||
|   else | ||||
|     echo "Done, took $elapsed $(plural second $elapsed)." | ||||
|   set -- $(grep -e 'passed$' "$logfile"|wc -l) $(grep -e 'failed$' "$logfile"|wc -l) | ||||
|   printf '%s\n' "$1 $(plural test "$1") passed." | ||||
|   [ $2 -gt 0 ] && printf '\033[31m' || printf '\033[32m' # If tests failed, print the message in red, otherwise in green. | ||||
|   printf '%s\n' "$2 $(plural test "$2") failed." | ||||
|     printf '%s\n' "$passed $(plural test "$passed") passed." | ||||
|     printf '%s\n' "$skipped $(plural test "$skipped") skipped." | ||||
|     [ $failed -gt 0 ] && printf '\033[31m' || printf '\033[32m' # If tests failed, print the message in red, otherwise in green. | ||||
|     printf '%s\n' "$failed $(plural test "$failed") failed." | ||||
|     printf '\033[m' | ||||
|   return "$2" | ||||
|   fi | ||||
|   rm -f "$logfile" | ||||
|   test -z "$failed" || test "$failed" -eq '0' | ||||
| } | ||||
|  | ||||
| urchin_molly_guard() { | ||||
| @@ -174,22 +247,23 @@ urchin_molly_guard() { | ||||
|  | ||||
| shell_for_sh_tests= | ||||
| force=false | ||||
| exit_on_fail=false | ||||
| tap_format=false | ||||
| while [ $# -gt 0 ] | ||||
| do | ||||
|     case "$1" in | ||||
|         -e) exit_on_fail=true;; | ||||
|         -f) force=true;; | ||||
|         -s) | ||||
|           shift | ||||
|           shell_for_sh_tests=$1 | ||||
|           which "$shell_for_sh_tests" >/dev/null || { echo "Cannot find specified shell: '$shell_for_sh_tests'" >&2; urchin_help >&2; exit 2; } | ||||
|           ;; | ||||
|         -x) # [EXPERIMENTAL; UNDOCUMENTED FOR NOW] `urchin -x <test-script>` in a test script's shebang line is equivalent to invoking that script with `"$TEST_SHELL" <test-script>` | ||||
|           shift | ||||
|           urchinsh=${TEST_SHELL:-/bin/sh} | ||||
|           "$urchinsh" "$@" | ||||
|           exit $?;; | ||||
|         -t) tap_format=true;; | ||||
|         -h|--help) urchin_help | ||||
|           exit 0;; | ||||
|         -v) echo "$VERSION" | ||||
|             exit;; | ||||
|         -*) urchin_help >&2 | ||||
|             exit 1;; | ||||
|         *)  break;; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user