LuaUnit Documentation

repository·main·Indexed 20 days ago

https://github.com/bluebird75/luaunit

An xUnit-style unit-testing framework for Lua that supports multiple output formats including Text, TAP, and JUnit for CI integration. It provides a standalone assertion library, automatic test discovery, and support for test lifecycle management via setUp and tearDown functions. Users can control test execution through a command-line interface or programmatically using the LuaUnit runner object to configure verbosity, test patterns, and execution order.

Tokens
11.1K
Snippets
44
Records
57
Agent score
69%

What's inside LuaUnit

  1. Use setUp and tearDown in test suites

    main

    When executing tests contained within a table (a test suite), you can use lifecycle methods to manage test state:

    • setUp(): Called immediately before each individual test execution. If setUp() fails or encounters an error, the test itself will not be executed, and the failure/error will be reported in the suite.
    • tearDown(): Called immediately after each individual test execution. This runs even if the test failed or if setUp() encountered an error. Any failure or error during tearDown() will be reported in the suite.
  2. How LuaUnit compares tables with table keys

    main

    When comparing tables that use other tables as keys, LuaUnit performs a reference check on the keys rather than just checking the content of the keys.

    Even if two key-tables have identical content, they are considered different keys if they are different objects in memory. Consequently, two parent tables containing these 'identical' key-tables will be considered unequal by lu.assertEquals.

    local lu = require('luaunit')
    
    local t1 = { 1, 2 }
    local t2 = { 1, 2 }
    
    -- These are equal because they have the same content
    lu.assertEquals(t1, t2)
    
    -- Using tables as keys
    local t3 = { t1 = 'a' }
    local t4 = { t2 = 'a' }
    
    -- This fails because t1 and t2 are different table references,
    -- even though their content is identical.
    lu.assertEquals(t3, t4)
  3. Use LuaUnit as an assertion library

    main
    Beyond its role as a test runner, LuaUnit can be used as a standalone assertion library to validate logic within a running program. It also provides a pretty stringifier that converts any type (including complex, nested, or recursive tables) into a formatted string.
  4. Use setUp and tearDown for test lifecycle management

    main

    When using test tables, you can define setUp() and tearDown() functions. These are executed before and after every individual test in that table, respectively. They are ideal for preparing resources (like files or database connections) and cleaning up the environment.

    Note:

    • Errors occurring in setUp() or tearDown() are reported as errors, not failures.
    • For compatibility with other frameworks, you may also use setup(), SetUp(), Setup(), teardown(), or TearDown().
    TestLogger = {}
    
    function TestLogger:setUp()
        -- Prepare environment
        self.fname = 'mytmplog.log'
        os.remove(self.fname)
    end
    
    function TestLogger:testLoggerCreatesFile()
        initLog(self.fname)
        log('toto')
        f = io.open(self.fname, 'r')
        lu.assertNotNil(f)
        f:close()
    end
    
    function TestLogger:tearDown()
        -- Cleanup environment
        os.remove(self.fname)
    end
  5. How LuaUnit collects and executes tests

    main

    LuaUnit follows a specific lifecycle for discovering and running tests:

    1. Test Collection

    LuaUnit determines which tests to run based on the following priority:

    • Explicit List: If you provide a specific list of tests via the command line or as arguments to runSuite() or runSuiteByInstances(), only those tests are used.
    • Automatic Discovery: If no list is provided, LuaUnit searches the global namespace (_G) for names starting with test or Test (that are functions or tables).
    • Table Scanning: It then scans all discovered tables for functions starting with test or Test and adds them to the list.
    • Filtering: Include and exclude patterns are applied to the resulting list.
    • Ordering: If shuffling is enabled, the list is randomized; otherwise, it is sorted alphabetically.

    2. Test Execution

    Each test is executed within a protected call. The outcome is categorized as follows:

    • Success: The test completes without assertion failures or errors.
    • Failure: A LuaUnit assertion (e.g., assertEquals) fails.
    • Error: A Lua error occurs during the test execution.

    Both failures and errors are reported at the end of the execution process.

  6. Group tests using tables

    main

    To organize large test suites, group related tests into tables. The table name must start with Test or test. Test functions within these tables should be defined using the colon syntax (function TableName:testName) to ensure they have access to the table context.

    TestAdd = {}
    
    function TestAdd:testAddPositive()
        lu.assertEquals(add(1,1), 2)
    end
    
    function TestAdd:testAddZero()
        lu.assertEquals(add(1,0), 0)
    end
  7. Update functional test reference files

    main

    If you intentionally change LuaUnit's output, you must update the reference files in test/ref. The run_functional_tests.lua script provides a --update option.

    Warning: Using --update without an argument overwrites all reference output. This is generally discouraged.

    Instead, pass specific subset identifiers to update only the relevant files:

    • TestXml: XML output of test_with_xml
    • ExampleXml: XML output of example_with_luaunit
    • ExampleTap: TAP output of example_with_luaunit
    • ExampleText: text output of example_with_luaunit
    • ExampleNil: nil output of example_with_luaunit
    • ErrFailPassText: text output of test_with_err_fail_pass
    • ErrFailPassTap: TAP output of test_with_err_fail_pass
    • ErrFailPassXml: XML output of test_with_err_fail_pass
    • StopOnError: errFailPassTextStopOnError-1.txt, -2.txt, -3.txt, -4.txt
    # Example: update specific error/fail/pass outputs
    $ lua run_functional_tests.lua --update ErrFailPassXml ErrFailPassTap ErrFailPassText
  8. Process for releasing a new version of LuaUnit

    main

    Follow these steps to release a new version:

    1. Prepare Code: Update functionality and update version numbers in luaunit.lua and doit.py.
    2. Verify Tests: Run doit.py runtests.
      • Tests should fail initially due to the version change in XML outputs.
      • Use WinMerge to compare test/ and ref/ directories.
      • Update ref/*.xml files by updating only the version number.
      • Verify functional tests pass.
    3. Documentation: Update examples/ and README.rst with release info.
    4. Packaging:
      • Create a branch LUAUNIT_VX_X.
      • GitHub: Run doit.py packageit, verify contents (docs, examples, tests), and merge to master.
      • LuaRocks: Rename packaging/luaunit-*.rockspec to the new version, run doit.py buildrock, upload to LuaRocks, and verify with luarocks install luaunit.
    5. Finalize: Create a GitHub release, upload archives, and tag the result.
  9. Use the NIL output format

    main

    The nil format suppresses all output during test execution. The only way to determine if tests passed or failed is by checking the command's exit code. This mode is primarily used for LuaUnit's internal validation.

    lua my_test_suite_with_failures.lua -o nil --verbose
  10. Use the TEXT output format

    main

    The TEXT format is the default output for LuaUnit. It provides a compact summary of test results inspired by Python's unittest library.

    • Compact mode (default): Prints a single character per test: . for success, F for failure, and E for error. A summary of failures/errors and a final tally are provided at the end.
    • Verbose mode (--verbose): Prints the start time, one line per test (ending in Ok, FAIL, or ERROR), and a detailed summary of failures/errors. This is useful when tests produce debug output that needs to be aligned with the test results.
    # Default compact output
    lua my_test_suite.lua
    
    # Verbose output
    lua my_test_suite_with_failures.lua --verbose
  11. Install LuaUnit via LuaRocks

    main

    You can install LuaUnit using the LuaRocks package manager. This requires LuaRocks version 2.4.4 or higher to ensure compatibility with GitHub HTTPS downloading.

    # Use LuaRocks to install the module
    luarocks install bluebird75/luaunit