题目
设计一个单元测试用例来验证一个简单的字符串处理函数
信息
- 类型:问答
- 难度:⭐⭐
考点
单元测试设计,边界条件处理,测试用例完整性
快速回答
针对字符串处理函数 truncateString(str, maxLength) 的测试用例应包含:
- 正常情况:字符串短于最大长度时返回原字符串
- 边界情况:字符串长度等于最大长度时
- 异常情况:空字符串、null/undefined输入、非字符串类型
- 特殊字符:包含多字节字符(如emoji)的截断处理
- 参数验证:maxLength为负数或非整数时的处理
函数需求说明
实现一个字符串截断函数:function truncateString(str, maxLength) { ... },要求:
- 当
str.length <= maxLength时返回原字符串 - 当
str.length > maxLength时截断为maxLength长度并在末尾添加 "..." - 需处理异常输入和边界情况
测试用例设计
// 使用 Jest 测试框架示例
describe('truncateString', () => {
test('字符串短于最大长度', () => {
expect(truncateString('Hello', 10)).toBe('Hello');
});
test('字符串等于最大长度', () => {
expect(truncateString('Hello', 5)).toBe('Hello');
});
test('字符串长于最大长度', () => {
expect(truncateString('Hello World', 5)).toBe('He...');
});
test('空字符串处理', () => {
expect(truncateString('', 5)).toBe('');
});
test('null/undefined 输入', () => {
expect(truncateString(null, 5)).toBe('');
expect(truncateString(undefined, 5)).toBe('');
});
test('非字符串类型输入', () => {
expect(truncateString(12345, 3)).toBe('12...');
});
test('多字节字符处理', () => {
expect(truncateString('你好👋世界', 4)).toBe('你好...');
});
test('maxLength 为负数', () => {
expect(truncateString('Hello', -1)).toBe('');
});
test('maxLength 为小数', () => {
expect(truncateString('Hello', 3.7)).toBe('He...');
});
});核心考察点解析
- 边界条件覆盖:必须测试等于 maxLength 的临界点
- 异常处理:空输入、null/undefined、非字符串类型的健壮性处理
- 多字节字符:JavaScript 中 String.length 按 UTF-16 编码计算,需注意 emoji 等字符可能占两个码元
- 参数校验:maxLength 为负数或非整数时的合理处理
最佳实践
- 使用测试框架的
describe/test组织用例 - 每个测试用例保持单一职责原则
- 测试名称应明确描述场景(如 "should return original string when length <= maxLength")
- 添加性能测试(如超长字符串处理)
常见错误
- 未考虑多字节字符导致截断位置错误(如将 👋 截断为乱码)
- 未处理 maxLength=0 或负数的情况
- 截断后 "..." 导致总长度超过 maxLength
- 未对非字符串输入进行类型转换
扩展知识
- Unicode 问题:使用
Array.from(str).slice(0, maxLength)可更准确处理多字节字符 - 测试覆盖率:使用 Istanbul/Jest 内置工具检查分支覆盖率
- 参数化测试:使用
test.each简化相似用例:test.each([ ['abc', 5, 'abc'], ['abcdef', 5, 'ab...'] ])('truncate %s with %i', (str, max, expected) => { expect(truncateString(str, max)).toBe(expected); });