Skip to content

Commit 6b016ff

Browse files
committed
[Coding Agent] Update API Compatibility Claude Code Skills
1 parent beff399 commit 6b016ff

14 files changed

Lines changed: 2634 additions & 1547 deletions

File tree

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
name: add-compatibility-test
3+
description: 负责《Paddle API 对齐 PyTorch 项目》中 Step3:兼容性测试,为已修改的 Paddle API 添加兼容性单测并执行验证,确保 API 的 Paddle 用法与 PyTorch 用法均能正常工作。
4+
disable-model-invocation: false
5+
---
6+
7+
# 一、标准工作流程
8+
9+
## Step 1:编写测试用例(仅首次执行)
10+
11+
`${ROOT_DIR}/Paddle/test/legacy_test/` 目录下找到 `test_api_compatibility[1-9]\.py` 中数字最大的文件,在该文件中添加测试。
12+
13+
严格按以下模板编写测试类:
14+
15+
### 测试模板
16+
17+
```python
18+
class Test<APIName>API(unittest.TestCase):
19+
def setUp(self):
20+
# If not use random seed, remove setUp
21+
np.random.seed(2025)
22+
self.np_x = np.random.rand(...).astype(...)
23+
24+
def test_dygraph_Compatibility(self):
25+
paddle.disable_static()
26+
x = paddle.to_tensor(self.np_x)
27+
28+
# 1. Paddle Positional arguments
29+
out1 = paddle.<api_name>(x, ...)
30+
31+
# 2. Paddle keyword arguments
32+
out2 = paddle.<api_name>(x=x, ...)
33+
34+
# 3. Pytorch Positional arguments (only if order different with paddle args)
35+
out3 = paddle.<api_name>(x, ...)
36+
37+
# 4. PyTorch keyword arguments (alias)
38+
out4 = paddle.<api_name>(input=x, dim=...)
39+
40+
# 5. Mixed arguments
41+
out5 = paddle.<api_name>(x, axis=...)
42+
43+
# 6. out parameter test (only if supported)
44+
out6 = paddle.empty_like(x)
45+
out7 = paddle.<api_name>(x, ..., out=out6)
46+
47+
# 7. Tensor method - args (only if supported)
48+
out8 = x.<api_name>(...)
49+
50+
# 8. Tensor method - kwargs (only if supported)
51+
out9 = x.<api_name>(axis=...)
52+
53+
# Verify all outputs
54+
for out in [out1, out2, out3, out4, out5, out6, out7, out8, out9]:
55+
np.testing.assert_allclose(out.numpy(), ...)
56+
57+
paddle.enable_static()
58+
59+
def test_static_Compatibility(self):
60+
paddle.enable_static()
61+
main = paddle.static.Program()
62+
startup = paddle.static.Program()
63+
with paddle.static.program_guard(main, startup):
64+
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
65+
66+
# Create multiple outputs
67+
out1 = paddle.<api_name>(x, ...)
68+
out2 = paddle.<api_name>(x=x, ...)
69+
out3 = paddle.<api_name>(input=x, dim=...)
70+
71+
exe = paddle.static.Executor()
72+
fetches = exe.run(
73+
main,
74+
feed={"x": self.np_x},
75+
fetch_list=[out1, out2, out3],
76+
)
77+
78+
# Verify all outputs
79+
for out in fetches:
80+
np.testing.assert_allclose(out, ...)
81+
```
82+
83+
### 测试规范
84+
85+
**动态图模式必测项**
86+
1. ✅ Paddle 位置参数(全部位置参数)
87+
2. ✅ Paddle 关键字参数(全部关键字参数)
88+
3. ✅ PyTorch 位置参数(如果 PyTorch 与 Paddle 参数顺序不同)
89+
4. ✅ PyTorch 关键字参数(使用参数别名)
90+
5. ✅ 混合参数(如果参数量>=2,位置+关键字)
91+
6. ✅ out 参数(如果 API 支持,inplace API 无需测)
92+
7. ✅ 类方法 PyTorch 位置参数(如果有类方法)
93+
8. ✅ 类方法 PyTorch 关键字参数(如果有类方法)
94+
95+
**静态图模式必测项**(inplace API 无需测):
96+
1. ✅ Paddle 位置参数(全部位置参数)
97+
2. ✅ Paddle 关键字参数(全部关键字参数)
98+
3. ✅ PyTorch 位置参数(如果 PyTorch 与 Paddle 参数顺序不同)
99+
4. ✅ PyTorch 关键字参数(使用参数别名)
100+
5. ✅ 类方法 PyTorch 位置参数(如果有类方法)
101+
6. ✅ 类方法 PyTorch 关键字参数(如果有类方法)
102+
103+
### 测试注意事项
104+
105+
1. **可选测试项判断**:根据 API 实际支持的用法判断是否需要添加对应测试项
106+
2. **顺序要求**:添加测试项需遵循上述顺序,不要打乱
107+
3. **输出编号连贯**:输出结果序号需要保持连贯,每个输出结果均需检验
108+
4. **避免重复**:对于内容相同的测试项,不要重复添加
109+
5. **inplace API 特殊处理**:inplace API 只需测试动态图,无需测试静态图
110+
111+
### 特殊参数测试
112+
113+
**pin_memory 参数测试**
114+
```python
115+
if paddle.device.is_compiled_with_cuda() or paddle.device.is_compiled_with_xpu():
116+
x = paddle.xxx([2], device="gpu", pin_memory=True)
117+
self.assertTrue("pinned" in str(x.place))
118+
```
119+
120+
**device 参数测试**
121+
```python
122+
# 测试不同设备
123+
if paddle.device.is_compiled_with_cuda():
124+
out_cpu = paddle.<api_name>(x, device="cpu")
125+
out_gpu = paddle.<api_name>(x, device="gpu:0")
126+
```
127+
128+
## Step 2:编译并运行单测(每次改动均需执行)
129+
130+
单测编写完成后,按以下命令验证执行:
131+
132+
```bash
133+
cd ${ROOT_DIR}/Paddle/build
134+
cmake .. && make -j$(nproc)
135+
python test_xxx.py
136+
```
137+
138+
根据报错信息修改测试用例或回退,确保所有测试用例通过。每次修改后均需要重新执行本步骤。
139+
140+
**编译注意事项**
141+
- 无需重装,直接生效(勿执行 setup/install 等安装操作)
142+
- 勿删除 build 目录(否则增量编译失效,编译时间极长)
143+
144+
# 二、技术背景知识
145+
146+
### 测试框架说明
147+
148+
- **unittest**:Python 标准库测试框架,本步骤采用该框架
149+
- **动态图测试**:通过 `paddle.disable_static()``paddle.enable_static()` 切换模式
150+
- **静态图测试**:通过 `paddle.static.program_guard` 创建程序上下文
151+
152+
### 常用断言方法
153+
154+
```python
155+
# 数值比对
156+
np.testing.assert_allclose(actual, expected, rtol=1e-5, atol=1e-8)
157+
np.testing.assert_array_equal(actual, expected)
158+
159+
# 布尔断言
160+
self.assertTrue(condition)
161+
self.assertFalse(condition)
162+
self.assertEqual(a, b)
163+
self.assertIsInstance(obj, cls)
164+
```
165+
166+
### 测试数据生成
167+
168+
```python
169+
# 随机数据
170+
np.random.seed(2025)
171+
self.np_x = np.random.rand(2, 3).astype(np.float32)
172+
173+
# 特定形状
174+
self.shape = [2, 3, 4]
175+
self.dtype = np.float32
176+
```
177+
178+
# 三、注意事项
179+
180+
1. 严格按标准工作流程执行,杜绝自行臆断和跳过步骤
181+
2. `${ROOT_DIR}` 变量表示根目录,需自行替换为实际路径,若未通过 ROOT_DIR 指定,则均为相对于 ROOT_DIR 的路径
182+
3. 不要新建测试文件,直接在已有的 `test_api_compatibility[1-9]\\.py` 中添加
183+
4. 测试类命名遵循 `Test<APIName>API` 格式,如 `TestArgmaxAPI`
184+
5. 确保测试覆盖所有新增的参数别名和参数用法
185+
186+
# 四、异常回退原则
187+
188+
当本步骤多次尝试仍无法通过时,需要根据错误信息诊断问题根源:
189+
190+
1. **若判断为测试用例编写有误**(如断言逻辑错误、测试数据错误):
191+
- 直接在本步骤修正测试用例
192+
- 无需回退到其他步骤
193+
194+
2. **若判断为代码实现有误**(如参数处理逻辑错误、类型转换失败等):
195+
- 回退到总步骤 Step2(代码修改)调整实现方式
196+
- 回退后再进入本步骤(Step3),则只需执行:编译并运行,其他步骤无需执行
197+
198+
3. **若判断为方案选择错误**(如当前方案不适用、底层不支持等):
199+
- 回退到总步骤 Step1(方案决策)重新决策
200+
- 回退后再进入本步骤(Step3),则只需执行:编译并运行,其他步骤无需执行
201+
202+
# 五、常见问题处理
203+
204+
### Q1:测试报错 "unexpected keyword argument"
205+
206+
**错误现象**
207+
```
208+
TypeError: xxx() got an unexpected keyword argument 'out'
209+
```
210+
211+
**解决方法**
212+
检查 API 签名是否正确添加了 out 参数,或参数名是否拼写正确。
213+
214+
### Q2:pin_memory 测试报错 "Pinning memory is not supported"
215+
216+
**错误现象**
217+
```
218+
RuntimeError: Pinning memory is not supported for Place(cpu)
219+
```
220+
221+
**解决方法**
222+
`pin_memory=True` 仅在 GPU/XPU 设备上有意义。确保测试逻辑中正确添加了环境判断:
223+
```python
224+
if paddle.device.is_compiled_with_cuda() or paddle.device.is_compiled_with_xpu():
225+
x = paddle.xxx([2], device="gpu", pin_memory=True)
226+
self.assertTrue("pinned" in str(x.place))
227+
```
228+
229+
### Q3:静态图测试失败 "object has no attribute"
230+
231+
**错误现象**
232+
```
233+
AttributeError: 'OpResult' object has no attribute 'pin_memory'
234+
```
235+
236+
**解决方法**
237+
某些动态图专用的方法需要在 `in_dynamic_mode()` 保护下执行:
238+
```python
239+
if in_dynamic_mode():
240+
tensor = tensor.pin_memory()
241+
```
242+
243+
### Q4:数值比对失败
244+
245+
**错误现象**
246+
```
247+
AssertionError: Not equal to tolerance rtol=1e-5, atol=1e-8
248+
```
249+
250+
**解决方法**
251+
1. 检查输入数据是否正确生成
252+
2. 检查预期输出值是否正确
253+
3. 适当调整容差参数 `rtol``atol`

0 commit comments

Comments
 (0)