SkillAgentSearch skills...

Shunit2

shUnit2 is a xUnit based unit test framework for Bourne based shell scripts.

Install / Use

/learn @kward/Shunit2
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

shUnit2

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.

Travis CI

Information

If you want to jump straight in, scroll down to the Quickstart section.

Background

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 software

Tested Operating Systems (varies over time)

| OS | Support | Verified | | ----------------------------------- | --------- | ---------- | | Ubuntu Linux (14.04.05 LTS) | Travis CI | continuous | | macOS High Sierra (10.13.3) | Travis CI | continuous | | FreeBSD | user | unknown | | Solaris 8, 9, 10 (inc. OpenSolaris) | user | unknown | | Cygwin | user | unknown |

Tested Shells

  • Bourne Shell (sh)
  • BASH - GNU Bourne Again SHell (bash)
  • DASH - Debian Almquist Shell (dash)
  • Korn Shell - AT&T version of the Korn shell (ksh)
  • mksh - MirBSD Korn Shell (mksh)
  • zsh - Zsh (zsh) (since 2.1.2) please see the Zsh shell errata for more information

See the appropriate Release Notes for this release (doc/RELEASE_NOTES-X.X.X.txt) for the list of actual versions tested.

Credits / Contributors

A list of contributors to shUnit2 can be found in doc/contributors.md. 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 related software, check out https://github.com/kward.

Feedback

Feedback is most certainly welcome for this document. Send your questions, comments, and criticisms via the shunit2-users forum (created 2018-12-09), or file an issue via https://github.com/kward/shunit2/issues.

Quickstart

Overview

shUnit is designed to execute all functions in your unit test that are prefixed test. It will walk through them one by one in the order they appear. In addition, there are some helper functions that will be called to setup and cleanup the environment.

The overall flow looks like this.

sequenceDiagram
  participant unit_test as unit test

  unit_test-->>shUnit2: shUnit2 loaded from unit test

  note over unit_test,shUnit2: shUnit2 identifies test*() functions

  shUnit2->>unit_test: oneTimeSetUp()

  loop for each test function
    shUnit2->>unit_test: setUp()
    shUnit2->>unit_test: testSomeFunction()
    unit_test-->>script: code called from testSomeFunction()
    shUnit2->>unit_test: tearDown()
  end

  shUnit2->>unit_test: oneTimeTearDown()

Your first test

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.
. ../shunit2

Running the unit test should give results similar to the following.

$ cd examples
$ ./equality_test.sh
testEquality

Ran 1 test.

OK

W00t! You've just run your first successful unit test.

Analysis

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:

When shUnit2 is sourced, it will walk through any functions defined whose name starts with the string test, and add those to an internal list of tests to execute. Once a list of test functions to be run has been determined, shunit2 will go to work.

Before any tests are executed, shUnit2 again looks for a function, this time one named oneTimeSetUp(). If it exists, it will be run. This function is normally used to setup the environment for all tests to be run. Things like creating directories for output or setting environment variables are good to place here. Just so you know, you can also declare a corresponding function named oneTimeTearDown() function that does the same thing, but once all the tests have been completed. It is good for removing temporary directories, etc.

shUnit2 is now ready to run tests.

  • Before doing so though, it again looks for another function that might be declared, one named setUp(). If the function exists, it will be run before each test. It is good for resetting the environment so that each test starts with a clean slate.
  • At this stage, the first test is finally run. The success of the test is recorded for a report that will be generated later.
  • After the test is run, shUnit2 looks for a final function that might be declared, one named tearDown(). If it exists, it will be run after each test. It is a good place for cleaning up after each test, maybe doing things like removing files that were created, or removing directories. This set of steps, setUp() > test() > tearDown(), is repeated for all of the available tests.

Once all the work is done, shUnit2 will generate the nice report you saw above. A summary of all the successes and failures will be given so that you know how well your code is doing.

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.
. ../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 meet the unit testing need that log4sh had.

If you are using distribution packaged shUnit2 which is accessible from /usr/bin/shunit2 such as Debian, you can load shUnit2 without specifying its path. So the last 2 lines in the above can be replaced by:

# Load shUnit2.
. shunit2

Function Reference

General Info

Any string values passed should be properly quoted -- they should be surrounded by single-quote (') or double-quote (") characters -- so that the shell will properly parse them.

Asserts

Equality

assertEquals [message] expected actual

Asserts that expected and actual are equal to one another. The expected and actual values can be either strings or integer values as both will be treated as strings. The message is optional, and must be quoted.

assertNotEquals [message] unexpected actual

Asserts that unexpected and actual are not equal to one another. The unexpected and actual values can be either strings or integer values as both will be treated as strings. The message is optional, and must be quoted.

assertSame [message] expected actual

{deprecated} This function is functionally equivalent to assertEquals.

assertNotSame [message] unexpected actual

{deprecated} This function is functionally equivalent to assertNotEquals.

Containment

assertContains [message] container content

Asserts that container contains content. The container and content values can be either strings or integer values as both will be treated as strings. The message is optional, and must be quoted.

assertNotContains [message] container content

Asserts that container does not contain content. The container and content values can be either strings or integer values as both will be treated as strings. The message is optional, and must be quoted.

Null

assertNull [message] value

Asserts that value is null, or in shell terms, a zero-length string. The value must be a string as an integer value does not translate into a zero-length string. The message is optional, and must be quoted.

assertNotNull [message] value

Asserts that value is not null, or in shell terms, a non-empty string. The value may be a string or an integer as the latter will be parsed as a non-empty string value. The message is optional, and must be quoted.

Truth

assertTrue [message] condition

Asserts that a given shell test condition is true. The condition can be as simple as a shell

Related Skills

View on GitHub
GitHub Stars1.7k
CategoryDevelopment
Updated16h ago
Forks202

Languages

Shell

Security Score

95/100

Audited on Apr 2, 2026

No findings