一个木箱是一个独立的编译单元,可以包含一个module hierarchy,最顶层的module叫crate root,,比如建一个新工程:
$ cd ~/projects $ cargo new modules --bin $ cd modules生成的src/main.rs就是一个crate,在其中可以定义很多module
fn main() {
println!("Hello, world!")
}
mod hello {
fn print_hello() {
println!("Hello, world!")
}
}
可以把mod关键字想像成java中的class,这样就好理解了,其中的方法默认都是private的,加上pub关键字就成了public
fn main() {
hello::print_hello();
}
mod hello {
pub fn print_hello() {
println!("Hello, world!")
}
}
16测试
#[test]
fn is_one_equal_to_one() {
assert_eq!(1i, 1i);
}
和java比,,,@Test变成了#[test],要多出2个蛋疼的符号,为嘛不用@Test
16.1Attributes
#[test]这玩意在rust中叫Attributes,在java中叫Annotation, Attr可以标记在任何的rust item上,比如:
如果是#后加个!, hash bang?我在写shell吗?
#!表示作用在整个crate上(初学,我暂时理解为当前所在的文件)
6种级别deprecated,experimental,unstable,stable,frozen,locked
warn就是专门为这些级别而生的一种Attributes,用法如下:
// applies to the crate we're in
#![warn(unstable)]
extern crate some_crate;
// applies to the following `fn`.
#[test]
fn a_test() {
// ...
}
warn(unstable)表示如果导入了标记为unstable的模块,就要报警了~如果不加warn标记,默认只有deprecated会报警
$ cd ~/projects $ cargo new testing --bin $ cd testing在源码中写的test叫unit test,在tests目录下写的test叫integration test.
#[test]
fn foo() {
assert!(true);
}
此时cargo test一下,测试成功,但是会报警main()方法未被使用,这样就行
#[cfg(not(test))]
fn main() {
println!("Hello, world!")
}
我稍微玩了一个#!,,,she bang!!!看看我的src/main.rs
#![cfg(not(test))] fn main() { println!("Hello, world!"); bar(); } fn bar(){}
#![cfg(not(test))]表示在测试的时候编译我,但不要报警??(这点没完全明白, 报不报警有那么重要..)
来个完整的:
首先是在src/lib.rs中定义一个新的方法, 然后是分别在src/main.rs和tests/lib.rs中使用这个方法
src/lib.rs代码如下:
pub fn add_three_times_four(x: int) -> int {
times_four(add_three(x))
}
fn add_three(x: int) -> int { x + 3 }
fn times_four(x: int) -> int { x * 4 }
src/main.rs中这样使用
extern crate testing;
#[cfg(not(test))]
fn main() {
println!("Hello, world!")
}
tests/lib.rs中这样测试
extern crate testing;
use testing::add_three_times_four;
#[test]
fn math_checks_out() {
let result = add_three_times_four(5i);
assert_eq!(32i, result);
}
使用extern crate导入crate,使用use导入方法 ...我想std是默认已经导入的crate,而testing需要我们手动导入..不明白为什么还要多一个导入crate的动作..java中为嘛一个import就能搞定
其中src/lib.rs中的两个私有方法,不能做tests测试(容我这样叫),只能做unit测试,修改src/lib.rs如下:
pub fn add_three_times_four(x: int) -> int {
times_four(add_three(x))
}
fn add_three(x: int) -> int { x + 3 }
fn times_four(x: int) -> int { x * 4 }
#[cfg(test)]
mod test {
use super::add_three;
use super::times_four;
#[test]
fn test_add_three() {
let result = add_three(5i);
assert_eq!(8i, result);
}
#[test]
fn test_times_four() {
let result = times_four(5i);
assert_eq!(20i, result);
}
}
可以看到把测试的方法组织到了一个mod下面,个人认为纯属好看,
pub fn add_3_times_4(x: int) -> int { times_4(add_3(x)) } fn times_4(x:int) -> int { x*4 } fn add_3(x:int)->int{ x+3 } mod test{ use super::add_3; use super::times_4; #[test] fn test_add_3(){ let result = add_3(5i); assert_eq!(8i, result); } #[test] fn test_times_4(){ let result = times_4(5i); assert_eq!(20i, result); } }
cyper@zerorun:~/rust/projects/testing$ cargo test
Compiling testing v0.0.1 (file:///home/cyper/rust/projects/testing)
/home/cyper/rust/projects/testing/src/lib.rs:11:9: 11:21 warning: unused import, #[warn(unused_imports)] on by default
/home/cyper/rust/projects/testing/src/lib.rs:11 use super::add_3;
^~~~~~~~~~~~
/home/cyper/rust/projects/testing/src/lib.rs:12:9: 12:23 warning: unused import, #[warn(unused_imports)] on by default
/home/cyper/rust/projects/testing/src/lib.rs:12 use super::times_4;
^~~~~~~~~~~~~~
Running target/lib-20cb46c181088f0d
running 1 test
test math_checks_out ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Running target/testing-4b195e8c06dad98e
running 2 tests
test test::test_add_3 ... ok
test test::test_times_4 ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
Running target/testing-c693f606fb5b87e0
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
Doc-tests testing
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
cyper@zerorun:~/rust/projects/testing$
不过再次运行cargo test上面的报警会消失..运行cargo clean后再次运行cargo run或cargo test报警又会出现.