2016-05-05 10 views
3

ユニットテスト用の錆コード用のフィクスチャを提供する汎用ソリューションを作成しようとしています。私は、セットアップティアダウンメソッドを定義することができるマクロを考え出しました。これまでの私の解決策は次のとおりです。tyをRustマクロで使用する方法

struct FooTestFixture { 
    pub name : String 
} 

impl FooTestFixture { 
    fn setup() -> FooTestFixture { 
     FooTestFixture { name: String::from("Initialised") } 
    } 
} 

fn teardown(fixture : &mut FooTestFixture) { 
    fixture.name = "".to_string(); 
} 

macro_rules! unit_test { 
    ($name:ident $fixt:ident $expr:expr) => (
     #[test] 
     fn $name() { 
      let mut $fixt : FooTestFixture = FooTestFixture::setup(); 
      $expr; 

      teardown(&mut $fixt); 
     } 
    ) 
} 

unit_test! (heap_foo_fixture_should_be_initialised_using_macro f { 
    assert_eq!(f.name, "Initialised"); 
}); 

これは機能します。唯一の問題は、マクロunit_testが汎用ではなく、フィクスチャ名FooTestFixtureにバインドされていることです。これは、各テストモジュールがすべてのテストフィクスチャに対してこのマクロを再定義する必要があることを意味しますが、これは理想的ではありません。私ができるようにしたいのは、型変数を導入し、その型をマクロ展開で使用することです。私は種類を表す「TY」アイテムがあることを発見した、と私はこれを行うことができると思ったマクロにもっと踏み込んで...

macro_rules! unit_test { 
    ($name:ident $fixt:ident $ftype:ty $expr:expr) => (
     #[test] 
     fn $name() { 
      let mut $fixt : $ftype = $ftype::setup(); 
      $expr; 

      teardown(&mut $fixt); 
     } 
    ) 
} 

unit_test! (heap_foo_fixture_should_be_initialised_using_macro FooTestFixture f { 
    assert_eq!(f.name, "Initialised"); 
}); 

しかし、これは次のように動作し、結果はありませんエラー:あなたが見ることができるように

src\tests\heap_fixture_with_new.rs:48:40: 48:50 error: $ftype:ty is followed by $expr:expr , which is not allowed for ty fragments src\tests\heap_fixture_with_new.rs:48 ($name:ident $fixt:ident $ftype:ty $expr:expr) => (

、マクロ定義の中で、私は$ FTYPEでFooTestFixtureへの参照を交換しました。

達成しようとしていることはありますか?マクロと同じように、マクロ定義内で型を渡すことができます。

答えて

2

まあ、私はtyが必要ではないことに気付きました。

macro_rules! unit_test { 
    ($name:ident $fixt:ident $ftype:ident $expr:expr) => (
     #[test] 
     fn $name() { 
      let mut $fixt = $ftype::setup(); 
      $expr; 

      teardown(&mut $fixt); 
     } 
    ) 
} 

unit_test! (foo_fixture_should_be_initialised_using_generic_macro f FooTestFixture { 
    assert_eq!(f.name, "Initialised"); 
}); 
2

tyが直接exprを続けることができません。次の作業を行いますので、私はちょうどidentパラメータとして型を指定することができます。それはfollowed by a specific set of tokensでなければなりません:

  • =>
  • ,
  • =
  • |
  • ;
  • :
  • >
  • [
  • {
  • as
  • where

同様の制限はexprstmtpathpat後に存在します。これは、RFC 550〜future-proof potential change in Rust syntaxで導入されました。

修正するには、マクロのパターンを変更する必要があります。

macro_rules! unit_test { 
    ($name:ident $fixt:ident<$ftype:ty> $expr:expr) => (
//      ^  ^followed by '>' is OK 

unit_test! (test_name fixture_name<FooTestFixture> f {  
//        ^   ^
関連する問題