├── example ├── .gitignore ├── myfunctions.h ├── Makefile ├── myfunctions.c ├── README.txt └── myfunctions_test.c ├── README.md └── tinytest.h /example/.gitignore: -------------------------------------------------------------------------------- 1 | myfunctions.o 2 | myfunctions_test 3 | -------------------------------------------------------------------------------- /example/myfunctions.h: -------------------------------------------------------------------------------- 1 | /* Header for functions to be tested. */ 2 | 3 | #ifndef _MYFUNCTIONS_INCLUDED 4 | #define _MYFUNCTIONS_INCLUDED 5 | 6 | int add_numbers(int a, int b); 7 | int multiply_numbers(int a, int b); 8 | 9 | #endif -------------------------------------------------------------------------------- /example/Makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -g -O0 2 | 3 | .PHONY: clean test 4 | 5 | all: myfunctions.o myfunctions_test 6 | 7 | myfunctions_test: myfunctions.o 8 | 9 | test: myfunctions_test 10 | ./myfunctions_test 11 | 12 | clean: 13 | rm -f *.o myfunctions_test 14 | -------------------------------------------------------------------------------- /example/myfunctions.c: -------------------------------------------------------------------------------- 1 | /* Some sample functions to be tested. Yeah, they're dumb. */ 2 | 3 | #include "myfunctions.h" 4 | 5 | int add_numbers(int a, int b) 6 | { 7 | return a + b; 8 | }; 9 | 10 | int multiply_numbers(int a, int b) 11 | { 12 | return a * b; 13 | }; 14 | -------------------------------------------------------------------------------- /example/README.txt: -------------------------------------------------------------------------------- 1 | This is a simple example of how to use TinyTest. 2 | 3 | There are some simple functions in myfunctions.c that are tested 4 | by myfunctions_test.c. 5 | 6 | To run: 7 | make test 8 | 9 | The tests will fail. This is to demonstrate what happens when 10 | they fail. To see them pass, fix the tests and try again. 11 | 12 | -------------------------------------------------------------------------------- /example/myfunctions_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for myfunctions.c, using TinyTest. */ 2 | 3 | #include "../tinytest.h" 4 | #include "myfunctions.h" 5 | 6 | void test_addition() 7 | { 8 | ASSERT_EQUALS(10, add_numbers(3, 7)); 9 | ASSERT_EQUALS(-10, add_numbers(4, -14)); 10 | } 11 | 12 | void test_that_fails() 13 | { 14 | /* this assertion fails - to demonstrate what happens */ 15 | ASSERT_EQUALS(10, add_numbers(3, 33)); 16 | /* because of the failure, this line won't even run */ 17 | ASSERT_EQUALS(10, add_numbers(3, 7)); 18 | } 19 | 20 | void test_multiplication() 21 | { 22 | ASSERT_EQUALS(12, multiply_numbers(3, 4)); 23 | ASSERT_EQUALS(-12, multiply_numbers(4, -3)); 24 | } 25 | 26 | /* test runner */ 27 | int main() 28 | { 29 | RUN(test_addition); 30 | RUN(test_that_fails); 31 | RUN(test_multiplication); 32 | return TEST_REPORT(); 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TinyTest 2 | ======== 3 | 4 | A really really really tiny and simple no-hassle C unit-testing framework. 5 | 6 | Features 7 | -------- 8 | 9 | * **No library dependencies**. Not even itself. Just a header file. 10 | * Simple ANSI C. Should work with virtually every C or C++ compiler on virtually any platform. 11 | * Reports assertion failures, including expressions and line numbers. 12 | * Stops test on first failed assertion. 13 | * ANSI color output for maximum visibility. 14 | * Easy to embed in apps for runtime tests (e.g. environment tests). 15 | 16 | Example Usage 17 | ------------- 18 | 19 | #include "tinytest.h" 20 | #include "mylib.h" 21 | 22 | void test_sheep() 23 | { 24 | ASSERT("Sheep are cool", are_sheep_cool()); 25 | ASSERT_EQUALS(4, sheep.legs); 26 | } 27 | 28 | void test_cheese() 29 | { 30 | ASSERT("Cheese is tangy", cheese.tanginess > 0); 31 | ASSERT_STRING_EQUALS("Wensleydale", cheese.name); 32 | } 33 | 34 | int main() 35 | { 36 | RUN(test_sheep); 37 | RUN(test_cheese); 38 | return TEST_REPORT(); 39 | } 40 | 41 | To run the tests, compile the tests as a binary and run it. 42 | 43 | *2010-2014, -Joe Walnes http://joewalnes.com* 44 | 45 | 46 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/joewalnes/tinytest/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 47 | 48 | -------------------------------------------------------------------------------- /tinytest.h: -------------------------------------------------------------------------------- 1 | /* TinyTest: A really really really tiny and simple no-hassle C unit-testing framework. 2 | * 3 | * Features: 4 | * - No library dependencies. Not even itself. Just a header file. 5 | * - Simple ANSI C. Should work with virtually every C or C++ compiler on 6 | * virtually any platform. 7 | * - Reports assertion failures, including expressions and line numbers. 8 | * - Stops test on first failed assertion. 9 | * - ANSI color output for maximum visibility. 10 | * - Easy to embed in apps for runtime tests (e.g. environment tests). 11 | * 12 | * Example Usage: 13 | * 14 | * #include "tinytest.h" 15 | * #include "mylib.h" 16 | * 17 | * void test_sheep() 18 | * { 19 | * ASSERT("Sheep are cool", are_sheep_cool()); 20 | * ASSERT_EQUALS(4, sheep.legs); 21 | * } 22 | * 23 | * void test_cheese() 24 | * { 25 | * ASSERT("Cheese is tangy", cheese.tanginess > 0); 26 | * ASSERT_STRING_EQUALS("Wensleydale", cheese.name); 27 | * } 28 | * 29 | * int main() 30 | * { 31 | * RUN(test_sheep); 32 | * RUN(test_cheese); 33 | * return TEST_REPORT(); 34 | * } 35 | * 36 | * To run the tests, compile the tests as a binary and run it. 37 | * 38 | * Project home page: http://github.com/joewalnes/tinytest 39 | * 40 | * 2010, -Joe Walnes http://joewalnes.com 41 | */ 42 | 43 | #ifndef _TINYTEST_INCLUDED 44 | #define _TINYTEST_INCLUDED 45 | 46 | #include 47 | #include 48 | 49 | /* Main assertion method */ 50 | #define ASSERT(msg, expression) if (!tt_assert(__FILE__, __LINE__, (msg), (#expression), (expression) ? 1 : 0)) return 51 | 52 | /* Convenient assertion methods */ 53 | /* TODO: Generate readable error messages for assert_equals or assert_str_equals */ 54 | #define ASSERT_EQUALS(expected, actual) ASSERT((#actual), (expected) == (actual)) 55 | #define ASSERT_STRING_EQUALS(expected, actual) ASSERT((#actual), strcmp((expected),(actual)) == 0) 56 | 57 | /* Run a test() function */ 58 | #define RUN(test_function) tt_execute((#test_function), (test_function)) 59 | #define TEST_REPORT() tt_report() 60 | 61 | #define TT_COLOR_CODE 0x1B 62 | #define TT_COLOR_RED "[1;31m" 63 | #define TT_COLOR_GREEN "[1;32m" 64 | #define TT_COLOR_RESET "[0m" 65 | 66 | int tt_passes = 0; 67 | int tt_fails = 0; 68 | int tt_current_test_failed = 0; 69 | const char* tt_current_msg = NULL; 70 | const char* tt_current_expression = NULL; 71 | const char* tt_current_file = NULL; 72 | int tt_current_line = 0; 73 | 74 | void tt_execute(const char* name, void (*test_function)()) 75 | { 76 | tt_current_test_failed = 0; 77 | test_function(); 78 | if (tt_current_test_failed) { 79 | printf("failure: %s:%d: In test %s():\n %s (%s)\n", 80 | tt_current_file, tt_current_line, name, tt_current_msg, tt_current_expression); 81 | tt_fails++; 82 | } else { 83 | tt_passes++; 84 | } 85 | } 86 | 87 | int tt_assert(const char* file, int line, const char* msg, const char* expression, int pass) 88 | { 89 | tt_current_msg = msg; 90 | tt_current_expression = expression; 91 | tt_current_file = file; 92 | tt_current_line = line; 93 | tt_current_test_failed = !pass; 94 | return pass; 95 | } 96 | 97 | int tt_report(void) 98 | { 99 | if (tt_fails) { 100 | printf("%c%sFAILED%c%s [%s] (passed:%d, failed:%d, total:%d)\n", 101 | TT_COLOR_CODE, TT_COLOR_RED, TT_COLOR_CODE, TT_COLOR_RESET, 102 | tt_current_file, tt_passes, tt_fails, tt_passes + tt_fails); 103 | return -1; 104 | } else { 105 | printf("%c%sPASSED%c%s [%s] (total:%d)\n", 106 | TT_COLOR_CODE, TT_COLOR_GREEN, TT_COLOR_CODE, TT_COLOR_RESET, 107 | tt_current_file, tt_passes); 108 | return 0; 109 | } 110 | } 111 | 112 | #endif 113 | --------------------------------------------------------------------------------