Cpp unit testing framework

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

A simple single header C++17 unit test framework

License

drleq/CppUnitTestFramework

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

A single header C++17 unit test framework with a focus on simplicity and quick setup. It should compile with any C++17 compliant compiler without any additional source or binary dependencies. Platform specific operations are avoided.

  1. Copy (or clone) the header to your local codebase.
  2. Create an entry-point file with the following contents to generate a main function:
#define GENERATE_UNIT_TEST_MAIN #include "CppUnitTestFramework.hpp"

#include «CppUnitTestFramework.hpp« namespace < struct MyFixture < . >; > TEST_CASE(MyFixture, Test1) < . >TEST_CASE(MyFixture, Test2)

The default main function supports a small number of command line options:

Usage: [] Cpp unit testing framework Cpp unit testing framework . -h, --help, -?: Displays this message -v, --verbose: Show verbose output --discover_tests: Output test details --adapter_info: Output additional details for test adapters 

If no options or keywords are provided then all test cases are run but only test failures are recorded. The —verbose option will force all test cases to be recorded, even if they pass or are skipped. Any keywords provided will be used to filter the set of test cases.

Читайте также:  Php stack trace on warning

A test fixture is a base class that is re-used for multiple test cases. Each test case will have it’s own copy of the base class so each test case will perform the same set-up and tear-down steps.

struct MyFixture < constexpr int CommonData = 10; >; TEST_CASE(MyFixture, Test1) < // MyFixture constructor called CHECK_EQUAL(CommonData, 10); // MyFixture destructor called > TEST_CASE(MyFixture, Test2) < // MyFixture constructor called CHECK_EQUAL(CommonData, 10); // MyFixture destructor called >

If you want to use assertions in the test fixture base class then it should inherit from CppUnitTestFramework::CommonFixture .

struct MyFixture : CppUnitTestFramework::CommonFixture < // Constructors should be forwarded to allow for initialization using CppUnitTestFramework::CommonFixture::CommonFixture; void CustomAssert(int a, int b) < // This will only compile if CommonFixture is a base class CHECK_EQUAL(a, b) > >;

Test cases can be optionally tagged, allowing them to be grouped into categories that span multiple test files. For example, given the following tests:

TEST_CASE(MyFixture, TestWithoutTags) < . >TEST_CASE_WITH_TAGS(MyFixture, TestWithTags, «gpu«) < . >TEST_CASE_WITH_TAGS(OtherFixture, TestWithTags, «gpu«)

You can then execute the tests individually using keywords :

./MyTests # Runs all tests ./MyTests MyFixture # Runs both MyFixture tests ./MyTests TestWithTags # Runs both test cases called TestWithTags ./MyTests gpu # Runs both test cases tagged as "gpu"

All keyword matching is case sensitive. Keywords will match a fixture or test case name if they occur anywhere in the name, but must match a test tag exactly. For example:

./MyTests MyFix # Runs both MyFixture tests ./MyTests gp # Fails to match any tests

Assertions are provided in two flavors: REQUIRE and CHECK . A REQUIRE assertion will cause a test case to immediately fail, while a CHECK assertion will allow the test case to continue but will still cause a failure once it completes. Both flavors include a basic set of assertion types:

REQUIRE(Expression) // Same as REQUIRE_TRUE REQUIRE_TRUE(Expression) // Asserts that [Expression] evaluates to [true] REQUIRE_FALSE(Expression) // Asserts that [Expression] evaluates to [false] REQUIRE_EQUAL(Left, Right) // Asserts that [Left == Right] REQUIRE_NULL(Expression) // Asserts that [Expression] evaluates to [nullptr] REQUIRE_NOT_NULL(Expression) // Asserts that [Expression] does not evaluate to [nullptr] REQUIRE_THROW(ExceptionType, Expession) // Asserts that invoking [Expression] causes an exception of type [ExceptionType] to be thrown REQUIRE_NO_THROW(Expression) // Asserts that invoking [Expression] does not cause any type of exception to be thrown REQUIRE_CLOSE(Left, Right, Percentage) // Asserts that [abs(Right - Left)] is less than the absolute [Percentage] of [Left] or [Right] REQUIRE_CLOSE_FRACITON(Left, Right, Fraction) // Asserts that [abs(Right - Left)] is less than [Fraction]

Each of these assertion macros invoke an equivalent method in the CppUnitTestFramework::Assert namespace. These methods can be overloaded in your own code if additional customization is required:

namespace CppUnitTestFramework::Assert < template typename TLeft, typename TRight> std::optional AreEqual(const TLeft& left, const TRight& right, const char* expression); template typename T> std::optional IsNull(const T& value, const char* expression); template typename T> std::optional IsNotNull(const T& value, const char* expression); std::optional IsTrue(bool value, const char* expression); std::optional IsFalse(bool value, const char* expression); template typename TException, typename Callback> std::optional Throws(const Callback& callback); template typename Callback> std::optional NoThrow(const Callback& callback); std::optional Close(float left, float right, float percentage); std::optional Close(double left, double right, double percentage); std::optional CloseFraction(float left, float right, float fraction); std::optional CloseFraction(double left, double right, double fraction); >

If an assertion fails then a failure message is generated. In the case of REQUIRE_EQUAL the Left and Right values are converted to a std::string to be included in the message. This conversion is done through an overload of the CppUnitTestFramework::Ext::ToString() method. Standard coversions are provided for nullptr , pointers, enums and any type that can be converted to a std::string by construction or std::to_string() .

namespace CppUnitTestFramework::Ext < template typename T> std::string ToString(const T& value); >

Within a test case it is possible to provide smaller scoped sections that isolate specific test functionality. Sections can be nested as required. The behavior of REQUIRE and CHECK assertions are unaffected by sections, but the test record will include the section text as it progresses.

TEST_CASE(MyFixture, Test1) < SECTION("Construction") < SECTION("Default constructor") < // Test the default constructor here > SECTION("Copy-constructor") < // Test the copy-constructor here > > >

There is basic support for Behavior Driven Development using special section types. For example:

TEST_CASE(MyFixture, Test1) < SCENARIO("Refunded items should be returned to stock") < GIVEN("a customer previously bought a black sweater from me") < . >AND("I have three black sweaters in stock") < . >WHEN("they return the black sweater for a refund") < . >THEN("I should have four black sweaters in stock") < . >> >

A utility macro called UNUSED_RETURN() is provided to assist with the [[nodiscard]] attribute. This is useful when calling REQUIRE_THROW with a method that is marked as non-discardable.

[[nodiscard]] int Foo() < throw std::logic_error("Always fails"); > REQUIRE_THROW(std::logic_error, UNUSED_RETURN(Foo()));

Custom initialization and main()

Читайте также:  Html width 100 auto

In situations where you want to perform your own global setup and shutdown (such as initializing other libraries) you must provide your own main() method. This simply involves copying the main() method from the end of the CppUnitTestFramework.hpp file:

int main(int argc, const char* argv[]) < // Check the command line options CppUnitTestFramework::RunOptions options; if (!options.ParseCommandLine(argc, argv)) < return 2; > // Custom initialization here bool success = CppUnitTestFramework::TestRegistry::Run( &options, CppUnitTestFramework::ConsoleLogger::Create(&options) ); // Custom shutdown here return success ? 0 : 1; >

About

A simple single header C++17 unit test framework

Источник

Оцените статью