skills/check-test-code-quality/rules/R015/SKILL.md
# R015: Level参数缺省 - **规则编号**: R015 - **严重级别**: Warning - **规则复杂度**: complex(需要代码分析) - **问题类型**: it()函数缺少Level参数 - **修复方式**: 添加`Level.LEVEL*`参数 - **预期问题数量**: 1100+ ## 扫描范围 仅扫描测试文件: - `.test.ets` - ArkTS测试文件 - `.test.ts` - TypeScript测试文件 - `.test.js` - JavaScript测试文件 ## 问题描述 `it()`函数声明时缺少`Level.LEVEL*`参数,不符合编码规范要求。每个测试用例必须指定测试级别。 ## 检测逻辑 ### 核心算法 ```python import re def scan_r015(file_path: str, content: str) -> list: """ 扫描文件中缺少Level参数的it()函数调用。 Args: file_path: 文件相对
npx skillsauth add openharmonyinsight/openharmony-skills skills/check-test-code-quality/rules/R015Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Level.LEVEL*参数仅扫描测试文件:
.test.ets - ArkTS测试文件.test.ts - TypeScript测试文件.test.js - JavaScript测试文件it()函数声明时缺少Level.LEVEL*参数,不符合编码规范要求。每个测试用例必须指定测试级别。
import re
def scan_r015(file_path: str, content: str) -> list:
"""
扫描文件中缺少Level参数的it()函数调用。
Args:
file_path: 文件相对路径
content: 文件完整内容
Returns:
问题列表,每条包含 rule, type, severity, file, line, testcase, snippet, suggestion
"""
issues = []
lines = content.split('\n')
i = 0
while i < len(lines):
line = lines[i]
# 匹配it()函数调用的起始行
if re.search(r'\bit\s*\(\s*["\']', line):
# 检查当前行是否已包含Level.LEVEL
if 'Level.LEVEL' in line:
i += 1
continue
# 如果行末以逗号结尾,Level参数可能在下一行,不报告
if line.rstrip().endswith(','):
i += 1
continue
# 提取it()声明块(可能跨多行)以获取完整参数列表
it_block, end_idx = extract_it_declaration(lines, i)
if it_block and 'Level.LEVEL' in it_block:
i = end_idx + 1
continue
# 确认缺少Level参数,提取testcase名称
tc_match = re.search(r'\bit\s*\(\s*([\'"])([^\'"]+)\1', line)
tc_name = tc_match.group(2) if tc_match else '-'
snippet = line.strip()
if len(snippet) > 120:
snippet = snippet[:120] + '...'
issues.append({
'rule': 'R015',
'type': 'Level参数缺省',
'severity': 'Warning',
'file': file_path,
'line': i + 1,
'testcase': tc_name,
'snippet': snippet,
'suggestion': (
f"路径: {file_path}, 行号: {i + 1}, "
f"问题描述: it()函数缺少Level参数。"
f"请在it()的第二个参数位置添加Level.LEVEL0、Level.LEVEL1、"
f"Level.LEVEL2、Level.LEVEL3或Level.LEVEL4。"
),
})
i += 1
return issues
def extract_it_declaration(lines: list, start_idx: int) -> tuple:
"""
从起始行开始,提取完整的it()参数声明部分(直到遇到第一个 { )。
使用状态机跳过字符串字面量中的括号和逗号。
Args:
lines: 文件所有行
start_idx: it()起始行索引
Returns:
(it_declaration_text, end_line_index) 或 (None, start_idx)
"""
in_single = False
in_double = False
paren_depth = 0
found_open_paren = False
declaration_lines = []
for idx in range(start_idx, min(start_idx + 20, len(lines))):
line = lines[idx]
declaration_lines.append(line)
j = 0
while j < len(line):
c = line[j]
# 处理转义字符
if c == '\\' and (in_single or in_double):
j += 2
continue
# 处理字符串字面量
if c == "'" and not in_double:
in_single = not in_single
elif c == '"' and not in_single:
in_double = not in_double
elif not in_single and not in_double:
if c == '(':
paren_depth += 1
found_open_paren = True
elif c == ')':
paren_depth -= 1
elif c == '{':
# 遇到函数体开始的{,停止提取
if found_open_paren and paren_depth <= 0:
return '\n'.join(declaration_lines), idx
elif c == ',':
# 逗号在字符串外且括号平衡,可能Level在后续行
pass
j += 1
# 如果括号已经平衡且找到过开括号,停止
if found_open_paren and paren_depth <= 0:
return '\n'.join(declaration_lines), idx
return None, start_idx
在提取it()块时,字符串字面量中的{和}会干扰大括号计数,必须使用状态机跳过字符串内容。
错误做法(朴素大括号计数):
# 错误:字符串中的{和}被计入
brace_count += line.count('{') - line.count('}')
正确做法(状态机解析):
def count_braces_outside_strings(line: str) -> tuple:
"""只计算字符串外的{和}数量"""
in_single = False
in_double = False
open_count = 0
close_count = 0
i = 0
while i < len(line):
c = line[i]
if c == '\\' and (in_single or in_double):
i += 2
continue
if c == "'" and not in_double:
in_single = not in_single
elif c == '"' and not in_single:
in_double = not in_double
elif not in_single and not in_double:
if c == '{':
open_count += 1
elif c == '}':
close_count += 1
i += 1
return open_count, close_count
如果it()声明行以逗号结尾,Level参数可能在下一行,此时不应报告。
# 错误:行末有逗号,Level在下一行
it('test001',
Level.LEVEL0, # ← Level在下一行,不应报告
async (done: Function) => {
if line.rstrip().endswith(','):
# Level参数可能在下一行,跳过不报告
continue
// 错误1:缺少Level参数
it('test001', () => {
console.info('test001');
// ✗ 错误:缺少Level参数
});
// 错误2:缺少Level参数
it('testUrl[Symbol.iterator]()002', () => {
console.info('test002');
// ✗ 错误:缺少Level参数
});
// 错误3:缺少Level参数(使用function关键字)
it('test003', async function (done) {
console.info('test003');
done();
// ✗ 错误:缺少Level参数
});
// 错误4:缺少Level参数(使用TypeScript类型注解)
it('test004', async (done: Function) => {
console.info('test004');
done();
// ✗ 错误:缺少Level参数
});
// 正确1:包含Level.LEVEL0参数
it('test001', Level.LEVEL0, () => {
console.info('test001');
// ✓ 正确:包含Level参数
});
// 正确2:测试用例名称中包含括号也能正确识别Level参数
it('testUrl[Symbol.iterator]()002', Level.LEVEL0, () => {
console.info('test002');
// ✓ 正确:包含Level参数
});
// 正确3:Level在下一行(行末有逗号)
it('test003',
Level.LEVEL0, // ✓ 正确:Level在下一行
async (done: Function) => {
console.info('test003');
done();
});
// 正确4:使用Level.LEVEL1
it('test004', Level.LEVEL1, async (done: Function) => {
console.info('test004');
done();
// ✓ 正确:包含Level参数
});
// 正确5:使用Level.LEVEL2
it('test005', Level.LEVEL2, 0, () => {
expect(true).assertTrue();
// ✓ 正确:包含Level参数
});
{
'rule': 'R015',
'type': 'Level参数缺省',
'severity': 'Warning',
'file': 'rel/path.test.ets',
'line': 25,
'testcase': 'test001',
'snippet': "it('test001', () => {",
'suggestion': '路径: rel/path.test.ets, 行号: 25, 问题描述: it()函数缺少Level参数。请在it()的第二个参数位置添加Level.LEVEL0、Level.LEVEL1、Level.LEVEL2、Level.LEVEL3或Level.LEVEL4。'
}
| 列序 | 列名 | 示例 |
|------|------|------|
| 1 | 问题ID | R015 |
| 2 | 问题类型 | Level参数缺省 |
| 3 | 严重级别 | Warning |
| 4 | 文件路径 | web/DFX/log/entry/src/ohosTest/ets/test/Test.test.ets |
| 5 | 行号 | 25 |
| 6 | 所属用例 | test001 |
| 7 | 代码片段 | it('test001', () => { |
| 8 | 修复建议 | 路径: ..., 行号: 25, 问题描述: it()函数缺少Level参数。请在it()的第二个参数位置添加Level.LEVEL0... |
在it()函数的testcase名称之后、回调函数之前,添加Level.LEVEL*参数:
// 修复前
it('test001', () => {
// ...
});
// 修复后
it('test001', Level.LEVEL0, () => {
// ...
});
可选的Level级别:
Level.LEVEL0 - 最基础级别Level.LEVEL1Level.LEVEL2Level.LEVEL3Level.LEVEL4 - 最高级别来源: EXAMPLES.md
以下为补充示例(与上方已有示例互补):
错误示例:
// 错误:缺少Level参数
it('test001', () => {
console.info('test001');
// ✗ 错误:缺少Level参数
});
// 错误:测试用例名称中包含括号但仍缺少Level参数
it('testUrl[Symbol.iterator]()002', () => {
console.info('test002');
// ✗ 错误:缺少Level参数
});
正确示例:
// 正确:包含Level参数
it('test001', Level.LEVEL0, () => {
console.info('test001');
// ✓ 正确:包含Level参数
});
// 正确:测试用例名称中包含括号也能正确识别Level参数
it('testUrl[Symbol.iterator]()002', Level.LEVEL0, () => {
console.info('test002');
// ✓ 正确:包含Level参数
});
来源: IMPLEMENTATION_DETAILS.md
检测方法: 检查it()函数是否包含Level.LEVEL参数
注意: 如果行末是逗号,说明参数可能在下一行,不报错。
if re.search(r'\bit\s*\(\s*["\']', line):
if 'Level.LEVEL' not in line:
if not line.rstrip().endswith(','):
# 报告Level参数缺省
来源: V3_UPGRADE_GUIDE.md
development
Run local code quality checks covering a subset of OpenHarmony gate CI (copyright, CodeArts C/C++) plus additional local checks (pylint/flake8, shellcheck/bashate, gn format). Use before committing to reduce gate failures. Triggers on: /oh-precommit-codecheck, "门禁检查", "门禁预检", "检查代码", "run codecheck", "check code quality", "lint my code", "代码检查", or after completing code implementation. WHEN to use: before git commit, before creating PR, after modifying C/C++/Python/Shell/GN files, when gate CI fails with codecheck defects, or when you want to preview what gate will flag.
development
OpenHarmony PR full lifecycle workflow. Five modes: - Commit: standardized commit with DCO sign-off and Issue linking - Create PR: commit + push to fork + create Issue + create PR on upstream - Fix Codecheck: fetch gate CI codecheck defects from a PR and auto-fix them - Review PR: fetch a PR's changes to local for code review - Fix Review: fetch unresolved review comments from a PR and auto-fix them Triggers on: /oh-pr-workflow, "提交代码", "创建PR", "提个PR", "commit", "修复告警", "修复门禁", "修复codecheck", "fix codecheck", "review pr", "review这个pr", "看下这个pr", "检视pr", "修复review", "修复检视意见", "fix review", or a GitCode PR URL with fix/review intent.
testing
分析 HM Desktop PRD 文档,提取需求信息、验证完整性、检查章节顺序(需求来源→需求背景→需求价值分析→竞品分析→需求描述)、检查 KEP 定义、检测需求冲突并生成结构化分析报告。适用于用户请求:(1) 分析或审查 PRD 文档, (2) 从需求中提取 KEP 列表, (3) 检查 PRD 完整性或一致性, (4) 将需求映射到模块架构, (5) 验证 PRD 格式合规性, (6) 验证竞品分析章节完整性。关键词:PRD分析, requirement extraction, KEP验证, completeness check, chapter order validation, 竞品分析检查, analyze PRD, 需求提取, 完整性检查, 章节顺序验证
development
基于 PRD 文档自动生成鸿蒙系统设计文档,包括架构设计文档和功能设计文档。生成前会分析 OpenHarmony 存量代码结构,确保与现有架构兼容。架构设计文档第2章必须为竞品方案分析,位于需求背景之后。适用于用户请求:(1) 生成架构设计文档, (2) 生成功能设计文档, (3) 从 PRD 生成设计文档, (4) 创建系统架构设计, (5) 编写功能规格说明, (6) 分析 OH 代码结构。关键词:architecture design, functional design, design doc, 竞品方案分析, OpenHarmony code analysis, 架构设计, 功能设计, 设计文档生成, OH代码分析, analyze codebase, competitor analysis