This project is stored on code.google.com as http://code.google.com/p/shunit2/. -All releases as of 2.1.4 and full source are available there. Documentation is -included as part of the source and each release. Source code is stored in -Subversion and can be accessed using the following information.
-Browse the code in a web browser:
-Check out the code locally
--$ svn checkout http://shunit2.googlecode.com/svn/trunk/ shflags-read-only --
DEPRECATED
-This project is stored on SourceForge as http://sf.net/projects/shunit2. The -source code is stored in Subversion and can be accessed using the following -information.
-Check out the code locally
--$ svn co https://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1 shunit2 --
Browse the code in a web browser:
- -For these steps, it is assumed we are working with release 2.0.0.
-Steps:
-This should be pretty self explanatory. Use one of the release notes from a -previous release as an example.
-The versions of the various platforms and shells are included when the -master unit test script is run, or when bin/gen_test_results.sh is -used. To determine the versions of the installed shells by hand, use the -lib/versions script.
-Alternatively, do the following:
-Shell | -OS | -Notes | -
---|---|---|
bash | -- | $ bash --version | -
dash | -Linux | -$ dpkg -l |grep dash | -
ksh | -- | $ ksh --version --or- -$ echo 'echo $KSH_VERSION' |ksh | -
Cygwin | -see pdksh | -|
Solaris | -$ strings /usr/bin/ksh |grep 'Version' | -|
pdksh | -- | $ strings /bin/pdksh |grep 'PD KSH' | -
Cygwin | -look in the downloaded Cygwin directory | -|
sh | -Solaris | -not possible | -
zsh | -- | $ zsh --version | -
Edit src/shell/shunit2 and change the version number in the comment, as well -as in the SHUNIT_VERSION variable.
-Make sure that any remaining changes get put into the CHANGES-X.X.txt file.
-Finish writing the RELEASE_NOTES-X.X.X.txt. If necessary, run it -through the fmt command to make it pretty (hopefully it is already).
--$ fmt -w 80 RELEASE_NOTES-2.0.0.txt >RELEASE_NOTES-2.0.0.txt.new -$ mv RELEASE_NOTES-2.0.0.txt.new RELEASE_NOTES-2.0.0.txt --
We want to have an up-to-date version of the documentation in the release, so -we'd better build it.
--$ pwd -.../shunit2/source/2.1 -$ cd doc -$ RST2HTML_OPTS='--stylesheet-path=rst2html.css' -$ rst2html ${RST2HTML_OPTS} shunit2.txt >shunit2.html -$ rst2html ${RST2HTML_OPTS} README.txt >README.html --
This step is pretty self-explanatory
--$ pwd -.../shunit2/source/2.0 -$ svn ci -m "finalizing release" --
-$ pwd -.../shunit2/source -$ ls -2.0 2.1 -$ svn cp -m "Release 2.0.0" 2.0 https://shunit2.googlecode.com/svn/tags/source/2.0.0 --
-$ pwd -.../shunit2/builds -$ svn export https://shunit2.googlecode.com/svn/tags/source/2.0.0 shunit2-2.0.0 --
-$ tar cfz ../releases/shunit2-2.0.0.tgz shunit2-2.0.0 --
-$ cd ../releases -$ gpg --default-key kate.ward@forestent.com --detach-sign shunit2-2.0.0.tgz --
Again, pretty self-explanatory. Make sure to copy the GPG signature file. Once -that is done, make sure to tag the website so we can go back in time if needed.
--$ pwd -.../shunit2 -$ ls -source website -$ svn cp -m "Release 2.0.0" \ -website https://shunit2.googlecode.com/svn/tags/website/20060916 --
Now, update the website. It too is held in Subversion, so ssh into the web -server and use svn up to grab the latest version.
-shUnit2 is a xUnit unit test framework for Bourne based shell scripts, and it -is designed to work in a similar manner to JUnit, PyUnit, etc.. If you have -ever had the desire to write a unit test for a shell script, shUnit2 can do the -job.
-Table of Contents
-shUnit2 was originally developed to provide a consistent testing solution for -log4sh, a shell based logging framework similar to log4j. During the -development of that product, a repeated problem of having things work just fine -under one shell (/bin/bash on Linux to be specific), and then not working -under another shell (/bin/sh on Solaris) kept coming up. Although several -simple tests were run, they were not adequate and did not catch some corner -cases. The decision was finally made to write a proper unit test framework after -multiple brown-bag releases were made. Research was done to look for an -existing product that met the testing requirements, but no adequate product was -found.
-Tested Operating Systems (varies over time)
-Tested Shells
-See the appropriate Release Notes for this release -(doc/RELEASE_NOTES-X.X.X.txt) for the list of actual versions tested.
-A list of contributors to shUnit2 can be found in the source archive in -doc/contributors.txt. Many thanks go out to all those who have contributed -to make this a better tool.
-shUnit2 is the original product of many hours of work by Kate Ward, the primary -author of the code. For other products by her, look up log4sh or shFlags, or -visit her website at http://forestent.com/.
-Feedback is most certainly welcome for this document. Send your additions, -comments and criticisms to the shunit2-users@google.com mailing list.
-This section will give a very quick start to running unit tests with shUnit2. -More information is located in later sections.
-Here is a quick sample script to show how easy it is to write a unit test in -shell. Note: the script as it stands expects that you are running it from the -``examples`` directory.
--#! /bin/sh -# file: examples/equality_test.sh - -testEquality() -{ - assertEquals 1 1 -} - -# load shunit2 -. ../src/shell/shunit2 --
Running the unit test should give results similar to the following.
--testEquality - -Ran 1 test. - -OK --
W00t! You've just run your first successful unit test. So, what just happened? -Quite a bit really, and it all happened simply by sourcing the shunit2 -library. The basic functionality for the script above goes like this:
-We should now try adding a test that fails. Change your unit test to look like -this.
--#! /bin/sh -# file: examples/party_test.sh - -testEquality() -{ - assertEquals 1 1 -} - -testPartyLikeItIs1999() -{ - year=`date '+%Y'` - assertEquals "It's not 1999 :-(" \ - '1999' "${year}" -} - -# load shunit2 -. ../src/shell/shunit2 --
So, what did you get? I guess it told you that this isn't 1999. Bummer, eh? -Hopefully, you noticed a couple of things that were different about the second -test. First, we added an optional message that the user will see if the assert -fails. Second, we did comparisons of strings instead of integers as in the first -test. It doesn't matter whether you are testing for equality of strings or -integers. Both work equally well with shUnit2.
-Hopefully, this is enough to get you started with unit testing. If you want a -ton more examples, take a look at the tests provided with log4sh or shFlags. -Both provide excellent examples of more advanced usage. shUnit2 was after all -written to help with the unit testing problems that log4sh had.
-Any string values passed should be properly quoted -- they should must be -surrounded by single-quote (') or double-quote (") characters -- so that the -shell will properly parse them.
-Asserts that a given shell test condition is true. The condition can be as -simple as a shell true value (the value 0 -- equivalent to -${SHUNIT_TRUE}), or a more sophisticated shell conditional expression. The -message is optional, and must be quoted.
-A sophisticated shell conditional expression is equivalent to what the if -or while shell built-ins would use (more specifically, what the test -command would use). Testing for example whether some value is greater than -another value can be done this way.
--assertTrue "[ 34 -gt 23 ]" --
Testing for the ability to read a file can also be done. This particular test -will fail.
--assertTrue 'test failed' "[ -r /some/non-existant/file' ]" --
As the expressions are standard shell test expressions, it is possible to -string multiple expressions together with -a and -o in the standard -fashion. This test will succeed as the entire expression evaluates to true.
--assertTrue 'test failed' '[ 1 -eq 1 -a 2 -eq 2 ]' --
One word of warning: be very careful with your quoting as shell is not the -most forgiving of bad quoting, and things will fail in strange ways.
-Asserts that a given shell test condition is false. The condition can be -as simple as a shell false value (the value 1 -- equivalent to -${SHUNIT_FALSE}), or a more sophisticated shell conditional expression. -The message is optional, and must be quoted.
-For examples of more sophisticated expressions, see ``assertTrue``.
-Just to clarify, failures do not test the various arguments against one -another. Failures simply fail, optionally with a message, and that is all they -do. If you need to test arguments against one another, use asserts.
-If all failures do is fail, why might one use them? There are times when you may -have some very complicated logic that you need to test, and the simple asserts -provided are simply not adequate. You can do your own validation of the code, -use an assertTrue ${SHUNIT_TRUE} if your own tests succeeded, and use a -failure to record a failure.
-Fails the test immediately, reporting that the unexpected and actual -values are not equal to one another. The message is optional, and must be -quoted.
-Note: no actual comparison of unexpected and actual is done.
-Fails the test immediately, reporting that the expected and actual values -are the same. The message is optional, and must be quoted.
-Note: no actual comparison of expected and actual is done.
-Fails the test immediately, reporting that the expected and actual values -are not the same. The message is optional, and must be quoted.
-Note: no actual comparison of expected and actual is done.
-This function can be be optionally overridden by the user in their test suite.
-If this function exists, it will be called once before any tests are run. It -is useful to prepare a common environment for all tests.
-This function can be be optionally overridden by the user in their test suite.
-If this function exists, it will be called once after all tests are completed. -It is useful to clean up the environment after all tests.
-This function can be be optionally overridden by the user in their test suite.
-If this function exists, it will be called before each test is run. It is -useful to reset the environment before each test.
-This function can be be optionally overridden by the user in their test suite.
-If this function exists, it will be called after each test completes. It is -useful to clean up the environment after each test.
-The default behavior of shUnit2 is that all tests will be found dynamically. If -you have a specific set of tests you want to run, or you don't want to use the -standard naming scheme of prefixing your tests with test, these functions -are for you. Most users will never use them though.
-This function can be optionally overridden by the user in their test suite.
-If this function exists, it will be called when shunit2 is sourced. If it -does not exist, shUnit2 will search the parent script for all functions -beginning with the word test, and they will be added dynamically to the -test suite.
-This section covers several advanced usage topics.
-There are several constants provided by shUnit2 as variables that might be of -use to you.
-Predefined
-SHUNIT_VERSION | -The version of shUnit2 you are running. | -
SHUNIT_TRUE | -Standard shell true value (the integer value 0). | -
SHUNIT_FALSE | -Standard shell false value (the integer value 1). | -
SHUNIT_ERROR | -The integer value 2. | -
SHUNIT_TMPDIR | -Path to temporary directory that will be automatically -cleaned up upon exit of shUnit2. | -
User defined
-SHUNIT_PARENT | -The filename of the shell script containing the tests. This -is needed specifically for Zsh support. | -
The constants values SHUNIT_TRUE, SHUNIT_FALSE, and SHUNIT_ERROR are -returned from nearly every function to indicate the success or failure of the -function. Additionally the variable flags_error is filled with a detailed -error message if any function returns with a SHUNIT_ERROR value.
-If you include lots of assert statements in an individual test function, it can -become difficult to determine exactly which assert was thrown unless your -messages are unique. To help somewhat, line numbers can be included in the -assert messages. To enable this, a special shell "macro" must be used rather -than the standard assert calls. Shell doesn't actually have macros; the name is -used here as the operation is similar to a standard macro.
-For example, to include line numbers for a assertEquals() function call, -replace the assertEquals() with ${_ASSERT_EQUALS_}.
-Example -- Asserts with and without line numbers
--#! /bin/sh -# file: examples/lineno_test.sh - -testLineNo() -{ - # this assert will have line numbers included (e.g. "ASSERT:[123] ...") - echo "ae: ${_ASSERT_EQUALS_}" - ${_ASSERT_EQUALS_} 'not equal' 1 2 - - # this assert will not have line numbers included (e.g. "ASSERT: ...") - assertEquals 'not equal' 1 2 -} - -# load shunit2 -. ../src/shell/shunit2 --
Notes:
-Due to how shell parses command-line arguments, all strings used with macros -should be quoted twice. Namely, single-quotes must be converted to -single-double-quotes, and vice-versa. If the string being passed is -absolutely for sure not empty, the extra quoting is not necessary.
-Normal assertEquals call.
--assertEquals 'some message' 'x' '' --
Macro _ASSERT_EQUALS_ call. Note the extra quoting around the message -and the null value.
--_ASSERT_EQUALS_ '"some message"' 'x' '""' --
Line numbers are not supported in all shells. If a shell does not support -them, no errors will be thrown. Supported shells include: bash (>=3.0), -ksh, pdksh, and zsh.
-There are times where the test code you have written is just not applicable to -the system you are running on. This section describes how to skip these tests -but maintain the total test count.
-Probably the easiest example would be shell code that is meant to run under the -bash shell, but the unit test is running under the Bourne shell. There are -things that just won't work. The following test code demonstrates two sample -functions, one that will be run under any shell, and the another that will run -only under the bash shell.
-Example -- math include
--# available as examples/math.inc - -add_generic() -{ - num_a=$1 - num_b=$2 - - expr $1 + $2 -} - -add_bash() -{ - num_a=$1 - num_b=$2 - - echo $(($1 + $2)) -} --
And here is a corresponding unit test that correctly skips the add_bash() -function when the unit test is not running under the bash shell.
-Example -- math unit test
--#! /bin/sh -# available as examples/math_test.sh - -testAdding() -{ - result=`add_generic 1 2` - assertEquals \ - "the result of '${result}' was wrong" \ - 3 "${result}" - - # disable non-generic tests - [ -z "${BASH_VERSION:-}" ] && startSkipping - - result=`add_bash 1 2` - assertEquals \ - "the result of '${result}' was wrong" \ - 3 "${result}" -} - -oneTimeSetUp() -{ - # load include to test - . ./math.inc -} - -# load and run shUnit2 -. ../src/shell/shunit2 --
Running the above test under the bash shell will result in the following -output.
--$ /bin/bash math_test.sh -testAdding - -Ran 1 test. - -OK --
But, running the test under any other Unix shell will result in the following -output.
--$ /bin/ksh math_test.sh -testAdding - -Ran 1 test. - -OK (skipped=1) --
As you can see, the total number of tests has not changed, but the report -indicates that some tests were skipped.
-Skipping can be controlled with the following functions: startSkipping(), -stopSkipping(), and isSkipping(). Once skipping is enabled, it will -remain enabled until the end of the current test function call, after which -skipping is disabled.
-For help, please send requests to either the shunit2-users@googlegroups.com -mailing list (archives available on the web at -http://groups.google.com/group/shunit2-users) or directly to -Kate Ward <kate dot ward at forestent dot com>.
-For compatibility with Zsh, there is one requirement that must be met -- the -shwordsplit option must be set. There are three ways to accomplish this.
-In the unit-test script, add the following shell code snippet before sourcing -the shunit2 library.
--setopt shwordsplit --
When invoking zsh from either the command-line or as a script with -#!, add the -y parameter.
--#! /bin/zsh -y --
When invoking zsh from the command-line, add -o shwordsplit -- as -parameters before the script name.
--$ zsh -o shwordsplit -- some_script --