TEST_ASSERT_EQUAL_UINT(expected, actual)
TEST_ASSERT_EQUAL_UINT8(expected, actual)
TEST_ASSERT_EQUAL_UINT16(expected, actual)
TEST_ASSERT_EQUAL_UINT32(expected, actual)
TEST_ASSERT_EQUAL_UINT64(expected, actual)
比较两个整数是否相等,并将错误显示为无符号整数。像INT
一样,也有不同大小的变体。
TEST_ASSERT_EQUAL_HEX(expected, actual)
TEST_ASSERT_EQUAL_HEX8(expected, actual)
TEST_ASSERT_EQUAL_HEX16(expected, actual)
TEST_ASSERT_EQUAL_HEX32(expected, actual)
TEST_ASSERT_EQUAL_HEX64(expected, actual)
比较两个整数是否相等,并将错误显示为十六进制。与其他整数比较一样,您可以指定大小…在这里,大小也会影响显示了多少个小块(例如,HEX16
将显示4个小块)。
TEST_ASSERT_EQUAL(expected, actual)
另一种调用TEST_ASSERT_EQUAL_INT
的方法
TEST_ASSERT_INT_WITHIN(delta, expected, actual)
断言实际值在期望值的正负之间。这也出现在大小特定的变体。
TEST_ASSERT_GREATER_THAN(threshold, actual)
断言实际值大于阈值。这也出现在大小特定的变体。
TEST_ASSERT_LESS_THAN(threshold, actual)
断言实际值小于阈值。这也出现在大小特定的变体。
Arrays
_ARRAY
您可以将_ARRAY
附加到任何这些宏中,以对该类型进行数组比较。在这里,您需要更关心被检查的值的实际大小。您还将指定一个附加参数,即要比较的元素数量。例如:
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements)
_EACH_EQUAL
另一个数组比较选项是检查数组中的每个元素是否等于单个期望值。您可以通过指定EACH_EQUAL
宏来实现这一点。例如:
TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements)
Numerical Assertions: Bitwise
TEST_ASSERT_BITS(mask, expected, actual)
使用一个整数掩码来指定两个其他整数之间应该比较哪些位。比较掩码中的高比特,忽略低比特。
TEST_ASSERT_BITS_HIGH(mask, actual)
使用整数掩码指定应该检查哪些位以确定它们是否都设置为高。比较掩码中的高比特,忽略低比特。
TEST_ASSERT_BITS_LOW(mask, actual)
使用一个整数掩码来指定应该检查哪些位以确定它们是否都设置得很低。比较掩码中的高比特,忽略低比特。
TEST_ASSERT_BIT_HIGH(bit, actual)
测试单个位,并验证它是否高。为32位整数指定0-31位。
TEST_ASSERT_BIT_LOW(bit, actual)
测试一个比特并确认它是低的。为32位整数指定0-31位。
Numerical Assertions: Floats
TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)
断言实际值在期望值的正负之间。
TEST_ASSERT_EQUAL_FLOAT(expected, actual)
TEST_ASSERT_EQUAL_DOUBLE(expected, actual)
断言两个浮点值在期望值的小%增量内“相等”。
String Assertions
TEST_ASSERT_EQUAL_STRING(expected, actual)
比较两个空终止字符串。如果任何字符不同或长度不同,则失败。
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)
比较两个字符串。如果任何字符不同,则在len字符后停止比较。
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)
比较两个空终止字符串。如果任何字符不同或长度不同,则失败。失败时输出自定义消息。
TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)
比较两个字符串。如果任何字符不同,则在len字符后停止比较。失败时输出自定义消息。
Pointer Assertions
大多数指针操作都可以通过使用上面的整数比较来执行。但是,为了清楚起见,添加了一些特殊的情况。
TEST_ASSERT_NULL(pointer)
如果指针不等于NULL,则失败
TEST_ASSERT_NOT_NULL(pointer)
如果指针等于NULL,则失败
Memory Assertions
TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)
比较两块内存。对于不能强制执行标准类型的类型来说,这是一个很好的通用断言……但是由于这是内存比较,所以必须注意数据类型的打包。
可以看到在unity中,存在着各种各样的断言。
除了C语言库中存在的真假断言,还有整数断言,数组断言,位断言,浮点数断言,字符串断言,指针断言,
在单元测试框架中,我们在一个测试函数中,可以建立对某个函数的完整测试,
void testNullInputToInit\_should\_fail(void) {
uint8_t ret;
lwrb_t buff = { 0 };
uint8_t buff_data[1];
ret = lwrb\_init(NULL, buff_data, sizeof(buff_data));
TEST\_ASSERT\_EQUAL(0, ret);
ret = lwrb\_init(&buff, NULL, sizeof(buff_data));
TEST\_ASSERT\_EQUAL(0, ret);
ret = lwrb\_init(&buff, buff_data, 0);
TEST\_ASSERT\_EQUAL(0, ret);
ret = lwrb\_is\_ready(&buff);
TEST\_ASSERT\_EQUAL(0, ret);
}
在这个测试函数中,我们主要测试的是环形缓冲的lwrb_init函数,我们对其进行了不同的输入测试,并且使用断言来判断实际输出和我们期望的输出是否一致。
在我之前的博客【C语言开源库】在CLion上使用一个轻量的适合嵌入式系统的环形缓冲库ring buffer 和C语言Unity单元测试框架中,我们测试了环形缓冲开源库的一些函数,运行结果和预期一致时,运行显示如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rlVueSAk-1628230382669)(https://raw.githubusercontent.com/xkyvvv/blogpic/main/pic1/image-20210805180906253.png)]
当运行结果和预期不一致时,运行显示如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cB2Xl1Ii-1628230382671)(https://raw.githubusercontent.com/xkyvvv/blogpic/main/pic1/image-20210805181024986.png)]
可以看到,单元测试框架就是一个断言集合,下面我们通过源码来看一下不同断言的具体实现。
/\* ==========================================
Unity Project - A Test Framework for C
Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams
[Released under MIT License. Please refer to license.txt for details]
========================================== \*/
#ifndef UNITY\_FRAMEWORK\_H
#define UNITY\_FRAMEWORK\_H
#define UNITY
#define UNITY\_VERSION\_MAJOR 2
#define UNITY\_VERSION\_MINOR 5
#define UNITY\_VERSION\_BUILD 4
#define UNITY\_VERSION ((UNITY\_VERSION\_MAJOR << 16) | (UNITY\_VERSION\_MINOR << 8) | UNITY\_VERSION\_BUILD)
#ifdef \_\_cplusplus
extern "C"
{
#endif
#include "unity\_internals.h"
/\*-------------------------------------------------------
\* Test Setup / Teardown
\*-------------------------------------------------------\*/
/\* These functions are intended to be called before and after each test.
\* If using unity directly, these will need to be provided for each test
\* executable built. If you are using the test runner generator and/or
\* Ceedling, these are optional. \*/
void setUp(void);
void tearDown(void);
/\* These functions are intended to be called at the beginning and end of an
\* entire test suite. suiteTearDown() is passed the number of tests that
\* failed, and its return value becomes the exit code of main(). If using
\* Unity directly, you're in charge of calling these if they are desired.
\* If using Ceedling or the test runner generator, these will be called
\* automatically if they exist. \*/
void suiteSetUp(void);
int suiteTearDown(int num_failures);
/\*-------------------------------------------------------
\* Test Reset and Verify
\*-------------------------------------------------------\*/
/\* These functions are intended to be called before during tests in order
\* to support complex test loops, etc. Both are NOT built into Unity. Instead
\* the test runner generator will create them. resetTest will run teardown and
\* setup again, verifying any end-of-test needs between. verifyTest will only
\* run the verification. \*/
void resetTest(void);
void verifyTest(void);
/\*-------------------------------------------------------
\* Configuration Options
\*-------------------------------------------------------
\* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
\* Integers/longs/pointers
\* - Unity attempts to automatically discover your integer sizes
\* - define UNITY\_EXCLUDE\_STDINT\_H to stop attempting to look in <stdint.h>
\* - define UNITY\_EXCLUDE\_LIMITS\_H to stop attempting to look in <limits.h>
\* - If you cannot use the automatic methods above, you can force Unity by using these options:
\* - define UNITY\_SUPPORT\_64
\* - set UNITY\_INT\_WIDTH
\* - set UNITY\_LONG\_WIDTH
\* - set UNITY\_POINTER\_WIDTH
\* Floats
\* - define UNITY\_EXCLUDE\_FLOAT to disallow floating point comparisons
\* - define UNITY\_FLOAT\_PRECISION to specify the precision to use when doing TEST\_ASSERT\_EQUAL\_FLOAT
\* - define UNITY\_FLOAT\_TYPE to specify doubles instead of single precision floats
\* - define UNITY\_INCLUDE\_DOUBLE to allow double floating point comparisons
\* - define UNITY\_EXCLUDE\_DOUBLE to disallow double floating point comparisons (default)
\* - define UNITY\_DOUBLE\_PRECISION to specify the precision to use when doing TEST\_ASSERT\_EQUAL\_DOUBLE
\* - define UNITY\_DOUBLE\_TYPE to specify something other than double
\* - define UNITY\_EXCLUDE\_FLOAT\_PRINT to trim binary size, won't print floating point values in errors
\* Output
\* - by default, Unity prints to standard out with putchar. define UNITY\_OUTPUT\_CHAR(a) with a different function if desired
\* - define UNITY\_DIFFERENTIATE\_FINAL\_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
\* Optimization
\* - by default, line numbers are stored in unsigned shorts. Define UNITY\_LINE\_TYPE with a different type if your files are huge
\* - by default, test and failure counters are unsigned shorts. Define UNITY\_COUNTER\_TYPE with a different type if you want to save space or have more than 65535 Tests.
\* Test Cases
\* - define UNITY\_SUPPORT\_TEST\_CASES to include the TEST\_CASE macro, though really it's mostly about the runner generator script
\* Parameterized Tests
\* - you'll want to create a define of TEST\_CASE(...) which basically evaluates to nothing
\* Tests with Arguments
\* - you'll want to define UNITY\_USE\_COMMAND\_LINE\_ARGS if you have the test runner passing arguments to Unity
\*-------------------------------------------------------
\* Basic Fail and Ignore
\*-------------------------------------------------------\*/
#define TEST\_FAIL\_MESSAGE(message) UNITY\_TEST\_FAIL(\_\_LINE\_\_, (message))
#define TEST\_FAIL() UNITY\_TEST\_FAIL(\_\_LINE\_\_, NULL)
#define TEST\_IGNORE\_MESSAGE(message) UNITY\_TEST\_IGNORE(\_\_LINE\_\_, (message))
#define TEST\_IGNORE() UNITY\_TEST\_IGNORE(\_\_LINE\_\_, NULL)
#define TEST\_MESSAGE(message) UnityMessage((message), \_\_LINE\_\_)
#define TEST\_ONLY()
#ifdef UNITY\_INCLUDE\_PRINT\_FORMATTED
#define TEST\_PRINTF(message, ...) UnityPrintF(\_\_LINE\_\_, (message), \_\_VA\_ARGS\_\_)
#endif
/\* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
\* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. \*/
#define TEST\_PASS() TEST\_ABORT()
#define TEST\_PASS\_MESSAGE(message) do { UnityMessage((message), \_\_LINE\_\_); TEST\_ABORT(); } while(0)
/\* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
\* which files should be linked to in order to perform a test. Use it like TEST\_FILE("sandwiches.c") \*/
#define TEST\_FILE(a)
/\*-------------------------------------------------------
\* Test Asserts (simple)
\*-------------------------------------------------------\*/
/\* Boolean \*/
#define TEST\_ASSERT(condition) UNITY\_TEST\_ASSERT( (condition), \_\_LINE\_\_, " Expression Evaluated To FALSE")
#define TEST\_ASSERT\_TRUE(condition) UNITY\_TEST\_ASSERT( (condition), \_\_LINE\_\_, " Expected TRUE Was FALSE")
#define TEST\_ASSERT\_UNLESS(condition) UNITY\_TEST\_ASSERT( !(condition), \_\_LINE\_\_, " Expression Evaluated To TRUE")
#define TEST\_ASSERT\_FALSE(condition) UNITY\_TEST\_ASSERT( !(condition), \_\_LINE\_\_, " Expected FALSE Was TRUE")
#define TEST\_ASSERT\_NULL(pointer) UNITY\_TEST\_ASSERT\_NULL( (pointer), \_\_LINE\_\_, " Expected NULL")
#define TEST\_ASSERT\_NOT\_NULL(pointer) UNITY\_TEST\_ASSERT\_NOT\_NULL((pointer), \_\_LINE\_\_, " Expected Non-NULL")
#define TEST\_ASSERT\_EMPTY(pointer) UNITY\_TEST\_ASSERT\_EMPTY( (pointer), \_\_LINE\_\_, " Expected Empty")
#define TEST\_ASSERT\_NOT\_EMPTY(pointer) UNITY\_TEST\_ASSERT\_NOT\_EMPTY((pointer), \_\_LINE\_\_, " Expected Non-Empty")
/\* Integers (of all sizes) \*/
#define TEST\_ASSERT\_EQUAL\_INT(expected, actual) UNITY\_TEST\_ASSERT\_EQUAL\_INT((expected), (actual), \_\_LINE\_\_, NULL)
#define TEST\_ASSERT\_EQUAL\_INT8(expected, actual) UNITY\_TEST\_ASSERT\_EQUAL\_INT8((expected), (actual), \_\_LINE\_\_, NULL)
#define TEST\_ASSERT\_EQUAL\_INT16(expected, actual) UNITY\_TEST\_ASSERT\_EQUAL\_INT16((expected), (actual), \_\_LINE\_\_, NULL)
#define TEST\_ASSERT\_EQUAL\_INT32(expected, actual) UNITY\_TEST\_ASSERT\_EQUAL\_INT32((expected), (actu