Rust测试工具库lance-testing的使用,提供高效可靠的测试框架和功能检测

以下是关于Rust测试工具库lance-testing的使用介绍,提供高效可靠的测试框架和功能检测的内容:


Lance Logo

Lance Logo

Lance是一个现代列式数据格式,专为机器学习工作流程和数据集优化。Lance非常适合以下场景:

  1. 构建搜索引擎和特征存储。
  2. 需要高性能IO和随机访问的大规模ML训练。
  3. 存储、查询和检查深度嵌套的数据(如机器人数据或图像、点云等大型二进制数据)。

Lance的关键特性包括:

  • 高性能随机访问:比Parquet快100倍,同时不牺牲扫描性能。
  • 向量搜索:在毫秒级找到最近邻,并结合OLAP查询与向量搜索。
  • 零拷贝自动版本控制:无需额外基础设施即可管理数据版本。
  • 生态系统集成:支持Apache Arrow、Pandas、Polars、DuckDB、Ray、Spark等。

快速开始

安装

cargo add lance-testing

示例代码

以下是一个完整的测试示例,展示如何使用lance-testing进行高效测试:

use lance_testing::assert_batches_eq;
use arrow::record_batch::RecordBatch;
use arrow::array::{Int32Array, StringArray};
use arrow::datatypes::{DataType, Field, Schema};

// 创建一个测试用的RecordBatch
fn create_test_batch() -> RecordBatch {
    let schema = Schema::new(vec![
        Field::new("id", DataType::Int32, false),
        Field::new("name", DataType::Utf8, false),
    ]);

    let ids = Int32Array::from(vec![1, 2, 3]);
    let names = StringArray::from(vec!["Alice", "Bob", "Charlie"]);

    RecordBatch::try_new(
        schema.into(),
        vec![
            Arc::new(ids),
            Arc::new(names),
        ],
    ).unwrap()
}

// 测试两个RecordBatch是否相等
#[test]
fn test_record_batch_equality() {
    let batch1 = create_test_batch();
    let batch2 = create_test_batch();
    
    // 使用lance-testing提供的断言
    assert_batches_eq(&["id", "name"], &[batch1], &[batch2]);
}

// 测试向量搜索功能
#[test]
fn test_vector_search() {
    let vectors = vec![
        vec![1.0, 2.0, 3.0],
        vec![4.0, 5.0, 6.0],
        vec![7.0, 8.0, 9.0],
    ];
    
    let query = vec![1.1, 2.1, 3.1];
    let result = lance_testing::nearest_neighbors(&vectors, &query, 1);
    
    assert_eq!(result[0], 0); // 最近的向量是第一个
}

测试功能说明

  1. assert_batches_eq:用于比较两个RecordBatch是否相等,支持指定列的顺序。
  2. nearest_neighbors:提供向量搜索功能的测试支持,可以快速验证最近邻算法的正确性。
  3. 性能测试工具:内置性能测试框架,可以测量数据读取、写入和搜索的延迟。

基准测试

Lance在以下场景中表现优异:

  1. 向量搜索:对100个随机查询向量,平均响应时间<1ms(在2023款M2 MacBook Air上)。
  2. 对比Parquet:在随机访问场景中比Parquet快100倍。

平均延迟 召回率与延迟


为什么选择Lance?

Lance专为多阶段ML开发周期设计,解决了以下问题:

  • 学术界常用的XML/JSON格式难以集成到数据基础设施中。
  • 工业界使用的数据湖(如Delta Lake、Iceberg)需要转换为训练友好格式(如TFRecord)。
  • Lance提供了统一的格式,支持从数据收集到模型部署的全流程。

社区案例

Lance目前被以下项目用于生产环境:

  • LanceDB:一个无服务器、低延迟的ML应用向量数据库。
  • 领先的多模态生成式AI公司,用于处理PB级多模态数据。
  • 自动驾驶公司,用于大规模多模态数据的存储和检索。

总结

lance-testing提供了强大的测试工具和框架,特别适合需要高性能数据访问和向量搜索的ML应用。通过上述示例和工具,开发者可以快速验证功能的正确性和性能。


完整示例代码

