Unity Test Documentation

repository·master·Indexed 26 days ago

https://github.com/throwtheswitch/unity

A lightweight unit testing framework written in C and optimized for embedded systems and microcontrollers. It features a wide range of assertions for integers, floating point, strings, and memory, as well as optional add-ons for BDD-style test structuring (GIVEN, WHEN, THEN), test groups via Unity Fixtures, and memory leak detection and tracking.

Tokens
11.9K
Snippets
20
Records
71
Agent score
88%

What's inside Unity Test

  1. Understand Unity Assertion Conventions

    master

    Unity assertions follow a standard parameter order to ensure consistency across different types. The general pattern is:

    TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )

    • actual: The value being tested. This is the only parameter present in all assertion variants.
    • modifiers: Optional masks, ranges, bit flag specifiers, or floating point deltas.
    • expected: The value you expect the actual value to match. This is optional for assertions that only require an actual parameter (e.g., null checks).
    • size/count: Used for string lengths, number of array elements, etc.
  2. Write high-quality commit messages

    master

    Follow these rules for commit messages to ensure compatibility with git tools:

    1. Separate the subject from the body with a blank line.
    2. Limit the subject line to 50 characters.
    3. Capitalize the subject line.
    4. Do not end the subject line with a period.
    5. Wrap the body at approximately 72 characters.
    6. Use the body to explain why the change is being made, not what or how (the code handles that).
    7. Prefix the title with the relevant component name or emoji (e.g., [Docs] Fix typo).

    Example structure:

    :palm_tree: Summary of Amazing Feature Here
    
    Add a more detailed explanation here, if necessary. Possibly give 
    some background about the issue being fixed, etc. The body of the 
    commit message can be several paragraphs.
    
    Explain the problem that this commit is solving. Focus on why you
    are making this change as opposed to how or what.
    
     - Bullet points are awesome, too
    
    Resolves: #123
  3. Submit a pull request

    master

    For non-trivial changes, it is recommended to open an issue first to discuss your approach with maintainers.

    Best Practices for PRs

    • Small and isolated: Submit one PR per bug fix or feature. Do not include unrelated refactors or reformatting.
    • Clarity: Prioritize readable, concise code over cleverness. Add comments if logic is not obvious.
    • Consistency: Follow existing coding styles and conventions (use spaces, not tabs).
    • Testing: Include unit tests following existing patterns and update example projects if applicable.
    • Documentation: Update code doc comments, guides, and the CHANGELOG.
    • CHANGELOG Format: Include the issue number and your GitHub username (e.g., - Fixed crash in profile view. #123 @jessesquires).
    • Workflow: Branch from and submit to the repo's default branch (usually main). Resolve merge conflicts and promptly fix any CI failures.
  4. Follow the ThrowTheSwitch.org Ruby Coding Standard

    master

    When writing Ruby code for this project, follow these stylistic preferences:

    Whitespace

    • Use spaces for indentation.
    • Use 2 spaces per indent level.
    • For wrapped lines, indent further to align with columns.

    Naming and Case

    EntityCasing Style
    Filesall_lower_case_with_underscores
    Variablesall_lower_case_with_underscores
    Classes & ModulesCamelCase
    Functionsall_lower_case_with_underscores
    ConstantsALL_UPPER_CASE_WITH_UNDERSCORES
  5. Enable memory tracking in Unity

    master

    To track malloc and free calls to detect memory leaks, include unity.h and unity_memory.h.

    Note: This module requires overriding standard library functions via defines. It is most effective when a single unit is responsible for both allocation and deallocation. If memory management is asymmetric across the system, tests may report false failures. For full system memory tracking, use a dedicated runtime tool.

  6. Follow coding style and linting guidelines

    master

    Consistency with the existing codebase is mandatory. Follow the established style, formatting, and naming conventions of the files you modify. For example, if the project uses underscore prefixes for private properties (e.g., _property) or camelCase for methods (e.g., myMethod), you must adhere to those patterns.

    Linting is enforced using the following tools:

  7. Use BDD macros to structure test scenarios

    master

    The Unity BDD feature provides macros to structure test scenarios into descriptive phases: GIVEN, WHEN, and THEN. These macros are used for documentation and descriptive purposes only and do not add functional logic to the tests. They help organize the setup, action, and assertion phases of a test.

    GIVEN("a valid input") {
        // Test setup and context
        // ...
    
        WHEN("the input is processed") {
            // Perform the action
            // ...
    
            THEN("the expected outcome occurs") {
                // Assert the outcome
                // ...
            }
        }
    }
  8. Aggregate test results with `unity_test_summary.rb`

    master

    The unity_test_summary.rb script aggregates results from multiple test files into a single summary report. It looks for files ending in .testpass and .testfail in a specified directory.

    Usage:

    1. Basic usage: ruby unity_test_summary.rb build/test/

    2. With a root path (for relative path resolution): ruby unity_test_summary.rb build/test/ ~/projects/myproject/

    Output Format: The script prints a summary including:

    • A list of ignored tests.
    • A list of failed tests (including file, line, test name, and expected vs actual).
    • An overall summary (Total tests, total failures, total ignored).
    ruby unity_test_summary.rb build/test/
  9. Create a Unity test file

    master

    Unity test files are C files that typically correspond to a single C module. To create a test file:

    1. Include unity.h and the header file for the module you are testing.
    2. Define void setUp(void) to run code before every test.
    3. Define void tearDown(void) to run code after every test.
    4. Define test functions. While not strictly required, it is recommended to prefix test functions with test_ or spec_ for compatibility with automated scripts.
    5. Implement a main() function to execute the tests using UNITY_BEGIN(), RUN_TEST(), and UNITY_END().

    Note: If you use the generate_test_runner.rb script, you do not need to manually write the main() function.

    #include "unity.h"
    #include "file_to_test.h"
    
    void setUp(void) {
        // set stuff up here
    }
    
    void tearDown(void) {
        // clean stuff up here
    }
    
    void test_function_should_doBlahAndBlah(void) {
        //test stuff
    }
    
    void test_function_should_doAlsoDoBlah(void) {
        //more test stuff
    }
    
    // not needed when using generate_test_runner.rb
    int main(void) {
        UNITY_BEGIN();
        RUN_TEST(test_function_should_doBlahAndBlah);
        RUN_TEST(test_function_should_doAlsoDoBlah);
        return UNITY_END();
    }
  10. Follow the ThrowTheSwitch.org C/C++ Coding Standard

    master

    When contributing to ThrowTheSwitch projects, follow these stylistic preferences for C and C++ code to ensure consistency:

    Whitespace and Indentation

    • Use spaces for indentation.
    • Use 4 spaces per indent level.
    • For wrapped lines (macros, function arguments), indent further to align with columns.

    Braces

    • Place the left brace on a new line after the declaration.
    • Place the right brace on a new line directly below the corresponding left brace.
    • Indent the content between braces by one level.
    • Always use braces, even for single-line blocks (e.g., inside while or if).

    Comments

    • Use old-school C block comments (/* ... */) to ensure compatibility with older embedded compilers.
        if (stuff_happened)
        {
            do_something();
        }
    
        while (blah)
        {
            // Even if only one line, we use braces.
        }
  11. Handle non-standard integer sizes on idiosyncratic targets

    master

    When working on microcontrollers with non-standard integer sizes (e.g., 12-bit or 24-bit integers), Unity may require manual configuration to ensure correct behavior.

    Best Practices:

    1. Type Detection: When setting up Unity for a new target, prioritize using macros for automatic type detection if the compiler supports them.
    2. Manual Configuration: If automatic detection fails, manually configure Unity's integer types to match your target.
    3. Handling Odd Sizes: If you encounter an odd size like a 24-bit int, the simplest approach is to configure Unity to use the next standard size up (e.g., 32-bit integers).

    Caveats for Up-sized Integers:

    • Error Reporting: When Unity displays errors, it will pad the upper unused bits with zeros.
    • Signed Operations: Be cautious with assertions performing signed operations, such as TEST_ASSERT_INT_WITHIN, as they may wrap at the wrong bit position and cause false failures. In these cases, fall back to a basic TEST_ASSERT and perform the arithmetic manually.