Appearance
显式用例
使用 cases() 语法精确控制每个测试用例。
基本语法
c
__attribute__((test_method, cases((值1, 值2, ...), (值1, 值2, ...), ...)))
int test_function(参数1, 参数2, ...) {
// 测试逻辑
}简单示例
c
/*
* 设计说明:测试字节截断函数
* 预期结果:超出范围的值被截断到边界
*/
__attribute__((test_method, cases(
(-100, 0),
(-1, 0),
(0, 0),
(128, 128),
(255, 255),
(256, 255),
(1000, 255)
)))
int test_clamp_byte(int input, int expected) {
return clamp_byte(input) == expected;
}生成 7 个测试用例:
test_clamp_byte[input=-100, expected=0]
test_clamp_byte[input=-1, expected=0]
test_clamp_byte[input=0, expected=0]
test_clamp_byte[input=128, expected=128]
test_clamp_byte[input=255, expected=255]
test_clamp_byte[input=256, expected=255]
test_clamp_byte[input=1000, expected=255]与 params + strategy(zip) 对比
cases() 和 params() + strategy(zip) 功能相似:
c
__attribute__((test_method, cases(
(1, 1),
(2, 4),
(3, 9)
)))
int test_square(int input, int expected) {
return math_square(input) == expected;
}c
__attribute__((test_method,
params(input = {1, 2, 3}, expected = {1, 4, 9}),
strategy(zip)))
int test_square(int input, int expected) {
return math_square(input) == expected;
}cases() 的优势:
- 输入和预期输出放在一起,更直观
- 适合复杂的测试数据
- 易于添加和修改用例
多参数用例
c
/*
* 设计说明:测试三数之和
* 预期结果:返回三个数的和
*/
__attribute__((test_method, cases(
(0, 0, 0, 0),
(1, 2, 3, 6),
(-1, 1, 0, 0),
(100, 200, 300, 600),
(-50, -50, 100, 0)
)))
int test_sum3(int a, int b, int c, int expected) {
return sum3(a, b, c) == expected;
}错误码测试
c
/*
* 设计说明:测试除法函数错误处理
* 预期结果:除零返回错误码,正常返回商
*/
__attribute__((test_method, cases(
(10, 2, 5, 0), // 正常除法
(10, 3, 3, 0), // 整数除法
(0, 5, 0, 0), // 零除以非零
(10, 0, 0, -1), // 除以零错误
(-10, 2, -5, 0) // 负数除法
)))
int test_safe_divide(int a, int b, int expected_result, int expected_error) {
int error = 0;
int result = safe_divide(a, b, &error);
if (expected_error != 0) {
return error == expected_error;
}
return result == expected_result && error == 0;
}字符串测试
c
/*
* 设计说明:测试字符串长度函数
* 预期结果:返回正确的长度
*/
__attribute__((test_method, cases(
("", 0),
("a", 1),
("hello", 5),
("hello world", 11)
)))
int test_strlen(const char *str, int expected) {
return my_strlen(str) == expected;
}边界值 + 显式用例
可以在同一个测试文件中结合使用:
c
// 使用边界类型进行广泛覆盖
__attribute__((test_method, params(n = boundary(uint8))))
int test_byte_boundary(int n) {
return is_valid_byte(n) == (n >= 0 && n <= 255);
}
// 使用显式用例测试特殊情况
__attribute__((test_method, cases(
(0, 1),
(255, 1),
(-1, 0),
(256, 0)
)))
int test_byte_explicit(int value, int expected) {
return is_valid_byte(value) == expected;
}完整示例
c
#include "parser.h"
/*
* 设计说明:测试 HTTP 状态码解析
* 预期结果:返回正确的状态码类别
*/
__attribute__((test_method, cases(
(200, STATUS_OK),
(201, STATUS_OK),
(204, STATUS_OK),
(301, STATUS_REDIRECT),
(302, STATUS_REDIRECT),
(400, STATUS_CLIENT_ERROR),
(401, STATUS_CLIENT_ERROR),
(403, STATUS_CLIENT_ERROR),
(404, STATUS_CLIENT_ERROR),
(500, STATUS_SERVER_ERROR),
(502, STATUS_SERVER_ERROR),
(503, STATUS_SERVER_ERROR)
)))
int test_status_category(int code, int expected_category) {
return get_status_category(code) == expected_category;
}
/*
* 设计说明:测试 URL 解析
* 预期结果:正确提取主机名
*/
__attribute__((test_method, cases(
("http://example.com", "example.com"),
("https://www.google.com/search", "www.google.com"),
("http://localhost:8080", "localhost"),
("https://api.github.com/repos", "api.github.com")
)))
int test_parse_host(const char *url, const char *expected_host) {
char host[256];
parse_host(url, host, 256);
return strcmp(host, expected_host) == 0;
}
/*
* 设计说明:测试日期解析
* 预期结果:正确解析年月日
*/
__attribute__((test_method, cases(
("2024-01-15", 2024, 1, 15, 0),
("2023-12-31", 2023, 12, 31, 0),
("2024-02-29", 2024, 2, 29, 0), // 闰年
("2023-02-29", 0, 0, 0, -1), // 非闰年,无效
("invalid", 0, 0, 0, -1) // 格式错误
)))
int test_parse_date(const char *str, int exp_y, int exp_m, int exp_d, int exp_err) {
int y, m, d;
int err = parse_date(str, &y, &m, &d);
if (exp_err != 0) {
return err == exp_err;
}
return y == exp_y && m == exp_m && d == exp_d;
}
// includes: -I../include最佳实践
- 输入和预期放一起:使用
cases()而非分开的params() - 覆盖边界情况:包含边界值、错误情况
- 注释说明:每个用例的目的
- 合理数量:通常 5-15 个用例足够