Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/pazamelin/sutf

simple unit test framework
https://github.com/pazamelin/sutf

cpp framework header-only macro single-header-lib unit-testing unit-testing-framework

Last synced: about 2 months ago
JSON representation

simple unit test framework

Awesome Lists containing this project

README

        

# simple unit test framework

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/954f686578db42a49f614bc4eea033f0)](https://app.codacy.com/gh/pazamelin/sutf?utm_source=github.com&utm_medium=referral&utm_content=pazamelin/sutf&utm_campaign=Badge_Grade) [![Linux Status](https://img.shields.io/badge/Linux-passing-brightgreen)]() [![macOS Status](https://img.shields.io/badge/macOS-passing-brightgreen)]() [![Windows Status](https://img.shields.io/badge/Windows-failing-red)]()

## Assertions:

### Basic Assertions

These assertions do basic true/false condition testing.

Fatal assertion | Nonfatal assertion | Verifies
-------------------------- | -------------------------- | --------------------
`ASSERT_TRUE(condition);` | `EXPECT_TRUE(condition);` | `condition` is true
`ASSERT_FALSE(condition);` | `EXPECT_FALSE(condition);` | `condition` is false

### Binary Comparison

This section describes assertions that compare two values.

Fatal assertion | Nonfatal assertion | Verifies
------------------------ | ------------------------ | --------------
`ASSERT_EQ(val1, val2);` | `EXPECT_EQ(val1, val2);` | `val1 == val2`
`ASSERT_NE(val1, val2);` | `EXPECT_NE(val1, val2);` | `val1 != val2`
`ASSERT_LT(val1, val2);` | `EXPECT_LT(val1, val2);` | `val1 < val2`
`ASSERT_LE(val1, val2);` | `EXPECT_LE(val1, val2);` | `val1 <= val2`
`ASSERT_GT(val1, val2);` | `EXPECT_GT(val1, val2);` | `val1 > val2`
`ASSERT_GE(val1, val2);` | `EXPECT_GE(val1, val2);` | `val1 >= val2`

### String Comparison

The assertions in this group compare two **C strings**. If you want to compare
two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.

| Fatal assertion | Nonfatal assertion | Verifies |
| -------------------------- | ------------------------------ | -------------------------------------------------------- |
| `ASSERT_CSTR_EQ(str1,str2);` | `EXPECT_CSTR_EQ(str1,str2);` | the two C strings have the same content |
| `ASSERT_CSTR_NE(str1,str2);` | `EXPECT_CSTR_NE(str1,str2);` | the two C strings have different contents |

## Simple Tests

To create a test:

1. Use the `TEST()` macro to define and name a test function.
2. In this function, along with any valid C++ statements you want to include,
use the various assertions to check values.
3. The test's result is determined by the assertions.
If any `ASSERT_*` in the test fails or if the test crashes, the entire test fails.
If any `EXPECT_*` in the test fails, an error message is produced, but the entire test won't fail.

```c++
TEST(TestName) {
... test body ...
}
```
To run all created tests use the `RUN_ALL_TESTS()` macro.

## Usage Example:

```c++
#include
#include
#include
#include
#include
#include

#include "single_header/sutf.hpp"

TEST(strings)
{
std::string str1{"first string"};
std::string str2{"second string"};

ASSERT_EQ(str1, "first string");
ASSERT_NE(str1, str2);
}

TEST(cstrings)
{
char cstr1[] = "first string";
char cstr2[] = "second string";

ASSERT_CSTR_EQ(cstr1, "first string");
ASSERT_CSTR_LT(cstr1, cstr2);
}

TEST(expect_failure)
{
std::string str1;

EXPECT_FALSE(str1.empty());
}

TEST(assert_failure)
{
std::set some_data{0, 1, 2, 4, 5};
auto value_entries{some_data.count(3)};

ASSERT_EQ(value_entries, 2u);
ASSERT_EQ(value_entries, 3u);
}

int main()
{
RUN_ALL_TESTS();
return 0;
}
```

## Test output:
If an assertion fails, an according failure message is printed to std::cerr in to provide information about failed comparison.
The failure message, inter alia, contains `actual` and `expected` values according to the failed assertion. There are, however, four different cases for test output:
1. If the type T has both standard stream inserter operator and custom test output function, then the custom test output function is used for printing the failure message.
2. If the type T has standard stream inserter operator but no custom test output function, then the standard stream inserter operator is used for printing the failure message.
3. If the type T has no standard stream inserter operator, but has custom test output function for test output, than the function is used for printing the failure message.
4. If the type T has neither standard stream inserter operator nor custom test output function, then default test output function is used.

custom test output function format:
```c++
std::ostream& user_defined_sutf_printer_function(std::ostream &os, T value)
{
...
}

```
The function may be used to provide different output for testing than the “normal” output. For example, you may want to print some hidden flags or data in the type that normally wouldn’t be exposed while printing.

standard stream inserter operator |custom test output function | what is used for output
------------------------ | ------------------------ | --------------
YES | YES | `custom test output function`
YES | NO | `standard stream inserter operator`
NO | YES | `custom test output function`
NO | NO | `default test output function`

### Examples for the four cases:
```c++
#include
#include
#include
#include
#include
#include

std::ostream& operator << (std::ostream& os, const std::set& obj)
{
return os << " user-defined stream inserter for set";
}

std::ostream& operator << (std::ostream& os, const std::map& obj)
{
return os << " user-defined stream inserter for map";
}

// user-defined stream inserter
std::ostream& operator << (std::ostream &os,
const std::vector>& value)
{
return os << "user-defined stream inserter std::vector>";
}

// user-defined function for test output
std::ostream& user_defined_sutf_printer_function(std::ostream &os,
const std::vector>& value)
{
return os << "user-defined test output for std::vector>";
}

#include "single_header/sutf.hpp"

TEST(test_output_print)
{
{
std::vector> data1{{0, 1}, {2, 4}};
std::vector> data2{{0, 1}, {2, 1}};

// std::vector> has no stream inserter operator
// values of data1 and data2 will still be printed by
// SUTF's default test output function
ASSERT_EQ(data1, data2);
}

{
std::map data1{{0, 1}, {2, 4}};
std::map data2{{0, 1}, {2, 6}};

// std::map has defined stream inserter operator
// values of data1 and data2 will be thus printed by the operator
ASSERT_EQ(data1,data2);
}

{
std::set data1{1,2,3};
std::set data2{1,2,4};

// std::set has defined stream inserter operator
// values of data1 and data2 will be thus printed by the operator
ASSERT_EQ(data1,data2);
}

{
std::vector> data1{{0, "abc"}, {2, "def"}};
std::vector> data2{{0, "abc"}, {2, "efg"}};

// std::vector> has stream inserter operator
// the type also has user_defined_sutf_printer_function, meaning that it shall be
// used for the output:
ASSERT_EQ(data1,data2);
}
}

int main()
{
// default ("non-test") output for std::vector> uses user-defined
// stream inserter operator (while for tests' output user_defined_sutf_printer_function is employed)
std::vector> data1{{0, "abc"}, {2, "def"}};
std::cout << data1 << std::endl;

RUN_ALL_TESTS();
return 0;
}

```