use std::sync::Arc;
use lance_testing::{assert_batches_eq, nearest_neighbors};
use arrow::{
    array::{Int32Array, StringArray, Float32Array},
    datatypes::{DataType, Field, Schema},
    record_batch::RecordBatch,
};

/// 创建测试数据批次 - 包含ID和名称
fn create_user_batch() -> RecordBatch {
    let schema = Schema::new(vec![
        Field::new("id", DataType::Int32, false),
        Field::new("name", DataType::Utf8, false),
    ]);

    RecordBatch::try_new(
        schema.into(),
        vec![
            Arc::new(Int32Array::from(vec![1, 2, 3])),
            Arc::new(StringArray::from(vec!["Alice", "Bob", "Charlie"])),
        ],
    ).unwrap()
}

/// 创建测试向量数据
fn create_vector_data() -> (Vec<Vec<f32>>, Vec<f32>) {
    let vectors = vec![
        vec![1.0, 2.0, 3.0],
        vec![4.0, 5.0, 6.0],
        vec![7.0, 8.0, 9.0],
    ];
    let query = vec![1.1, 2.1, 3.1];
    (vectors, query)
}

/// 测试RecordBatch比较功能
#[test]
fn test_batch_comparison() {
    let batch1 = create_user_batch();
    let batch2 = create_user_batch();
    assert_batches_eq(&["id", "name"], &[batch1], &[batch2]);
}

/// 测试向量搜索功能
#[test]
fn test_vector_search_functionality() {
    let (vectors, query) = create_vector_data();
    let result = nearest_neighbors(&vectors, &query, 1);
    assert_eq!(result[0], 0, "应该返回最接近的向量索引");
}

/// 性能测试示例
#[test]
fn test_performance() {
    use std::time::Instant;
    
    let (vectors, query) = create_vector_data();
    let start = Instant::now();
    
    for _ in 0..100 {
        nearest_neighbors(&vectors, &query, 1);
    }
    
    let duration = start.elapsed();
    println!("100次向量搜索耗时: {:?}", duration);
    assert!(duration.as_millis() < 100, "性能不达标");
}

这个完整示例包含:

  1. 创建测试数据的工具函数
  2. RecordBatch比较测试
  3. 向量搜索功能测试
  4. 简单的性能测试示例
  5. 详细的注释说明每个测试的目的

代码中使用了lance-testing提供的主要功能:

  • assert_batches_eq 用于数据验证
  • nearest_neighbors 用于向量搜索测试
  • 性能测量工具用于验证响应时间

1 回复

Rust测试工具库lance-testing的使用指南

介绍

lance-testing是一个为Rust开发者设计的高效可靠的测试框架和功能检测工具库。它提供了丰富的测试功能和实用工具,旨在简化测试流程并提高测试代码的可维护性。

主要特性

  • 简洁的测试API设计
  • 强大的断言功能
  • 测试并行执行支持
  • 灵活的测试组织方式
  • 丰富的测试生命周期钩子
  • 内置性能测试支持

安装

在Cargo.toml中添加依赖:

[dependencies]
lance-testing = "0.3"

基本使用方法

简单测试示例

use lance_testing::test;

#[test]
fn test_addition() {
    let result = 2 + 2;
    assert_eq!(result, 4);
}

测试套件组织

use lance_testing::{test_suite, test};

test_suite!("数学运算测试", {
    test!("加法测试", {
        assert_eq!(1 + 1, 2);
    });

    test!("减法测试", {
        assert_eq!(5 - 3, 2);
    });
});

高级断言

use lance_testing::{assertions, test};

#[test]
fn test_string_operations() {
    let s = String::from("hello");
    assertions::assert_that!(s)
        .has_length(5)
        .starts_with("h")
        .ends_with("o");
}

异步测试

use lance_testing::{async_test, tokio};

#[async_test]
async fn test_async_operation() {
    let result = some_async_function().await;
    assert!(result.is_ok());
}

性能测试

use lance_testing::{bench, Bencher};

#[bench]
fn bench_vector_push(b: &mut Bencher) {
    let mut v = Vec::new();
    b.iter(|| {
        v.push(0);
    });
    assert_eq!(v.len(), b.iterations());
}

测试生命周期钩子

