### shUnit2 oneTimeSetUp Example Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Override this function to perform one-time setup tasks before any tests are executed. It's useful for common environment preparation like creating temporary directories. ```sh oneTimeSetUp() { export TEST_DIR='/tmp/shunit_test' mkdir -p "$TEST_DIR" } ``` -------------------------------- ### Temporary Directory Structure Setup in Shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Example of using the `oneTimeSetUp` function to create a directory structure within the temporary directory for test setup. ```sh oneTimeSetUp() { WORK_DIR="$SHUNIT_TMPDIR/work" mkdir -p "$WORK_DIR/subdir" } ``` -------------------------------- ### One-Time Setup and Cleanup Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Implement `oneTimeSetUp` and `oneTimeTearDown` for setup and cleanup tasks that should run only once before all tests and after all tests, respectively. ```sh oneTimeSetUp() { SHARED_DIR="${SHUNIT_TMPDIR}/shared" mkdir -p "$SHARED_DIR" } oneTimeTearDown() { rm -rf "$SHARED_DIR" } ``` -------------------------------- ### shUnit2 setUp Example Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Override this function to reset the environment before each test function is executed. It's useful for common environment preparation tasks before each test. ```sh setUp() { # Reset state before each test test_var='' test_file="$TEST_DIR/test_$$_$RANDOM" touch "$test_file" } ``` -------------------------------- ### Isolating Global State with setUp and tearDown Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Shows how to use `setUp()` and `tearDown()` functions to manage and isolate changes to global environment variables like `PATH` and custom exports. `setUp()` is executed before each test, and `tearDown()` after. ```sh #!/bin/sh ORIGINAL_PATH="$PATH" testPathModification() { # setUp() will reset PATH new_path="/custom/bin:$PATH" PATH="$new_path" assertEquals 'PATH modified' "$new_path" "$PATH" } testEnvironmentIsolation() { export CUSTOM_VAR='value1' assertEquals 'var set' 'value1' "$CUSTOM_VAR" } setUp() { # Reset state before each test PATH="$ORIGINAL_PATH" unset CUSTOM_VAR } . ./shunit2 ``` -------------------------------- ### shUnit2 Per-Test Setup and Cleanup Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Use 'setUp()' and 'tearDown()' to prepare and reset the environment before and after each individual test function. This ensures each test runs in a clean, isolated state. ```sh #!/bin/sh TEST_DIR='' oneTimeSetUp() { TEST_DIR="${SHUNIT_TMPDIR}/tests" mkdir -p "$TEST_DIR" } setUp() { # Reset state before each test TEST_FILE="$TEST_DIR/test_$$.txt" rm -f "$TEST_FILE" # Ensure clean state } tearDown() { # Clean up after each test rm -f "$TEST_FILE" } testFirstWrite() { echo "data1" > "$TEST_FILE" assertEquals 'file has data' 'data1' "$(cat '$TEST_FILE')" } testSecondWrite() { # TEST_FILE is fresh (previously deleted by tearDown) echo "data2" > "$TEST_FILE" assertEquals 'file has data' 'data2' "$(cat '$TEST_FILE')" } . ./shunit2 ``` -------------------------------- ### Setup and Cleanup Functions Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Define `setUp` and `tearDown` functions to prepare test environments before each test and clean up afterward. These are executed automatically for each test case. ```sh setUp() { TEST_FILE="$SHUNIT_TMPDIR/test.txt" echo "data" > "$TEST_FILE" } tearDown() { rm -f "$TEST_FILE" } ``` -------------------------------- ### shUnit2 One-Time Setup and Cleanup Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Implement 'oneTimeSetUp()' and 'oneTimeTearDown()' for environment setup and cleanup that should occur only once for the entire test suite. This is ideal for creating and removing global test directories or fixtures. ```sh #!/bin/sh # Global test directory TEST_DIR='' oneTimeSetUp() { # Create a temporary directory for all tests TEST_DIR="${SHUNIT_TMPDIR}/test_suite_$$" mkdir -p "$TEST_DIR" # Create common fixtures echo "config=production" > "$TEST_DIR/config.txt" } oneTimeTearDown() { # Clean up after all tests complete rm -rf "$TEST_DIR" } testReadConfig() { config=$(cat "$TEST_DIR/config.txt") assertEquals 'config correct' 'config=production' "$config" } testWriteLog() { log_file="$TEST_DIR/test.log" echo "test log entry" > "$log_file" assertTrue 'log file created' '[ -f \'$log_file\' ]' } . ./shunit2 ``` -------------------------------- ### Install Core Utilities for shUnit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Install essential Unix utilities like 'coreutils' and 'bc' if they are missing on your system to resolve command not found errors. ```sh # For expr - usually built-in apt-get install coreutils # Debian/Ubuntu yum install coreutils # RedHat/CentOS # For bc apt-get install bc yum install bc ``` -------------------------------- ### Manage Test State with setUp and tearDown Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Utilize `setUp()` and `tearDown()` functions to reset or clean up variables and environment states between tests, preventing global state pollution. ```sh MY_VAR='' setUp() { MY_VAR='' # Reset before each test } tearDown() { unset MY_VAR # Clean up after each test } testOne() { MY_VAR='value1' assertEquals 'test 1' 'value1' "$MY_VAR" } testTwo() { # MY_VAR is empty (reset by setUp) assertEquals 'test 2' '' "$MY_VAR" } ``` -------------------------------- ### File Organization Example Source: https://github.com/kward/shunit2/blob/master/_autodocs/README.md Illustrates the typical directory structure for a shUnit2 project, showing the location of various documentation and configuration files. ```shell output/ ├── README.md (this file) ├── quick-reference.md ├── api-reference.md ├── configuration.md ├── examples.md ├── patterns-and-usage.md ├── internals.md └── troubleshooting.md ``` -------------------------------- ### shUnit2 Test Suite with Setup and Teardown Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md Demonstrates environment initialization and cleanup using one-time and per-test setup/teardown functions. Useful for managing test resources and state. ```shell #!/bin/sh # Test suite with one-time and per-test setup/teardown WORK_DIR='' TEST_FILE='' # One-time setup - called once before all tests oneTimeSetUp() { WORK_DIR="${SHUNIT_TMPDIR}/workspace" mkdir -p "$WORK_DIR" echo "shared data" > "$WORK_DIR/shared.txt" } # One-time teardown - called once after all tests oneTimeTearDown() { rm -rf "$WORK_DIR" } # Per-test setup - called before each test setUp() { TEST_FILE="$WORK_DIR/test_$RANDOM.txt" echo "test content" > "$TEST_FILE" } # Per-test teardown - called after each test tearDown() { rm -f "$TEST_FILE" } testFirstOperation() { # TEST_FILE exists from setUp content=$(cat "$TEST_FILE") assertEquals 'initial content' 'test content' "$content" } testSecondOperation() { # TEST_FILE is fresh (recreated by setUp after previous tearDown) assertTrue 'test file exists' "[ -f '$TEST_FILE' ]" # Modify the file echo "modified" > "$TEST_FILE" content=$(cat "$TEST_FILE") assertEquals 'modified content' 'modified' "$content" } testAccessSharedData() { # Access data from oneTimeSetUp shared=$(cat "$WORK_DIR/shared.txt") assertEquals 'shared data' 'shared data' "$shared" } . ./shunit2 ``` ```shell $ ./setup_teardown_test.sh testFirstOperation testSecondOperation testAccessSharedData Ran 3 tests. OK ``` -------------------------------- ### One-Time Setup Function Source: https://github.com/kward/shunit2/blob/master/README.md Override this function to perform actions once before any tests in the suite run. Useful for initializing a common test environment. ```shell oneTimeSetUp ``` -------------------------------- ### Install Shunit2 with Homebrew Source: https://github.com/kward/shunit2/wiki/Cookbook Use Homebrew to install the shunit2 package on macOS. This is the recommended method for macOS users. ```shell $ brew install shunit2 ``` -------------------------------- ### Per-Test Setup Function Source: https://github.com/kward/shunit2/blob/master/README.md Override this function to perform actions before each individual test runs. Useful for resetting the environment for each test. ```shell setUp ``` -------------------------------- ### Test Shell Script with shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md Demonstrates running shunit2 tests from the command line. This example shows the output when tests pass successfully. ```sh $ ./string_utils_test.sh testToUpper testToLower testIsEmptyTrue testIsEmptyFalse testTrimWhitespace testCountWord testCountWordNotFound Ran 7 tests. OK ``` -------------------------------- ### Shunit2 Integration with GitHub Actions Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Example of setting up Shunit2 tests and publishing JUnit XML results using GitHub Actions. ```yaml - name: Run tests run: | mkdir -p results ./test.sh -- --output-junit-xml=results/test.xml - name: Publish results uses: dorny/test-reporter@v1 with: path: results/test.xml reporter: java-junit ``` -------------------------------- ### Basic shUnit2 Test Structure Source: https://github.com/kward/shunit2/blob/master/README.md This is a minimal example of a shell script using shUnit2. It defines a single test function `testEquality` and loads the shUnit2 library. Ensure the script is run from the `examples` directory or adjust the path to `shunit2` accordingly. ```sh #! /bin/sh # file: examples/equality_test.sh testEquality() { assertEquals 1 1 } # Load shUnit2. . ../shunit2 ``` -------------------------------- ### Install Signal Traps Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md Installs traps for EXIT, INT, and TERM signals to ensure cleanup routines are called upon script termination or interruption. ```sh trap '_shunit_cleanup EXIT' 0 trap '_shunit_cleanup INT' 2 trap '_shunit_cleanup TERM' 15 ``` -------------------------------- ### Example External Test Data File Source: https://github.com/kward/shunit2/wiki/Table-driven-tests This is an example of the content for an external test data file used in table-driven tests. Each line represents a test case with a description, an argument, and the expected output, separated by spaces. ```text test#1 value1 output_one test#2 value2 output_two ``` -------------------------------- ### Shunit2 Integration with Make Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Examples of integrating Shunit2 tests into a Makefile, including running standard tests and generating JUnit XML reports. ```makefile test: ./shunit2_test.sh test-xml: ./shunit2_test.sh -- --output-junit-xml=results/test.xml .PHONY: test test-xml ``` -------------------------------- ### shUnit2 Multi-Shell Test Execution Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md This example shows how to iterate through different shells and execute your test script with each one to ensure cross-shell compatibility. ```sh # Run tests on multiple shells for shell in sh bash dash ksh zsh; do echo "Testing with $shell:" $shell test_script.sh done ``` -------------------------------- ### Loading shUnit2 from System Path Source: https://github.com/kward/shunit2/blob/master/README.md If you are using a distribution-packaged version of shUnit2, you can load it directly using `. shunit2` without specifying a relative or absolute path. This is useful when shUnit2 is installed in a standard system location like `/usr/bin/shunit2`. ```sh # Load shUnit2. . shunit2 ``` -------------------------------- ### Create First Shunit2 Test File Source: https://github.com/kward/shunit2/blob/master/_autodocs/00-START-HERE.txt This is a basic example of a Shunit2 test file. It defines a test function and uses the assertEquals assertion. Ensure the shunit2 script is sourced at the end. ```shell #!/bin/sh testExample() { assertEquals 'message' 1 1 } . ./shunit2 ``` -------------------------------- ### oneTimeSetUp Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md An optional user-defined function called once before any tests are executed. Override this in your test suite to perform one-time setup tasks. If this function returns non-zero, shunit2 will abort execution with a fatal error. ```APIDOC ## oneTimeSetUp ### Description Optional user-defined function called once before any tests are executed. Override this in your test suite to perform one-time setup tasks. ### Purpose Common one-time environment preparation for all tests (e.g., creating temporary directories, setting environment variables). ### Returns Exit code `0` (success) or non-zero (fatal error). ### Example ```sh oneTimeSetUp() { export TEST_DIR='/tmp/shunit_test' mkdir -p "$TEST_DIR" } ``` ### Notes If this function is defined and returns non-zero, shunit2 will abort execution with a fatal error. ``` -------------------------------- ### Basic Shunit2 Homebrew Test Source: https://github.com/kward/shunit2/wiki/Cookbook Create a simple test file using shunit2 after installing it via Homebrew. Ensure the shunit2 script is sourced at the end of the test file. ```shell testHomebrew() { assertTrue 0 } . /usr/local/bin/shunit2 ``` -------------------------------- ### Avoiding Expensive Setup in Tests Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Perform expensive operations like file loading once in `oneTimeSetUp` to avoid repeated execution for each test. Use pre-loaded data in subsequent tests. ```sh oneTimeSetUp() { # Expensive operation - runs once for all tests LARGE_DATA=$(cat /large/file.txt) } testDataProcessing() { # Use pre-loaded data result=$(echo "$LARGE_DATA" | grep 'pattern') assertNotNull 'result found' "$result" } ``` -------------------------------- ### setUp Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md An optional user-defined function called before each test function is executed. Override this in your test suite to reset the environment. If this function returns non-zero, shunit2 will abort execution with a fatal error. ```APIDOC ## setUp ### Description Optional user-defined function called before each test function is executed. Override this in your test suite to reset the environment. ### Purpose Common environment preparation tasks before each test (e.g., resetting variables, creating test files). ### Returns Exit code `0` (success) or non-zero (fatal error). ### Example ```sh setUp() { # Reset state before each test test_var='' test_file="$TEST_DIR/test_$$_$RANDOM" touch "$test_file" } ``` ### Notes If this function returns non-zero, shunit2 will abort execution with a fatal error. ``` -------------------------------- ### Shunit2 String Comparison Assertions Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Provides examples of various string comparison assertions including exact match, inequality, null/empty checks, and substring searches. ```shell testStringComparisons() { # Exact equality assertEquals 'exact match' 'hello' 'hello' # Inequality assertNotEquals 'values differ' 'hello' 'goodbye' # Null/empty checks assertNull 'empty string' '' assertNotNull 'has content' 'value' # Substring searches assertContains 'found substring' 'hello world' 'world' assertNotContains 'missing substring' 'hello' 'goodbye' } ``` -------------------------------- ### Specify Tests to Run Source: https://github.com/kward/shunit2/blob/master/_autodocs/configuration.md Run only specific test functions instead of all tests. The specified functions will be run in the order listed. The test must exist or shunit2 will attempt to run it and record a failure. This does not affect `setUp()` and `tearDown()` functions. ```sh test-script.sh -- testOne testTwo otherFunction ``` ```sh shunit2 test-script.sh testOne testTwo otherFunction ``` ```sh ./equality_test.sh -- testEquality testPartyLikeItIs1999 ``` -------------------------------- ### Skip Tests Based on Shell Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Use `startSkipping` and `endSkipping` to conditionally skip tests. This example demonstrates skipping tests that should only run in Bash. ```sh testBashOnly() { [ -z "${BASH_VERSION:-}" ] && startSkipping result=$(( 5 + 3 )) assertEquals 'result' 8 "$result" endSkipping } ``` -------------------------------- ### Configure Custom Test Runner in Shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md Customize test selection by implementing the `suite()` function. This example demonstrates adding tests dynamically, such as retrieving test function names from a database. ```sh suite() { # Custom test selection logic for test_func in $(list_tests_from_database); do suite_addTest "$test_func" done } ``` -------------------------------- ### Basic shUnit2 Test Suite Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md A minimal test suite demonstrating core shUnit2 assertion functions like assertEquals, assertNotEquals, assertTrue, and assertFalse. This is a good starting point for understanding basic test structure. ```shell #!/bin/sh # Basic test suite demonstrating core features # Define test functions testSimpleEquality() { assertEquals 'one equals one' 1 1 } testStringComparison() { assertEquals 'strings match' 'hello' 'hello' } testInequality() { assertNotEquals 'values differ' 'a' 'b' } testTruthValue() { assertTrue 'zero is true' 0 assertTrue 'arithmetic comparison' '[ 5 -gt 3 ]' } testFalseValue() { assertFalse 'one is false' 1 assertFalse 'string equality fails' "[ 'x' = 'y' ]" } # Load and run shUnit2 . ./shunit2 ``` ```shell $ ./basic_test.sh testSimpleEquality testStringComparison testInequality testTruthValue testFalseValue Ran 5 tests. OK ``` -------------------------------- ### shUnit2 tearDown Example Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Override this function to clean up the environment after each test function completes. It's useful for common environment cleanup tasks after each test. ```sh tearDown() { # Clean up after each test rm -f "$test_file" } ``` -------------------------------- ### Verify Test Function Definitions Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Use `grep` to find all lines in your test file that match the pattern for shUnit2 test functions (starting with 'test' followed by alphanumeric characters or underscores). ```sh # Check that test functions are defined grep '^test[A-Za-z0-9_]*() {' test.sh ``` -------------------------------- ### Platform-Specific Test Skipping (Linux/macOS) Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Skip tests based on the operating system. This example demonstrates skipping tests for Linux and macOS. The script must be sourced with '. ./shunit2'. ```sh #!/bin/sh testLinuxFeature() { # Skip on non-Linux systems [ "$(uname -s)" != 'Linux' ] && startSkipping # Test Linux-specific feature assertTrue 'Linux detected' '[ -d /proc ]' endSkipping } testDarwinFeature() { # Skip on non-macOS systems [ "$(uname -s)" != 'Darwin' ] && startSkipping # Test macOS-specific feature assertTrue 'macOS detected' '[ -d /Applications ]' endSkipping } . ./shunit2 ``` -------------------------------- ### shUnit2 test skipping example Source: https://github.com/kward/shunit2/blob/master/README.md A shUnit2 test script that conditionally skips the `add_bash` function test if not running under bash. It uses `startSkipping` to enable skipping. ```sh #! /bin/sh # file: 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. . ../shunit2 ``` -------------------------------- ### Shunit2 Test Execution Loop Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md This loop iterates through each test case, executing setup, the test itself, and teardown functions in isolation. It also records timing information for each test. ```sh for _shunit_test_ in ${__shunit_suite}; do __shunit_testSuccess=${SHUNIT_TRUE} endSkipping # Reset skip state __shunit_startCaseTime=`${__SHUNIT_CMD_DATE_SECONDS}` setUp # Run per-test setup eval ${_shunit_test_} # Execute the test tearDown # Run per-test cleanup __shunit_endCaseTime=`${__SHUNIT_CMD_DATE_SECONDS}` # Record timing and metrics done ``` -------------------------------- ### shUnit2 Test with Failing Assertion Source: https://github.com/kward/shunit2/blob/master/README.md This example extends the basic test by adding a second test function `testPartyLikeItIs1999` which includes an optional message for the assertion. This demonstrates how to provide user-facing messages upon test failure and compare strings. ```sh #! /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 ``` -------------------------------- ### Macro Quoting Example Source: https://github.com/kward/shunit2/blob/master/README.md When using macros like ${_ASSERT_EQUALS_}, all strings must be quoted twice. Single-quotes become single-double-quotes, and vice-versa. This example shows the correct quoting for a message and a null value. ```shell # Normal `assertEquals` call. assertEquals 'some message' 'x' '' ``` ```shell # Macro `_ASSERT_EQUALS_` call. Note the extra quoting around the _message_ and the _null_ value. _ASSERT_EQUALS_ '"some message"' 'x' '""' ``` -------------------------------- ### shUnit2 Start Skipping Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md Sets the internal skip flag to true, indicating that subsequent assertions should be marked as skipped. ```shell startSkipping() { __shunit_skip=${SHUNIT_TRUE} } ``` -------------------------------- ### Setup/Teardown Functions Source: https://github.com/kward/shunit2/blob/master/_autodocs/INDEX.md User-definable functions for setting up and tearing down test environments. ```APIDOC ## oneTimeTearDown ### Description User-defined function called once after all tests in a suite have run. This function can be overridden by the user. ### Usage Define this function in your test file to perform cleanup operations. ``` ```APIDOC ## oneTimeSetUp ### Description User-defined function called once before all tests in a suite begin. This function can be overridden by the user. ### Usage Define this function in your test file to perform initial setup operations. ``` ```APIDOC ## tearDown ### Description User-defined function called after each individual test runs. This function can be overridden by the user. ### Usage Define this function in your test file to perform cleanup operations between tests. ``` ```APIDOC ## setUp ### Description User-defined function called before each individual test runs. This function can be overridden by the user. ### Usage Define this function in your test file to perform setup operations before each test. ``` -------------------------------- ### Running Configuration Parser Tests Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md Demonstrates the execution of the configuration parser test suite. This shows the typical output when all tests pass successfully. ```sh $ ./config_parser_test.sh testParseExistingKey testParseNumericValue testParseNonexistentKey testValidateGoodConfig testParseNonexistentFile Ran 5 tests. OK ``` -------------------------------- ### Clean Up Background Processes Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Ensure background processes started in tests are properly terminated in the `tearDown()` function to prevent tests from hanging. ```sh setUp() { # Start background process sleep 3600 & BG_PID=$! } tearDown() { # Kill background process kill $BG_PID 2>/dev/null wait $BG_PID 2>/dev/null } ``` -------------------------------- ### Shunit2 Test Script Execution (With Arguments) Source: https://github.com/kward/shunit2/wiki/Cookbook Illustrates the output of a Shunit2 test script when executed with command-line arguments, showing that arguments are processed before shunit2. ```console $ ./test_date_cmd.sh a b c ARGC: #:3 1:a 2:b 3:c test_date_cmd Ran 1 test. OK ``` -------------------------------- ### Prepare Release Notes and Version Update Source: https://github.com/kward/shunit2/wiki/Making-a-release Copy the previous release notes and update the version number in the main script file. These changes are then staged and committed. ```bash cp doc/RELEASE_NOTES-2.1.7.md doc/RELEASE_NOTES-2.1.8.md subl doc/RELEASE_NOTES-2.1.8.md subl shunit2 ``` ```bash git add shunit2 doc/RELEASE_NOTES-2.1.8.md git commit -m 'Prepping for the 2.1.8 release.' git push ``` -------------------------------- ### Standard Indentation and Conditional Block Source: https://github.com/kward/shunit2/wiki/Coding-standards Code blocks should be indented with two spaces. This example shows a standard if/then conditional block structure. ```shell if [ -z 'some string' ]; then someFunction fi ``` -------------------------------- ### Add Test to Suite Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Use suite_addTest within the suite function to add individual tests. The function name does not need to start with 'test'. ```sh suite() { suite_addTest 'testOne' suite_addTest 'testTwo' suite_addTest 'customTestFunction' # Not required to start with 'test' } ``` -------------------------------- ### Correct Test Function Naming Convention Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Ensure test functions start with 'test' (lowercase) for shUnit2 to discover them. This pattern matching is case-sensitive. ```sh # Wrong Test_myfunction() { } myTest() { } # Correct testMyFunction() { } test_my_function() { } ``` -------------------------------- ### zsh Setup: Command-line invocation with shwordsplit Source: https://github.com/kward/shunit2/blob/master/_autodocs/configuration.md Execute your test script using 'zsh -o shwordsplit' to enable the 'shwordsplit' option for zsh compatibility. ```sh zsh -o shwordsplit -- test-script.sh ``` -------------------------------- ### Test Configuration File Parsing with shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md Tests a shell script designed to parse key-value pairs from a configuration file and validate its format. The `oneTimeSetUp` function creates a temporary configuration file for testing. ```sh #!/bin/sh . ./config_parser.sh CONFIG_FILE='' oneTimeSetUp() { CONFIG_FILE="$SHUNIT_TMPDIR/test.conf" cat > "$CONFIG_FILE" </dev/null) [ $? -ne 0 ] assertTrue 'file does not exist' 0 } . ./shunit2 ``` -------------------------------- ### Override shUnit2 Echo Command Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md If 'echo -e' is problematic, you can override the command shUnit2 uses for escape sequences by setting SHUNIT_CMD_ECHO_ESC, for example, to 'printf'. ```sh # Use printf instead of echo export SHUNIT_CMD_ECHO_ESC='printf' ``` -------------------------------- ### Basic shUnit2 Test Structure Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Demonstrates the fundamental structure of an shUnit2 test file, including how to define test functions and load the shUnit2 framework to execute tests. ```sh #!/bin/sh # Test functions start with 'test' testExample() { assertEquals 'message' expected actual } # Load shUnit2 (triggers discovery and execution) . ./shunit2 ``` -------------------------------- ### shUnit2 Automatic Test Discovery Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Use this pattern when tests can be named with a 'test' prefix. shUnit2 automatically finds and runs all functions starting with 'test'. ```sh #!/bin/sh # Define test functions - any function starting with 'test' is automatically discovered testFirstFeature() { assertEquals 'values match' 1 1 } testSecondFeature() { assertTrue 'condition is true' '[ 1 -eq 1 ]' } testThirdFeature() { assertContains 'substring found' 'hello world' 'world' } # Load shUnit2 - triggers automatic test discovery and execution . ./shunit2 ``` -------------------------------- ### JUnit XML Test Report Structure Source: https://github.com/kward/shunit2/blob/master/README.md Example structure of a JUnit XML test report generated by Shunit2. This format is commonly used by CI tools. ```xml ``` -------------------------------- ### Run Shunit2 Homebrew Test Source: https://github.com/kward/shunit2/wiki/Cookbook Execute a shunit2 test file from the command line. The output shows the test name and the result. ```shell $ sh homebrew_test.sh testHomebrew Ran 1 test. OK ``` -------------------------------- ### Shunit2 Temporary Directory Creation Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md This function creates a temporary directory for test isolation. It prioritizes using the standard 'mktemp' command and falls back to manual creation if 'mktemp' is unavailable. The created directory has restrictive permissions. ```sh _shunit_mktempDir() { # Try standard mktemp first if ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ); then return fi # Fall back to manual creation _shunit_tmpDir_="${TMPDIR:-/tmp}/shunit.${_shunit_random_}" umask 077 && command mkdir "${_shunit_tmpDir_}" } ``` -------------------------------- ### Start Skipping Assertions Source: https://github.com/kward/shunit2/blob/master/README.md Call this function to make subsequent assert and fail calls have no effect. Skipped assertions are recorded but do not alter the overall pass/fail count. ```shell startSkipping ``` -------------------------------- ### Shunit2 File System Assertions Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Illustrates assertions for file system operations, including checking file existence, readability, writability, content, and directory operations. ```shell testFileOperations() { file="$SHUNIT_TMPDIR/test.txt" # File creation and content echo "content" > "$file" assertTrue 'file exists' "[ -f '$file' ]" assertTrue 'file is readable' "[ -r '$file' ]" assertTrue 'file is writable' "[ -w '$file' ]" assertEquals 'file content' 'content' "$(cat '$file')" # File properties assertTrue 'file is regular' "[ -f '$file' ]" assertTrue 'file has size' "[ -s '$file' ]" # Directory operations dir="$SHUNIT_TMPDIR/subdir" mkdir "$dir" assertTrue 'directory exists' "[ -d '$dir' ]" assertTrue 'directory is readable' "[ -r '$dir' ]" } ``` -------------------------------- ### Specify Tests to Run from Command Line Source: https://github.com/kward/shunit2/blob/master/README.md Override the default test suite by providing test function names as arguments after the '--' marker. Tests are executed in the order they are specified. ```bash test-script.sh -- testOne testTwo otherFunction ``` ```bash shunit2 test-script.sh testOne testTwo otherFunction ``` -------------------------------- ### Basic Shell Table-Driven Test with Here Document Source: https://github.com/kward/shunit2/wiki/Table-driven-tests This snippet demonstrates a basic table-driven test structure using a here document. It reads test descriptions, arguments, and expected outputs, then asserts the function's return code and output. Note that values with spaces must be placed in the last column to be read correctly. ```sh while read desc arg want; do got=$(fn ${arg}) rtrn=$? assertTrue "${desc}: fn() unexpected error; return ${rtrn}" ${rtrn} assertEquals "${desc}: fn() = ${got}, want ${want}" "${got}" "${want}" done </dev/null 2>&1 || fail "$msg" } ``` -------------------------------- ### Function Documentation Header Source: https://github.com/kward/shunit2/blob/master/CONTRIBUTING.md Precede each function with a header detailing its purpose, arguments, output, and return values. This improves code comprehension and usability. ```shell # Records a test failure, stating two values were not equal. # # This is functionally equivalent to calling failNotEquals(). # # Args: # message: string: failure message [optional] # expected: string: expected value # actual: string: actual value # Returns: # integer: success (TRUE/FALSE/ERROR constant) ``` -------------------------------- ### Use SHUNIT_TMPDIR for Test Files Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Always use the `$SHUNIT_TMPDIR` variable for creating temporary files in tests to ensure proper permissions and automatic cleanup. ```sh # Wrong - may not have permissions testFile() { file="/etc/test_$$.txt" # Will fail echo "data" > "$file" } # Correct - uses allocated temp directory testFile() { file="$SHUNIT_TMPDIR/test.txt" echo "data" > "$file" # Automatically cleaned up } ``` ```sh ls -ld "$SHUNIT_TMPDIR" # Should show: drwx------ (mode 700, read/write/execute for owner only) ``` -------------------------------- ### shUnit2 oneTimeTearDown Example Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Override this function to perform one-time cleanup tasks after all tests are completed. It's useful for common environment cleanup like removing temporary directories. ```sh oneTimeTearDown() { rm -rf "$TEST_DIR" } ``` -------------------------------- ### Tag and Push Release Source: https://github.com/kward/shunit2/wiki/Making-a-release Create a signed tag for the new release in the local repository and then push all tags to the origin. This marks the release point in the version history. ```bash git tag -s v2.1.8 -m 'Signed 2.1.8 tag.' git push origin --tags ``` -------------------------------- ### zsh Setup: Invoke zsh with -y flag Source: https://github.com/kward/shunit2/blob/master/_autodocs/configuration.md Alternatively, invoke zsh with the '-y' flag to enable 'shwordsplit' automatically. Ensure 'SHUNIT_PARENT' is set to '$0' for proper shunit2 operation. ```sh #!/bin/zsh -y # Invoked with -y flag to enable shwordsplit testExample() { assertEquals 'values match' 1 1 } SHUNIT_PARENT="$0" . ./shunit2 ``` -------------------------------- ### Make Integration for Shunit2 Tests Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Define Make targets to run Shunit2 tests with different verbosity and output options. Ensure the shunit2_test.sh script is executable. ```makefile test: ./shunit2_test.sh test-verbose: SHUNIT_COLOR=always ./shunit2_test.sh test-xml: mkdir -p results ./shunit2_test.sh -- --output-junit-xml=results/test.xml .PHONY: test test-verbose test-xml ``` -------------------------------- ### Display shunit2 Version Source: https://github.com/kward/shunit2/blob/master/_autodocs/configuration.md Shows how to display the current shunit2 version using the SHUNIT_VERSION environment variable. This variable is read-only and informational. ```shell echo "Using shUnit2 version: $SHUNIT_VERSION" ``` -------------------------------- ### Assert Equals Macro Usage Source: https://github.com/kward/shunit2/blob/master/_autodocs/internals.md Example of using the line number macro within another macro for assertion functions. It demonstrates how to pass the current line number to assertion functions. ```sh _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' ``` -------------------------------- ### Conditional Test Execution with shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/examples.md Illustrates how to conditionally skip tests based on the shell environment (e.g., bash-specific features) or system conditions (e.g., command availability like 'jq'). Use `startSkipping` and `endSkipping` for conditional logic. ```sh #!/bin/sh testAlwaysRuns() { assertEquals 'all shells support this' 1 1 } testBashOnly() { # Skip this test if not running bash [ -z "${BASH_VERSION:-}" ] && startSkipping # Bash-specific features array=(1 2 3) assertEquals 'array length' 3 "${#array[@]}" endSkipping } testNonBashOnly() { # Skip if running bash [ -n "${BASH_VERSION:-}" ] && startSkipping # POSIX-only features assertTrue 'non-bash shell' 0 endSkipping } testLinuxOnly() { # Skip on non-Linux systems [ "$(uname -s)" = 'Linux' ] || startSkipping assertTrue 'running on Linux' '[ -d /proc ]' endSkipping } testWithCommand() { # Skip if 'jq' is not installed command -v jq >/dev/null 2>&1 || startSkipping 'jq not available' result=$(echo '{"key":"value"}' | jq .key) assertEquals 'jq parsing' '"value"' "$result" endSkipping } . ./shunit2 ``` -------------------------------- ### Enable Shell Tracing with set -x Source: https://github.com/kward/shunit2/blob/master/_autodocs/troubleshooting.md Use `set -x` to enable shell tracing, which prints each command before it's executed. This is useful for understanding the flow of your test script. Remember to disable it with `set +x` when done. ```sh # Use set -x for shell tracing set -x . ./test.sh set +x ``` -------------------------------- ### Using shunit2 Constants Source: https://github.com/kward/shunit2/blob/master/_autodocs/api-reference.md Demonstrates how to use shunit2's predefined constants like SHUNIT_TRUE, SHUNIT_FALSE, SHUNIT_ERROR, and SHUNIT_TMPDIR in shell scripts. The SHUNIT_TMPDIR constant provides a path to a temporary directory that is automatically cleaned up. ```sh testConstants() { # Check return values assertTrue 'SHUNIT_TRUE should be 0' "[ ${SHUNIT_TRUE} -eq 0 ]" assertTrue 'SHUNIT_FALSE should be 1' "[ ${SHUNIT_FALSE} -eq 1 ]" assertTrue 'SHUNIT_ERROR should be 2' "[ ${SHUNIT_ERROR} -eq 2 ]" # Use temporary directory test_file="${SHUNIT_TMPDIR}/test.txt" echo 'test' > "$test_file" assertTrue 'can write to SHUNIT_TMPDIR' "[ -f '$test_file' ]" } ``` -------------------------------- ### Shell Function to Square a Number Source: https://github.com/kward/shunit2/wiki/Table-driven-tests Defines a simple shell function named 'square' that calculates the square of its input using the 'expr' command. This function is used as an example for demonstrating testing techniques. ```shell square() { expr $1 \* $1; } ``` -------------------------------- ### Test with Manual Temporary File Cleanup (Avoid) Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Illustrates an anti-pattern where temporary files are created in `/tmp` and require manual cleanup using `rm -f`. This approach is error-prone as developers might forget to include the cleanup step. ```sh #!/bin/sh testWithTempFiles() { # Manual cleanup is error-prone temp_file="/tmp/test_$$_$RANDOM.txt" echo "test data" > "$temp_file" assertEquals 'file content' 'test data' "$(cat '$temp_file')" rm -f "$temp_file" # Must remember to clean up } ``` -------------------------------- ### Writing to Temporary Directory in Shunit2 Source: https://github.com/kward/shunit2/blob/master/_autodocs/quick-reference.md Demonstrates writing to a file within the temporary directory provided by Shunit2 and asserting its content. The temporary file is automatically cleaned up after the test. ```sh testFileOp() { file="$SHUNIT_TMPDIR/data.txt" echo "test" > "$file" assertEquals 'content' 'test' "$(cat '$file')" # File automatically cleaned up } ``` -------------------------------- ### Assert Falsiness with assertFalse Source: https://github.com/kward/shunit2/blob/master/README.md Use to assert that a shell test condition evaluates to false. This can be a simple false value (1) or a complex shell conditional expression. Refer to assertTrue for examples of complex expressions. ```shell assertFalse [message] condition ``` -------------------------------- ### zsh Setup: Set shwordsplit in Test Script Source: https://github.com/kward/shunit2/blob/master/_autodocs/configuration.md For zsh compatibility, enable 'shwordsplit' within the test script and set 'SHUNIT_PARENT' to '$0'. This is one method to ensure shunit2 functions correctly in a zsh environment. ```sh #!/bin/zsh setopt shwordsplit testExample() { assertEquals 'values match' 1 1 } SHUNIT_PARENT="$0" # Required for zsh . ./shunit2 ``` -------------------------------- ### Basic Test Function Output Source: https://github.com/kward/shunit2/blob/master/_autodocs/patterns-and-usage.md Shows the default output where each test function name is printed as it runs, followed by a summary. ```shell testOne testTwo testThree Ran 3 tests. OK ``` -------------------------------- ### Shunit2 Test Script Execution (No Arguments) Source: https://github.com/kward/shunit2/wiki/Cookbook Shows the output of a Shunit2 test script when executed without any command-line arguments. ```console $ ./test_date_cmd.sh test_date_cmd Ran 1 test. OK ``` -------------------------------- ### Pass Arguments to Shunit2 Test Script Source: https://github.com/kward/shunit2/wiki/Cookbook Demonstrates how to pass command-line arguments to a Shunit2 test script. Ensure all arguments are shifted off the stack before calling shunit2. ```sh #!/bin/bash # test_date_cmd.sh # Echo any provided arguments. [ $# -gt 0 ] && echo "ARGC: $# 1:$1 2:$2 3:$3" test_date_cmd() { ( date '+%a' >/dev/null 2>&1 ) local rtrn=$? assertTrue "unexpected date error; ${rtrn}" ${rtrn} } # Eat all command-line arguments before calling shunit2. shift $# . ~/lib/sh/shunit2 ``` -------------------------------- ### Shell Workaround for Values with Spaces in Table Data Source: https://github.com/kward/shunit2/wiki/Table-driven-tests This example illustrates a workaround for the `read` command's limitation with spaces in values. By placing values containing spaces in the last column of the here document, they are all captured by the last variable (`b` in this case). ```sh $ read a b <