Testing

Test organization

JavaScript solutions use separate projects to host test code, irrespective of the test framework being used (Jest, Mocha, etc.) and the type of tests (unit or integration) being written. The test code therefore lives in a separate assembly than the application or library code being tested. In C, developers use a third party tool called CUnit for testing.

See also:

Running tests

CUnit supports running all tests in all registered suites, but individual tests or suites can also be run. During each run, the framework keeps track of the number of suites, tests, and assertions run, passed, and failed. Note that the results are cleared each time a test run is initiated (even if it fails).

For more information, see "Running Tests in CUnit".

Output in Tests

For very complex integration or end-to-end test, developers sometimes log what's happening during a test. The actual way they do this varies with each test framework in C.

Assertions

JavaScript users have multiple ways to assert, depending on the framework being used. For example, an assertion in Jest might look like:

test('something has the right length', () => {
    let value = "something";
    expect(value.length).toBe(9);
});

An example that only uses vanilla JavaScript:

function somethingIsTheRightLength() {
    let value = "something";
    console.assert(value.length === 9);
}

somethingIsTheRightLength();

C does not require a separate framework like CUnit for asserting.

Below is an example:

#include <assert.h>
#include <string.h>

int main() {
    void test_something_is_the_right_length() {
        const char *value = "something";
        assert(strlen(value) == 9);
    }

    test_something_is_the_right_length(); // Call the test function
    return 0;
}

The standard library does not offer anything in the direction of data-driven tests.

Mocking

There are libraries for C too, like umock_c, that can help with mocking. However, it is also possible to use conditional compilation.

The example below shows mocking of a stand-alone function var_os and returns the value of an environment variable. It conditionally imports a mocked version of the var_os function:

#include <stdio.h>

#ifdef TEST
    #define var_os var_os_mock
    char* var_os_mock() {
        return "Mocked Value";
    }
#else
    char* var_os() {
        return "Actual Value";
    }
#endif

void get_env() {
    char* value = var_os();
    printf("Environment Variable Value: %s\n", value);
}

int main() {
    #ifndef TEST
        get_env();
    #endif

    return 0;
}

Code coverage

There is sophisticated tooling for JavaScript when it comes to analyzing test code coverage, such as Jest.

In C, one can implement code coverage functionalities by utilizing tools like gcov or LLVM's coverage tools. These tools can help collect test code coverage data in C programs. By incorporating these tools into the C codebase, developers can achieve code coverage analysis.