use lance_testing::{test_suite, before, after, test};

test_suite!("数据库测试", {
    before!(setup_database || {
        // 初始化数据库连接
    });

    after!(teardown_database || {
        // 清理数据库
    });

    test!("查询测试", {
        // 测试数据库查询
    });
});

高级功能

参数化测试

use lance_testing::{parameterized_test, test};

parameterized_test! {
    test_addition_cases,
    [
        (2, 2, 4),
        (3, 5, 8),
        (10, -5, 5),
    ],
    |a, b, expected| {
        assert_eq!(a + b, expected);
    }
}

测试过滤

可以通过属性标记测试并选择性地运行:

use lance_testing::{test, tag};

#[test]
#[tag("integration")]
fn test_database_integration() {
    // 集成测试代码
}

#[test]
#[tag("unit")]
fn test_business_logic() {
    // 单元测试代码
}

然后通过命令行参数运行特定标签的测试:

cargo test -- --tag integration

测试覆盖率支持

lance-testing可以与覆盖率工具集成:

cargo lance-coverage

最佳实践

  1. 使用test_suite!宏组织相关测试
  2. 为集成测试使用#[tag("integration")]
  3. 利用参数化测试减少重复代码
  4. 在性能关键部分使用#[bench]测试
  5. 使用生命周期钩子管理测试资源

总结

lance-testing为Rust开发者提供了全面的测试解决方案,从简单的单元测试到复杂的集成测试和性能测试。其简洁的API设计和丰富的功能可以帮助开发者编写更可靠、更易维护的测试代码。

完整示例demo

下面是一个综合使用lance-testing各种功能的完整示例:

// 导入lance-testing相关模块
use lance_testing::{
    test_suite, test, async_test, bench, Bencher,
    before, after, assertions, parameterized_test, tag
};
use tokio::time::{sleep, Duration};

// 测试套件示例
test_suite!("综合测试套件", {
    // 生命周期钩子示例
    before!(setup || {
        println!("测试开始前的准备工作");
    });

    after!(teardown || {
        println!("测试结束后的清理工作");
    });

    // 简单测试示例
    test!("基础数学运算", {
        assert_eq!(2 * 3, 6);
    });

    // 高级断言示例
    test!("字符串操作测试", {
        let name = "Alice".to_string();
        assertions::assert_that!(name)
            .has_length(5)
            .contains("lic");
    });

    // 异步测试示例
    #[async_test]
    async fn test_async_io() {
        let result = async {
            sleep(Duration::from_millis(100)).await;
            42
        }.await;
        assert_eq!(result, 42);
    }

    // 参数化测试示例
    parameterized_test! {
        test_multiplication_cases,
        [
            (1, 5, 5),
            (2, 6, 12),
            (0, 100, 0),
        ],
        |a, b, expected| {
            assert_eq!(a * b, expected);
        }
    }

    // 性能测试示例
    #[bench]
    fn bench_string_concat(b: &mut Bencher) {
        let mut s = String::new();
        b.iter(|| {
            s.push_str("test");
        });
    }

    // 带标签的测试示例
    #[test]
    #[tag("integration")]
    fn test_external_service() {
        // 模拟集成测试
        assert!(true);
    }
});

// 单独的性能测试模块
#[cfg(test)]
mod benchmarks {
    use super::*;
    use lance_testing::bench;

    #[bench]
    fn bench_vec_sort(b: &mut Bencher) {
        b.iter(|| {
            let mut v = vec![3, 1, 4, 1, 5, 9];
            v.sort();
            v
        });
    }
}

这个完整示例展示了:

  1. 测试套件的组织方式
  2. 测试生命周期管理
  3. 基本测试和高级断言
  4. 异步测试
  5. 参数化测试
  6. 性能测试
  7. 测试标签分类
  8. 模块化测试组织

对应的Cargo.toml配置:

[package]
name = "lance-testing-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
lance-testing = "0.3"
tokio = { version = "1.0", features = ["full"] }

[dev-dependencies]
lance-testing = { version = "0.3", features = ["full"] }

运行测试的命令:

# 运行所有测试
cargo test

# 只运行集成测试
cargo test -- --tag integration

# 运行性能测试
cargo test --bench
回到顶部