Как мне получить доступ к экспортированным функциям внутри каталога с тестами ящика?

Как мне получить доступ к функциям, экспортированным из моих библиотек, в каталоге create "tests"?

источник/relations.rs:

#![crate_type = "lib"]

mod relations {
    pub fn foo() {
        println!("foo");
    }
}

тесты/test.rs:

use relations::foo;

#[test]
fn first() {
    foo();
}
$ cargo test
   Compiling relations v0.0.1 (file:///home/chris/github/relations)
/home/chris/github/relations/tests/test.rs:1:5: 1:14 error: unresolved import `relations::foo`. Maybe a missing `extern crate relations`?
/home/chris/github/relations/tests/test.rs:1 use relations::foo;
                                                 ^~~~~~~~~

Если я добавлю предложенный extern crate relations, ошибка будет:

/home/chris/github/relations/tests/test.rs:2:5: 2:19 error: unresolved import `relations::foo`. There is no `foo` in `relations`
/home/chris/github/relations/tests/test.rs:2 use relations::foo;
                                                 ^~~~~~~~~~~~~~

Я хочу проверить свой relations в этом отдельном файле tests/test.rs. Как я могу решить эти use проблемы?


person fadedbee    schedule 15.10.2014    source источник


Ответы (2)


Ваша проблема в том, что, во-первых, mod relations не является общедоступным, поэтому он не виден за пределами ящика, а во-вторых, вы не импортируете свой ящик в тесты.

Если вы создаете свою программу с помощью Cargo, тогда имя контейнера будет таким, которое вы определили в Cargo.toml. Например, если Cargo.toml выглядит так:

[package]
name = "whatever"
authors = ["Chris"]
version = "0.0.1"

[lib]
name = "relations"  # (1)

И файл src/lib.rs содержит это:

pub mod relations {  // (2); note the pub modifier
    pub fn foo() {
        println!("foo");
    }
}

Затем вы можете написать это в tests/test.rs:

extern crate relations;  // corresponds to (1)

use relations::relations;  // corresponds to (2)

#[test]
fn test() {
    relations::foo();
}
person Vladimir Matveev    schedule 15.10.2014
comment
Этот ответ создает еще один уровень вложенности пространства имен, чем требуется, но он очень ясен и полезен. Являются ли крейты модулями сами по себе, или крейты и модули являются двумя формами пространств имен? - person fadedbee; 16.10.2014
comment
@chrisdew, да, ящики и модули разные. Ящики состоят из модулей; каждый крейт имеет безымянный модуль верхнего уровня, называемый корнем крейта, который состоит из всех определений в файле верхнего уровня, в данном случае lib.rs. Если вы удалите pub mod relations и соответствующие фигурные скобки и оставите fn foo() на верхнем уровне, вам не понадобится второй relations в use relations::relations в тестах, потому что теперь fn foo() будет жить в корне ящика. - person Vladimir Matveev; 16.10.2014
comment
Крейты — это единицы компиляции, а модули — это логические единицы для структурирования вашего кода. По этой причине, например, вы можете иметь взаимные зависимости между модулями в одном и том же крейте, но не можете иметь взаимных зависимостей между крейтами. - person Vladimir Matveev; 16.10.2014
comment
Ящики создают пространство имен, которое является их именем, а модули создают более глубокие пространства имен в пространстве имен ящика? Тесты в папке /tests ящика должны обращаться к ящику, как если бы они находились снаружи, т. е. использовать extern? - person fadedbee; 16.10.2014
comment
@chrisdew, да, ваша оценка абсолютно верна. Кстати, это малоизвестно, но имена крейтов могут иметь причудливые символы в именах, которые не могут быть у модулей, например, some-crate является допустимым идентификатором крейта: extern crate some-crate. Не уверен, что такие пути можно использовать в коде, возможно, нужно переименовать с помощью as. - person Vladimir Matveev; 16.10.2014
comment
Спасибо, @VladimirMatveev! Кстати, должен отметить, что строка extern crate relations больше не нужна. Вы можете просто использовать use relations::relations. - person Yvon Manzi; 14.11.2020

Решение состояло в том, чтобы указать crate_id в верхней части src/relations.rs:

#![crate_id = "relations"]
#![crate_type = "lib"]

pub fn foo() {
    println!("foo");
}

Это, кажется, объявляет, что весь содержащийся код является частью модуля «отношения», хотя я до сих пор не уверен, чем это отличается от более раннего блока mod.

person fadedbee    schedule 15.10.2014