#traits #compiler-plugin #test

nightly trait_tests

允许测试定义在特质之上的编译器插件

9 个版本

使用旧的 Rust 2015

0.3.3 2018 年 6 月 3 日
0.3.2 2018 年 4 月 24 日
0.2.1 2018 年 4 月 17 日
0.1.2 2018 年 3 月 31 日

#35 in #compiler-plugin

MIT 许可证

18KB
285

trait_tests

一个编译器插件,允许在 Rust 的特质上定义测试。

有关示例测试套件的更多信息,请参阅 https://github.com/gilescope/iunit

为什么

更多的测试是好的,但更少的代码意味着更少的错误,因此我们希望在代码更少的情况下有更多的测试。这个crate试图打破反复为所有单独实现编写测试的N*M问题。

目标是发布一个带有标准测试的标准库,并逐渐形成一个人们发布带有他们的特质/接口的标准测试的生态系统。

警告:这仍然处于概念验证阶段。从V0.2开始,它作为procmacro实现,而不是编译器插件,因此它更接近在稳定版和nightly版上工作。

如何:在特质上定义测试

要创建一个特质测试,创建一个要测试的特质的子特质,并在其上创建静态函数。泛型参数应该具体化为您选择的一种类型,以帮助您进行测试。

#[trait_tests]
pub trait SetIteratorTests: Set<char> + Sized + IntoIterator<Item=char>
{
    fn test_move_iter()
    {
        let hs = {
            let mut hs = Self::new();
            hs.insert('a');
            hs.insert('b');
            hs
        };

        let v = hs.into_iter().collect::<Vec<char>>();
        assert!(v == ['a', 'b'] || v == ['b', 'a']);
    }
}

特质上的 #[test_traits] 属性当前会在特质中生成一个 test_all 函数

pub trait SetIteratorTests: Set<char> + Sized + IntoIterator<Item=char>
{
    fn test_all() {
        Self::test_move_iter();
        ..
    }
    
    ..
}

(如何将这些报告为单独的测试而不是作为一个运行尚是一个开放问题,但从堆栈跟踪中可以清楚地看出失败的测试来源。)

如何:测试您的实现

编译器将指导您实现测试所需的额外特质。由于某些特质是一起使用的,这可以确保您的实现是全面的。

安装

V0.3及其以后版本是两个proc macros:`#[trait_tests]` 用于定义测试,`#[impl_test]` 用于调用测试。

以下是如何在特质上定义一些测试的示例

#![feature(proc_macro)]
extern crate trait_tests;
use trait_tests::*;

trait Hello {
    fn get_greeting(&self) -> &str;
}

#[trait_tests]
trait HelloTests : Hello + Sized + Default {
    fn test_1() {
        assert!(Self::default().get_greeting().len() < 200);
    }
}

要运行与特质相关的测试,您需要

  1. 使用 `use` 引入测试,以便导入它们。
  2. 在 impl 中添加 `#[test_impl]`。
#![feature(proc_macro)]
extern crate trait_tests;
use trait_tests::*;

struct SpanishHelloImpl {}

#[test_impl]
impl Hello for SpanishHelloImpl {
    fn get_greeting(&self) -> &str { "Hola" }
}

特质测试编写指南

由于 Rust 在其接口上包含静态函数,因此创建接口测试比您想象的要容易。随着越来越多的人编写特质测试,我确信我们将发现一些有效的模式。

目前,提示是

  • 尽量使用尽可能少的辅助接口来编写特性测试。例如,尽可能使用 &&mut 引用,而不是限制测试只能在实现 Sized 特性的实现中运行。

工厂方法

要编写有用的测试,你通常需要依赖于一些静态方法来实例化你的特性。虽然 Default 可以帮助你编写一些测试,但理想情况下能够注入状态可能会有所帮助。std::iter::FromIterator 特性对于设置集合风格的特性非常有帮助。

开放问题和限制

  1. 我们如何让测试框架列出所有单个测试。
  2. 特性测试目前是公开的,而不是在 cfg(test) 下
  3. 依赖于尚未标准化的 procmacro(尽管希望很快),因此目前仅在 nightly 版本中可用。

特性测试示例

讨论!

所有反馈和贡献都极其欢迎!

相关讨论

依赖关系

~2MB
~47K SLoC