testing-codegen

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Purpose

目的

Use this skill for testing, code generation, and preparing contributions. Covers snapshot testing with
insta
, code generation commands, and changeset creation.
本技能适用于测试、代码生成以及准备贡献代码的场景,涵盖使用
insta
进行快照测试、代码生成命令以及变更集创建等内容。

Prerequisites

前置条件

  1. Install required tools:
    just install-tools
    (installs
    cargo-insta
    )
  2. Install pnpm:
    corepack enable
    and
    pnpm install
    in repo root
  3. Understand which changes require code generation
  1. 安装所需工具:
    just install-tools
    (会安装
    cargo-insta
  2. 安装pnpm:在仓库根目录执行
    corepack enable
    pnpm install
  3. 了解哪些修改需要执行代码生成

Common Workflows

常见工作流

Run Tests

运行测试

shell
undefined
shell
undefined

Run all tests

运行所有测试

cargo test
cargo test

Run tests for specific crate

运行特定 crate 的测试

cd crates/biome_js_analyze cargo test
cd crates/biome_js_analyze cargo test

Run specific test

运行特定测试用例

cargo test quick_test
cargo test quick_test

Show test output (for dbg! macros)

显示测试输出(用于 dbg! 宏)

cargo test quick_test -- --show-output
cargo test quick_test -- --show-output

Run tests with just (uses CI test runner)

使用 just 运行测试(使用 CI 测试运行器)

just test
just test

Test specific crate with just

使用 just 测试特定 crate

just test-crate biome_cli
undefined
just test-crate biome_cli
undefined

Quick Test for Rules

规则快速测试

Fast iteration during development:
rust
// In crates/biome_js_analyze/tests/quick_test.rs
// Modify the quick_test function:

const SOURCE: &str = r#"
const x = 1;
var y = 2;
"#;

let rule_filter = RuleFilter::Rule("nursery", "noVar");
Run:
shell
just qt biome_js_analyze
开发过程中的快速迭代:
rust
// 路径:crates/biome_js_analyze/tests/quick_test.rs
// 修改 quick_test 函数:

const SOURCE: &str = r#"
const x = 1;
var y = 2;
"#;

let rule_filter = RuleFilter::Rule("nursery", "noVar");
运行命令:
shell
just qt biome_js_analyze

Quick Test for Parser Development

解析器开发快速测试

IMPORTANT: Use this instead of building full Biome binary for syntax inspection - it's much faster!
For inspecting AST structure when implementing parsers or working with embedded languages:
rust
// In crates/biome_html_parser/tests/quick_test.rs
// Modify the quick_test function:

#[test]
pub fn quick_test() {
    let code = r#"<button on:click={handleClick}>Click</button>"#;
    
    let source_type = HtmlFileSource::svelte();
    let options = HtmlParseOptions::from(&source_type);
    let root = parse_html(code, options);
    let syntax = root.syntax();
    
    dbg!(&syntax, root.diagnostics(), root.has_errors());
}
Run:
shell
just qt biome_html_parser
The
dbg!
output shows the full AST tree structure, helping you understand:
  • How directives/attributes are parsed (e.g.,
    HtmlAttribute
    vs
    SvelteBindDirective
    )
  • Whether values use
    HtmlString
    (quotes) or
    HtmlTextExpression
    (curly braces)
  • Token ranges and offsets needed for proper snippet creation
  • Node hierarchy and parent-child relationships
重要提示: 当需要检查语法时,请使用该方式替代构建完整的Biome二进制文件,速度会快很多!
在实现解析器或处理嵌入式语言时,用于检查AST结构:
rust
// 路径:crates/biome_html_parser/tests/quick_test.rs
// 修改 quick_test 函数:

#[test]
pub fn quick_test() {
    let code = r#"<button on:click={handleClick}>Click</button>"#;
    
    let source_type = HtmlFileSource::svelte();
    let options = HtmlParseOptions::from(&source_type);
    let root = parse_html(code, options);
    let syntax = root.syntax();
    
    dbg!(&syntax, root.diagnostics(), root.has_errors());
}
运行命令:
shell
just qt biome_html_parser
dbg!
输出会显示完整的AST树结构,帮助你理解:
  • 指令/属性的解析方式(例如
    HtmlAttribute
    SvelteBindDirective
    的区别)
  • 值是否使用
    HtmlString
    (带引号)或
    HtmlTextExpression
    (带大括号)
  • 正确生成代码片段所需的令牌范围和偏移量
  • 节点层级与父子关系

Snapshot Testing with Insta

基于Insta的快照测试

Run tests and generate snapshots:
shell
cargo test
Review generated/changed snapshots:
shell
undefined
运行测试并生成快照:
shell
cargo test
查看已生成/修改的快照:
shell
undefined

Interactive review (recommended)

交互式查看(推荐)

cargo insta review
cargo insta review

Accept all changes

接受所有变更

cargo insta accept
cargo insta accept

Reject all changes

拒绝所有变更

cargo insta reject
cargo insta reject

Review for specific test

查看特定测试的快照

cargo insta review --test-runner nextest

Snapshot commands:
- `a` - accept snapshot
- `r` - reject snapshot
- `s` - skip snapshot
- `q` - quit
cargo insta review --test-runner nextest

快照命令说明:
- `a` - 接受快照
- `r` - 拒绝快照
- `s` - 跳过快照
- `q` - 退出

Test Lint Rules

测试Lint规则

shell
undefined
shell
undefined

Test specific rule by name

按名称测试特定规则

just test-lintrule noVar
just test-lintrule noVar

Run from analyzer crate

进入分析器 crate 后运行测试

cd crates/biome_js_analyze cargo test
undefined
cd crates/biome_js_analyze cargo test
undefined

Create Test Files

创建测试文件

Single file tests - Place in
tests/specs/{group}/{rule}/
:
tests/specs/nursery/noVar/
├── invalid.js           # Code that triggers the rule
├── valid.js             # Code that doesn't trigger
└── options.json         # Optional: rule configuration
Multiple test cases - Use
.jsonc
files with arrays:
jsonc
// tests/specs/nursery/noVar/invalid.jsonc
[
  "var x = 1;",
  "var y = 2; var z = 3;",
  "for (var i = 0; i < 10; i++) {}"
]
Test-specific options - Create
options.json
:
json
{
  "linter": {
    "rules": {
      "nursery": {
        "noVar": {
          "level": "error",
          "options": {
            "someOption": "value"
          }
        }
      }
    }
  }
}
单文件测试 - 放置在
tests/specs/{group}/{rule}/
目录下:
tests/specs/nursery/noVar/
├── invalid.js           # 会触发规则的代码
├── valid.js             # 不会触发规则的代码
└── options.json         # 可选:规则配置
多测试用例 - 使用包含数组的
.jsonc
文件:
jsonc
// tests/specs/nursery/noVar/invalid.jsonc
[
  "var x = 1;",
  "var y = 2; var z = 3;",
  "for (var i = 0; i < 10; i++) {}"
]
测试专属配置 - 创建
options.json
文件:
json
{
  "linter": {
    "rules": {
      "nursery": {
        "noVar": {
          "level": "error",
          "options": {
            "someOption": "value"
          }
        }
      }
    }
  }
}

Code Generation Commands

代码生成命令

After modifying analyzers/lint rules:
shell
just gen-analyzer
This updates:
  • Rule registrations
  • Configuration schemas
  • Documentation exports
  • TypeScript bindings
After modifying grammar (.ungram files):
shell
undefined
修改分析器/lint规则后:
shell
just gen-analyzer
该命令会更新:
  • 规则注册信息
  • 配置Schema
  • 文档导出内容
  • TypeScript绑定
修改语法文件(.ungram)后:
shell
undefined

Specific language

特定语言

just gen-grammar html
just gen-grammar html

Multiple languages

多种语言

just gen-grammar html css
just gen-grammar html css

All languages

所有语言

just gen-grammar

**After modifying formatters:**
```shell
just gen-formatter html
After modifying configuration:
shell
just gen-bindings
Generates TypeScript types and JSON schema.
Full codegen (rarely needed):
shell
just gen-all
Before committing:
shell
just ready
Runs full codegen + format + lint (takes time).
Or run individually:
shell
just f  # Format Rust and TOML
just l  # Lint code
just gen-grammar

**修改格式化器后:**
```shell
just gen-formatter html
修改配置后:
shell
just gen-bindings
生成TypeScript类型与JSON Schema。
完整代码生成(很少需要):
shell
just gen-all
提交前检查:
shell
just ready
运行完整代码生成 + 格式化 + 检查(耗时较长)。
也可以单独运行:
shell
just f  # 格式化Rust与TOML代码
just l  # 代码检查

Create Changeset

创建变更集(Changeset)

For user-visible changes (bug fixes, new features):
shell
just new-changeset
This prompts for:
  1. Package selection: Usually
    @biomejs/biome
  2. Change type:
    • patch
      - Bug fixes
    • minor
      - New features
    • major
      - Breaking changes (requires targeting
      next
      branch)
  3. Description: What changed (used in CHANGELOG)
Changeset writing guidelines:
  • Be concise and clear (1-3 sentences)
  • Start bug fixes with:
    Fixed [#issue](link): ...
  • Use past tense for your actions: "Added", "Fixed", "Changed"
  • Use present tense for Biome behavior: "Biome now supports..."
  • Include code examples for new rules/features
  • Link to rules:
    [useConst](https://biomejs.dev/linter/rules/use-const/)
  • End sentences with periods
Example changeset:
markdown
---
"@biomejs/biome": patch
---

Fixed [#1234](https://github.com/biomejs/biome/issues/1234): The rule [`noVar`](https://biomejs.dev/linter/rules/no-var/) now correctly handles variables in for loops.

Biome now analyzes the scope of loop variables properly.
Edit changeset - Files created in
.changeset/
directory, edit them directly.
针对用户可见的变更(bug修复、新功能):
shell
just new-changeset
该命令会提示以下信息:
  1. 包选择:通常选择
    @biomejs/biome
  2. 变更类型
    • patch
      - bug修复
    • minor
      - 新功能
    • major
      - 破坏性变更(需要基于
      next
      分支开发)
  3. 描述信息:变更内容(会被用于CHANGELOG)
变更集编写指南:
  • 简洁清晰(1-3句话)
  • bug修复以
    Fixed [#issue](链接): ...
    开头
  • 描述自身操作时使用过去式:"Added"、"Fixed"、"Changed"
  • 描述Biome行为时使用现在式:"Biome now supports..."
  • 新规则/功能需包含代码示例
  • 链接到规则:
    [useConst](https://biomejs.dev/linter/rules/use-const/)
  • 句子以句号结尾
示例变更集:
markdown
---
"@biomejs/biome": patch
---

Fixed [#1234](https://github.com/biomejs/biome/issues/1234): 规则[`noVar`](https://biomejs.dev/linter/rules/no-var/)现在能正确处理for循环中的变量。

Biome现在会正确分析循环变量的作用域。
编辑变更集 - 变更集文件创建在
.changeset/
目录下,可直接编辑。

Run Doctests

运行文档测试

Test code examples in documentation comments:
shell
just test-doc
测试文档注释中的代码示例:
shell
just test-doc

Debugging Tests

测试调试

Use
dbg!()
macro in Rust code:
rust
fn some_function() -> &'static str {
    let some_variable = "debug_value";
    dbg!(&some_variable);  // Prints during test
    some_variable
}
Run with output:
shell
cargo test test_name -- --show-output
在Rust代码中使用
dbg!()
宏:
rust
fn some_function() -> &'static str {
    let some_variable = "debug_value";
    dbg!(&some_variable);  // 测试时会打印该值
    some_variable
}
带输出运行测试:
shell
cargo test test_name -- --show-output

Tips

小贴士

  • Snapshot organization: Group by feature/rule in separate directories
  • Test both valid and invalid: Create both
    valid.js
    and
    invalid.js
    files
  • Options per folder:
    options.json
    applies to all tests in that folder
  • .jsonc
    arrays
    : Use for multiple quick test cases in script context (no imports/exports)
  • Code generation order: Grammar → Analyzer → Formatter → Bindings
  • CI compatibility: Use
    just
    commands when possible (matches CI)
  • Changeset timing: Create before opening PR, can edit after
  • Snapshot review: Always review snapshots carefully - don't blindly accept
  • Test performance: Use
    #[ignore]
    for slow tests, run with
    cargo test -- --ignored
  • Parser inspection: Use
    just qt <package>
    to run quick_test and inspect AST, NOT full Biome builds (much faster)
  • String extraction: Use
    inner_string_text()
    for quoted strings, not
    text_trimmed()
    (which includes quotes)
  • Legacy syntax: Ask users before implementing deprecated/legacy syntax - wait for user demand
  • Borrow checker: Avoid temporary borrows that get dropped - use
    let binding = value; binding.method()
    pattern
  • 快照组织:按功能/规则分组,放在单独的目录中
  • 测试覆盖有效与无效代码:同时创建
    valid.js
    invalid.js
    文件
  • 目录级配置
    options.json
    会应用到该目录下的所有测试
  • .jsonc
    数组
    :适用于脚本上下文(无导入/导出)中的多个快速测试用例
  • 代码生成顺序:语法文件 → 分析器 → 格式化器 → 绑定
  • CI兼容性:尽可能使用
    just
    命令(与CI环境一致)
  • 变更集时机:在创建PR前创建,之后可编辑
  • 快照审查:务必仔细审查快照,不要盲目接受
  • 测试性能:对慢测试使用
    #[ignore]
    注解,运行时使用
    cargo test -- --ignored
  • 解析器检查:使用
    just qt <package>
    运行quick_test并查看AST,不要构建完整的Biome(速度快很多)
  • 字符串提取:使用
    inner_string_text()
    提取带引号的字符串,不要使用
    text_trimmed()
    (会包含引号)
  • 遗留语法:在实现已废弃/遗留语法前先询问用户,等待用户需求
  • 借用检查器:避免临时借用被提前释放,使用
    let binding = value; binding.method()
    模式

Common Test Patterns

常见测试模式

rust
// Snapshot test in rule file
#[test]
fn test_rule() {
    assert_lint_rule! {
        noVar,
        invalid => [
            "var x = 1;",
            "var y = 2;",
        ],
        valid => [
            "const x = 1;",
            "let y = 2;",
        ]
    }
}

// Quick test pattern
#[test]
#[ignore]  // Uncomment when using
fn quick_test() {
    const SOURCE: &str = r#"
        var x = 1;
    "#;
    
    let rule_filter = RuleFilter::Rule("nursery", "noVar");
    // Test runs with this configuration
}
rust
// 规则文件中的快照测试
#[test]
fn test_rule() {
    assert_lint_rule! {
        noVar,
        invalid => [
            "var x = 1;",
            "var y = 2;",
        ],
        valid => [
            "const x = 1;",
            "let y = 2;",
        ]
    }
}

// 快速测试模式
#[test]
#[ignore]  // 使用时取消注释
fn quick_test() {
    const SOURCE: &str = r#"
        var x = 1;
    "#;
    
    let rule_filter = RuleFilter::Rule("nursery", "noVar");
    // 使用该配置运行测试
}

Code Generation Dependencies

代码生成依赖关系

When you modify...Run...
.ungram
grammar files
just gen-grammar <lang>
Lint rules in
*_analyze
just gen-analyzer
Formatter in
*_formatter
just gen-formatter <lang>
Configuration types
just gen-bindings
Before committing
just f && just l
Full rebuild
just gen-all
(slow)
修改内容...运行命令...
.ungram
语法文件
just gen-grammar <lang>
*_analyze
中的Lint规则
just gen-analyzer
*_formatter
中的格式化器
just gen-formatter <lang>
配置类型
just gen-bindings
提交前检查
just f && just l
完整重建
just gen-all
(速度慢)

References

参考资料

  • Main testing guide:
    CONTRIBUTING.md
    § Testing
  • Insta documentation: https://insta.rs
  • Analyzer testing:
    crates/biome_analyze/CONTRIBUTING.md
    § Testing
  • Changeset guide:
    CONTRIBUTING.md
    § Changelog
  • 主测试指南:
    CONTRIBUTING.md
    § Testing
  • Insta文档:https://insta.rs
  • 分析器测试:
    crates/biome_analyze/CONTRIBUTING.md
    § Testing
  • 变更集指南:
    CONTRIBUTING.md
    § Changelog