Skip to content

Commit d5b629c

Browse files
committed
refactor(tests): reorganize and improve test coverage
- Restructure integration tests with describe blocks for better organization - Remove redundant simple tests that duplicated other test files - Add new tests for: unary operators, exponentiation, bitwise operations, array/object literals, operator precedence, edge cases - Streamline compile.test.ts and evaluate.test.ts to focus on unit testing - Add practical scenario tests (price calculation, coordinate transform) - Improve optimization tests with partial inlining and special value handling
1 parent e783fe4 commit d5b629c

6 files changed

Lines changed: 994 additions & 499 deletions

src/compile.test.ts

Lines changed: 130 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,136 @@
1-
import { expect, test } from "bun:test";
1+
import { describe, expect, test } from "bun:test";
22
import { z } from "zod";
3-
import { compile } from "./compile";
4-
import { expr } from "./expr";
5-
import { variable } from "./variable";
3+
import { compile, expr, variable } from "./index";
64

7-
test("compile: simple variable expression", () => {
8-
const x = variable(z.number());
9-
const y = variable(z.number());
5+
describe("compile 单元测试", () => {
6+
describe("编译输出格式", () => {
7+
test("基本结构: [变量名数组, ...表达式]", () => {
8+
const x = variable(z.number());
9+
const y = variable(z.number());
10+
11+
const sum = expr({ x, y })("x + y");
12+
const result = compile(sum, { x, y });
1013

11-
const sum = expr({ x, y })("x + y");
12-
const result = compile(sum, { x, y });
14+
expect(result).toHaveLength(2);
15+
expect(result[0]).toEqual(["x", "y"]);
16+
expect(typeof result[1]).toBe("string");
17+
});
18+
19+
test("变量占位符替换", () => {
20+
const x = variable(z.number());
21+
const y = variable(z.number());
22+
23+
const sum = expr({ x, y })("x + y");
24+
const result = compile(sum, { x, y });
1325

14-
// 预期结果:[["x", "y"], "$0+$1"](通过 AST 规范化输出,无空格)
15-
expect(result).toHaveLength(2);
16-
expect(result[0]).toEqual(["x", "y"]);
17-
expect(result[1]).toBe("$0+$1");
18-
});
19-
20-
test("compile: nested expressions with inline optimization", () => {
21-
const x = variable(z.number());
22-
const y = variable(z.number());
23-
24-
const sum = expr({ x, y })("x + y");
25-
const product = expr({ x, y })("x * y");
26-
const result = expr({ sum, product })("sum + product");
27-
28-
// 默认开启内联优化
29-
const compiled = compile(result, { x, y });
30-
31-
// 内联优化后,只剩一个表达式
32-
expect(compiled).toHaveLength(2);
33-
expect(compiled[0]).toEqual(["x", "y"]);
34-
expect(compiled[1]).toBe("$0+$1+$0*$1");
35-
});
36-
37-
test("compile: nested expressions without inline", () => {
38-
const x = variable(z.number());
39-
const y = variable(z.number());
40-
41-
const sum = expr({ x, y })("x + y");
42-
const product = expr({ x, y })("x * y");
43-
const result = expr({ sum, product })("sum + product");
44-
45-
// 禁用内联优化
46-
const compiled = compile(result, { x, y }, { inline: false });
47-
48-
// 预期:[["x", "y"], "$0+$1", "$0*$1", "$2+$3"](规范化输出)
49-
expect(compiled).toHaveLength(4);
50-
expect(compiled[0]).toEqual(["x", "y"]);
51-
expect(compiled[1]).toBe("$0+$1");
52-
expect(compiled[2]).toBe("$0*$1");
53-
expect(compiled[3]).toBe("$2+$3");
54-
});
55-
56-
test("compile: expression with single variable", () => {
57-
const x = variable(z.number());
58-
59-
const double = expr({ x })("x * 2");
60-
const result = compile(double, { x });
61-
62-
expect(result).toHaveLength(2);
63-
expect(result[0]).toEqual(["x"]);
64-
expect(result[1]).toBe("$0*2");
65-
});
66-
67-
test("compile: complex placeholder replacement", () => {
68-
const x = variable(z.number());
69-
const xy = variable(z.number());
70-
71-
// xy 是较长的名称,通过 AST 解析可以正确区分
72-
const expr1 = expr({ xy, x })("xy + x");
73-
const result = compile(expr1, { xy, x });
74-
75-
expect(result).toHaveLength(2);
76-
expect(result[0]).toEqual(["xy", "x"]);
77-
// xy 应该被替换为 $0,x 应该被替换为 $1
78-
expect(result[1]).toBe("$0+$1");
79-
});
80-
81-
test("compile: detects undefined variable reference", () => {
82-
const x = variable(z.number());
83-
const y = variable(z.number());
84-
85-
const sum = expr({ x, y })("x + y + z");
86-
87-
expect(() => {
88-
compile(sum, { x, y });
89-
}).toThrow();
90-
});
91-
92-
test("compile: variable order matches declaration", () => {
93-
const a = variable(z.number());
94-
const b = variable(z.number());
95-
const c = variable(z.number());
96-
97-
const expr1 = expr({ a, b, c })("a + b + c");
98-
const result = compile(expr1, { a, b, c });
26+
// 变量被替换为 $0, $1 等
27+
expect(result[1]).toBe("$0+$1");
28+
});
9929

100-
expect(result[0]).toEqual(["a", "b", "c"]);
101-
// 规范化输出: a+b+c -> $0+$1+$2
102-
expect(result[1]).toBe("$0+$1+$2");
30+
test("变量顺序与声明顺序一致", () => {
31+
const a = variable(z.number());
32+
const b = variable(z.number());
33+
const c = variable(z.number());
34+
35+
const expr1 = expr({ a, b, c })("c + b + a");
36+
const result = compile(expr1, { a, b, c });
37+
38+
expect(result[0]).toEqual(["a", "b", "c"]);
39+
});
40+
41+
test("相似变量名正确区分", () => {
42+
const x = variable(z.number());
43+
const xy = variable(z.number());
44+
45+
// xy 不应该被 x 的替换影响
46+
const e = expr({ xy, x })("xy + x");
47+
const result = compile(e, { xy, x });
48+
49+
expect(result[0]).toEqual(["xy", "x"]);
50+
expect(result[1]).toBe("$0+$1");
51+
});
52+
});
53+
54+
describe("错误检测", () => {
55+
test("检测未定义的变量引用", () => {
56+
const x = variable(z.number());
57+
const y = variable(z.number());
58+
59+
const sum = expr({ x, y })("x + y + z");
60+
61+
expect(() => {
62+
compile(sum, { x, y });
63+
}).toThrow();
64+
});
65+
66+
test("检测表达式中引用不存在的上下文变量", () => {
67+
const x = variable(z.number());
68+
69+
const e1 = expr({ x })("x + 1");
70+
const e2 = expr({ e1 })("e1 + e2"); // e2 不存在
71+
72+
expect(() => {
73+
compile(e2, { x });
74+
}).toThrow();
75+
});
76+
});
77+
78+
describe("内联优化输出", () => {
79+
test("内联模式减少表达式数量", () => {
80+
const x = variable(z.number());
81+
const y = variable(z.number());
82+
83+
const sum = expr({ x, y })("x + y");
84+
const product = expr({ x, y })("x * y");
85+
const result = expr({ sum, product })("sum + product");
86+
87+
const inlined = compile(result, { x, y }); // 默认内联
88+
const notInlined = compile(result, { x, y }, { inline: false });
89+
90+
expect(inlined.length).toBe(2);
91+
expect(notInlined.length).toBe(4);
92+
});
93+
94+
test("非内联模式保留所有中间表达式", () => {
95+
const x = variable(z.number());
96+
const y = variable(z.number());
97+
98+
const sum = expr({ x, y })("x + y");
99+
const product = expr({ x, y })("x * y");
100+
const result = expr({ sum, product })("sum + product");
101+
102+
const compiled = compile(result, { x, y }, { inline: false });
103+
104+
expect(compiled).toHaveLength(4);
105+
expect(compiled[0]).toEqual(["x", "y"]);
106+
expect(compiled[1]).toBe("$0+$1"); // sum
107+
expect(compiled[2]).toBe("$0*$1"); // product
108+
expect(compiled[3]).toBe("$2+$3"); // result
109+
});
110+
});
111+
112+
describe("AST 规范化", () => {
113+
test("输出不包含多余空格", () => {
114+
const x = variable(z.number());
115+
const y = variable(z.number());
116+
117+
// 原始表达式有空格
118+
const e = expr({ x, y })("x + y * 2");
119+
const result = compile(e, { x, y });
120+
121+
// 输出应该是规范化的
122+
expect(result[1]).toBe("$0+$1*2");
123+
});
124+
125+
test("保留必要的括号", () => {
126+
const x = variable(z.number());
127+
const y = variable(z.number());
128+
129+
const e = expr({ x, y })("(x + y) * 2");
130+
const result = compile(e, { x, y });
131+
132+
// 括号应该被保留以保持正确的运算顺序
133+
expect(result[1]).toBe("($0+$1)*2");
134+
});
135+
});
103136
});

0 commit comments

Comments
 (0)