alcjzk / Webserv

0 stars 0 forks source link

Unit testing & Makefile update #12

Closed alcjzk closed 9 months ago

alcjzk commented 9 months ago

Summary

This PR adds an automated framework for unit-testing, as well as a completely redone Makefile to support it, with some additional quality-of-life features.

Makefile changes

The Makefile now has 2 separate build profiles: a release build and a debug build. Both targets compile into their own object files and resulting binaries. This means there is no need to rebuild the entire project when switching between debug/releases builds. Each resulting binary goes inside the bin folder, with the exception of the release build being copied as webserv under the workspace root, when the build target is webserv or all (default).

The primary differences in the debug build are the following CFLAGS:

Release build in contrast sets flags as:

Primary rules of the Makefile are now as follows:

Unit testing

The project now contains a basic python script that finds all test functions inside the project and generates a main in order to run those tests. The make rule make test or make t as a shortcut, can be used to build and run all tests in the project. This rule is also executed in the PR workflow build job.

Small warning: The python script is very basic and does not do a lot of error checking. If the test build fails, running clang-format has a good chance to fix that, since the script is fairly fragile to bad formatting.

How to write a test?

There's a small working example in Reader.hpp / Reader.cpp. Intended use works as follows:

The test functions should look somewhat like this:

void FooTest::foo_basic_test()
{
    BEGIN // <- defined in testutils, will open a block for catching exceptions

    bool result = Foo::some_function(); // <- use functions from the class you're testing

    EXPECT(result == true); // <- defined in testutils, insert any boolean expression you expect
    // to eval as true. If the expectation above evaluates to false, the test fails and outputs the 
    // name of this function + file + linenumber

    EXPECT(true); // <- you can place multiple expectations in the same test

    try { /* Some function that SHOULD throw an exception */ }
    catch (/*exception type*/)
    {
        // If the function you're testing should throw an exception, you can catch it and return to 
        // pass the test
        return;
    }
    EXPECT(false); // This will fail the test if the catch block wasn't reached

    END // <- defined in testutils, any exceptions that were not caught will fail the test here
}

Note also: Multiple test classes in one file are not supported!

alcjzk commented 9 months ago

@lsileoni @lanximaomao This one doesn't need too thorough of a review, since the changes are mainly testing related. Do let me know however if you have anything in the functionality you think should be changed / if you find any clear issues / have any general questions about how all this works. This pr is also not against master, but stacked on the routing one