Я пытаюсь составить общее решение для обеспечения светильников для модульного тестирования кода ржавчины. Я придумал макрос, который позволяет пользователю определить setup и teardown методов. Вот мое решение:Как использовать 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. Это означает, что каждому тестовому модулю необходимо переопределить этот макрос для каждого тестового прибора, что не является идеальным. То, что я хотел бы сделать, это также ввести переменную типа и использовать этот тип в расширении макроса. Копаясь больше в макросы я обнаружил, что существует «ти» элемент, который представляет собой тип, и я думал, что я мог бы сделать это ...
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 forty
fragments src\tests\heap_fixture_with_new.rs:48 ($name:ident $fixt:ident $ftype:ty $expr:expr) => (
Как вы можете видеть, в определении макроса, я заменил ссылки на FooTestFixture с $ Ftype.
Является ли то, что я пытаюсь достичь, возможно? Это похоже на то, что я хочу, чтобы макрос был общим, позволяя вам передать тип, который будет использоваться внутри определения макроса.