← 代码俱乐部 · 创作者层 03 / 8
测试不是"额外功课",是让你睡得着觉的护栏。
你写一个 add(a, b) 函数。手测一次没问题。可是改了之后呢?三个月后再看呢?测试就是把"我刚才确认过"这件事记下来。
function add(a, b) { return a + b; }
// 测试
function test(name, fn) {
try { fn(); console.log("✓ " + name); }
catch (e) { console.log("✗ " + name + ": " + e.message); }
}add(a, b) 就是一个简单的加法函数。function test(name, fn) = 定义一个"测试函数",它接收两个参数:测试的名字,和一个"测试逻辑"(fn)。try { ... } catch (e) { ... } = "尝试运行测试,如果出错就捕获错误信息并打印"。
💡 测试的核心思想:定义什么时候"过",什么时候"失败"。如果过了,打 ✓;失败了,打 ✗。
test("1+1 应该等于 2", () => {
if (add(1, 1) !== 2) throw new Error("结果错了");
});
test("0+0 应该等于 0", () => {
if (add(0, 0) !== 0) throw new Error("0+0 不是 0");
});
test("负数也行", () => {
if (add(-1, -1) !== -2) throw new Error("负数错了");
});每个 test(...) 都检查一个条件。if (add(1, 1) !== 2) = "如果 1+1 不等于 2",那就 throw new Error("...") = 抛出一个错误。throw 会让 catch 块抓住,从而打印失败信息。如果条件通过(没有 throw),就会自动打 ✓。
💡 为什么要写多个用例:一个函数可能在某些情况下对,在其他情况下错。测试要覆盖边界情况:正数、0、负数。
👉 试改:改第一个 add(1,1) 成 add(2,3),改判断条件试试。
function add(a, b) { return a + b; }
// 测试
function test(name, fn) {
try { fn(); console.log("✓ " + name); }
catch (e) { console.log("✗ " + name + ": " + e.message); }
}
test("1+1 应该等于 2", () => {
if (add(1, 1) !== 2) throw new Error("结果错了");
});
test("0+0 应该等于 0", () => {
if (add(0, 0) !== 0) throw new Error("0+0 不是 0");
});
test("负数也行", () => {
if (add(-1, -1) !== -2) throw new Error("负数错了");
});
把这段保存为 test.js,在 VS Code 终端跑 node test.js。三个 ✓ 表示对。
一个更完整的测试框架,包括多个函数和更多测试用例:
<!DOCTYPE html>
<html>
<head><style>
body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
.container { max-width: 600px; margin: 0 auto; }
.test { margin: 8px 0; padding: 12px; border-radius: 5px; border-left: 4px solid; }
.pass { background: #c8e6c9; color: #2e7d32; border-left-color: #4caf50; }
.fail { background: #ffcdd2; color: #c62828; border-left-color: #f44336; }
.summary { margin: 20px 0; padding: 15px; background: white; border-radius: 5px; }
</style></head>
<body>
<div class="container">
<h1>我的函数测试报告</h1>
<div class="summary">
<p><strong>总测试:</strong> <span id="total">0</span></p>
<p><strong>通过:</strong> <span id="passed" style="color: #4caf50;">0</span></p>
<p><strong>失败:</strong> <span id="failed" style="color: #f44336;">0</span></p>
</div>
<div id="results"></div>
</div>
<script>
// 定义函数
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
function isEven(n) {
return n % 2 === 0;
}
// 运行测试
function runTests() {
let tests = [
{ name: 'add(2, 3) === 5', run: () => add(2, 3) === 5 },
{ name: 'add(-1, 1) === 0', run: () => add(-1, 1) === 0 },
{ name: 'multiply(3, 4) === 12', run: () => multiply(3, 4) === 12 },
{ name: 'multiply(0, 100) === 0', run: () => multiply(0, 100) === 0 },
{ name: 'isEven(4) === true', run: () => isEven(4) === true },
{ name: 'isEven(3) === false', run: () => isEven(3) === false }
];
let passed = 0, failed = 0;
let html = '';
for (let t of tests) {
let pass = t.run();
if (pass) passed++; else failed++;
let cls = pass ? 'pass' : 'fail';
let icon = pass ? '✓ 通过' : '✗ 失败';
html += '<div class="test ' + cls + '">' + icon + ': ' + t.name + '</div>';
}
document.getElementById('total').innerText = tests.length;
document.getElementById('passed').innerText = passed;
document.getElementById('failed').innerText = failed;
document.getElementById('results').innerHTML = html;
}
runTests();
</script>
</body>
</html>
进阶:这就是"单元测试"的真实流程 —— 写一个函数,给它各种输入,检查输出对不对。如果有一个测试失败了,你就知道函数有 bug。
用 JavaScript 实现字符串反转的几种方法:
<!DOCTYPE html>
<html>
<head><style>
body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
.test { margin: 8px 0; padding: 12px; border-radius: 5px; border-left: 4px solid; }
.pass { background: #c8e6c9; color: #2e7d32; border-left-color: #4caf50; }
.fail { background: #ffcdd2; color: #c62828; border-left-color: #f44336; }
</style></head>
<body>
<h1>字符串反转 —— 多种实现方法</h1>
<div id="results"></div>
<script>
// 方法 1: 用 split + reverse + join
function reverse_v1(str) {
return str.split('').reverse().join('');
}
// 方法 2: 用 for 循环
function reverse_v2(str) {
let result = '';
for (let i = str.length - 1; i >= 0; i--) {
result += str[i];
}
return result;
}
// 定义测试
let tests = [
{ name: "reverse('hello') === 'olleh'", run: () => reverse_v1('hello') === 'olleh' },
{ name: "reverse('abc') === 'cba'", run: () => reverse_v1('abc') === 'cba' },
{ name: "reverse('') === ''", run: () => reverse_v1('') === '' },
{ name: "reverse('a') === 'a'", run: () => reverse_v1('a') === 'a' }
];
let html = '<p><strong>方法 1(split + reverse + join):</strong></p>';
for (let t of tests) {
let pass = t.run();
let cls = pass ? 'pass' : 'fail';
let icon = pass ? '✓' : '✗';
html += '<div class="test ' + cls + '">' + icon + ' ' + t.name + '</div>';
}
document.getElementById('results').innerHTML = html;
</script>
</body>
</html>
进阶:TDD(测试驱动开发)是这样工作的:先写测试(定义你想要什么),然后写函数(实现你想要的)。这样你永远知道自己的代码对不对。
测试看起来麻烦。但有了测试,你才敢改代码。怕改坏,是不会写好东西的。