Rust 4 - 모듈, 크레이트, 테스트, 문서화
Rust 4 - 모듈, 크레이트, 테스트, 문서화
모듈
Rust에서 모듈 트리를 명시적으로 빌드해야 합니다. 파일 시스템 트리와 모듈 트리 사이에 암시적인 매핑이 없습니다.
다음과 같은 모듈 구조를 만들고 싶다고 생각해 보십시오(이 트리의 잎은 함수임).
crate
└── front_of_house
├── hosting
│ ├── add_to_waitlist
│ └── seat_at_table
└── serving
├── take_order
├── serve_order
└── take_payment
이 모듈 구조를 생성하기 위해 다음을 main.rs
파일에 추가할 수 있습니다.
// main.rs
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
fn main() {}
또는 다음 파일 구조를 만듭니다.
src
├── front_of_house
│ ├── mod.rs
│ ├── hosting.rs
│ └── serving.rs
└── main.rs
hosting.rs
및 serving.rs
파일은 모듈이며 위에서 언급한 기능을 포함합니다.
mod.rs
파일은 다음과 같은 하위 모듈을 선언해야 합니다.
// mod.rs
mod hosting;
mod serving;
main.rs
에서 front_of_house
하위 모듈도 선언해야 합니다.
// main.rs
mod front_of_house;
fn main() {}
front_of_house::serving::take_order();
에서 main.rs
함수를 호출할 수 있으려면 함수가 공개되어야 합니다. 또한 해당 기능으로 이어지는 모듈은 공개되어야 합니다.
함수를 공개합니다.
// serving.rs
pub fn take_order(){}
fn serve_order(){}
fn take_payment(){}
serving
의 mod.rs
모듈을 공개합니다.
// mod.rs
mod hosting;
pub mod serving;
이제 main()
에서 호출할 수 있습니다.
mod front_of_house;
fn main() {
// Absolute path
crate::front_of_house::serving::take_order();
// Relative path
front_of_house::serving::take_order();
}
모듈에 대한 자세한 설명을 보려면 다음 게시물을 읽어 보시기 바랍니다.
Clear explanation of Rust's module system
Rust modules explained
공공 구조물
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
}
pub fn eat_at_restaurant() {
// Order a breakfast in the summer with Rye toast
let mut meal = back_of_house::Breakfast::summer("Rye");
// Change our mind about what bread we'd like
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
// The next line won't compile if we uncomment it; we're not allowed
// to see or modify the seasonal fruit that comes with the meal
// meal.seasonal_fruit = String::from("blueberries");
}
공개 열거형
mod back_of_house {
pub enum Appetizer {
Soup,
Salad,
}
}
pub fn eat_at_restaurant() {
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
}
상대 및 절대 경로와 함께 사용
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant_rel() {
// relative
use self::front_of_house::hosting;
hosting::add_to_waitlist();
}
pub fn eat_at_restaurant_abs() {
// absolute
use crate::front_of_house::hosting;
hosting::add_to_waitlist();
}
pub fn eat_at_restaurant_full() {
// full path
use crate::front_of_house::hosting::add_to_waitlist;
add_to_waitlist();
}
여러 모듈과 함께 사용
use std::io::{self, Write};
// Write does not need to be prefixed but you’d still need to do io::BufReader and so on.
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
pub fn seat_at_table() {}
}
}
fn eat_at_restaurant() {
use front_of_house::hosting::{self, add_to_waitlist};
hosting::seat_at_table();
hosting::add_to_waitlist();
add_to_waitlist();
}
Glob 연산자 - 피하십시오
use std::collections::*;
슈퍼와 자기
fn function() {
println!("called `function()`");
}
mod cool {
pub fn function() {
println!("called `cool::function()`");
}
}
mod my {
fn function() {
println!("called `my::function()`");
}
mod cool {
pub fn function() {
println!("called `my::cool::function()`");
}
}
pub fn indirect_call() {
// Let's access all the functions named `function` from this scope!
print!("called `my::indirect_call()`, that\n");
// The `self` keyword refers to the current module scope - in this case `my`.
// Calling `self::function()` and calling `function()` directly both give
// the same result, because they refer to the same function.
self::function();
function();
// We can also use `self` to access another module inside `my`:
self::cool::function();
// The `super` keyword refers to the parent scope (outside the `my` module).
super::function();
// This will bind to the `cool::function` in the *crate* scope.
// In this case the crate scope is the outermost scope.
{
use crate::cool::function as root_function;
root_function();
}
}
}
fn main() {
my::indirect_call();
// prints:
// called `my::indirect_call()`, that
// called `my::function()`
// called `my::function()`
// called `my::cool::function()`
// called `function()`
// called `cool::function()`
}
종속성
crates.io에서
// Cargo.toml
// ...
[dependencies]
time = "0.2.16"
// main.rs
use time;
fn main() {
println!("2020 has {} days", time::days_in_year(2020));
}
현지의
projects
├── hello_utils
│ └── src
│ └── lib.rs
└── my_project
└── src
└── main.rs
// projects/my_project/Cargo.toml
// ...
[dependencies]
hello_utils = { path = "../hello_utils" }
// lib.rs
pub fn hello(){
println!("Hello!");
}
// main.rs
use hello_utils;
fn main() {
hello_utils::hello();
}
작업 공간
add
폴더를 만듭니다.
add
폴더 내에서 cargo new adder
및 cargo new add-one --lib
를 실행합니다.
이렇게 하면 다음 구조가 생성됩니다.
add
├── Cargo.lock
├── Cargo.toml
├── add-one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
// add/Cargo.toml (note that [package] section is missing)
[workspace]
members = [
"adder",
"add-one",
]
// add/add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
// add/adder/src/main.rs
use add_one;
fn main() {
let num = 10;
println!(
"Hello, world! {} plus one is {}!",
num,
add_one::add_one(num)
);
}
// add/adder/Cargo.toml
// ...
[dependencies]
add-one = { path = "../add-one" }
cargo run -p adder
로 실행합니다.
출력: Hello, world! 10 plus one is 11!.
테스트
동일한 파일에 또는 별도로 테스트를 작성할 수 있습니다.
단위 테스트
Put unit tests in the src
directory in each file with the code that they’re testing. The convention is to create a module named tests
in each file to contain the test functions and to annotate the module with #[cfg(test)]
.
// src/lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4, 2 + 2);
}
}
통합 테스트
Integration test use your library in the same way any other code would, which means they can only call functions that are part of your library’s public API. To create integration tests, you need a tests
directory next to your src
directory.
// tests/integration_test.rs
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
다음을 사용하여 테스트 실행:
# runs all tests
cargo test
# runs only library tests
cargo test --lib
# runs only documentation tests
cargo test --doc
프로그램 패닉이 발생하면 테스트에 실패합니다.
#[test]
fn test_that_fails() {
panic!("Make this test fail");
}
어설션
// when you want to ensure that some condition in a test evaluates to true
assert!(4 == 2 + 2);
// compare two arguments for equality
assert_eq!(4, 2 + 2);
// compare two arguments for inequality
assert_ne!(4, 2 + 1);
맞춤 메시지
pub fn greeting(name: &str) -> String {
String::from("Hello!")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`",
result
);
}
}
패닉 테스트
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn greater_than_100() {
Guess::new(200);
}
}
테스트는 결과를 반환할 수 있습니다.
#[cfg(test)]
mod tests {
#[test]
fn it_works() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
}
선적 서류 비치
용도CommonMark .
문서의 테스트
섹션
다음을 사용하여 문서를 생성합니다.
# '--open' opens generated documentation in the browser
cargo doc --open
수업 과정
암호 변환기 - 2부
일
프로그램을 라이브러리로 리팩토링합니다.
converters
모듈 내에서 Converter
특성을 만듭니다.
KasperskyPasswordManager
모듈 내부의 converters::kaspersky
에 대해 이 특성을 구현합니다.
KasperskyPasswordManager
에 대한 문서, 문서 테스트 및 단위 테스트를 작성합니다.
KasperskyPasswordManager
를 일반으로 만듭니다.
해결책
Password converter lib
어드벤처 게임 - 파트 2
일
에서 어드벤처 게임에 전투 장면을 추가합니다.
적이있을 것입니다. 적에게는 공격 피해 범위와 체력이 있습니다.
플레이어는 공격 피해 범위와 체력이 있습니다(각 장면마다 별도).
플레이어는 행동을 선택합니다:
Rust에서 모듈 트리를 명시적으로 빌드해야 합니다. 파일 시스템 트리와 모듈 트리 사이에 암시적인 매핑이 없습니다.
다음과 같은 모듈 구조를 만들고 싶다고 생각해 보십시오(이 트리의 잎은 함수임).
crate
└── front_of_house
├── hosting
│ ├── add_to_waitlist
│ └── seat_at_table
└── serving
├── take_order
├── serve_order
└── take_payment
이 모듈 구조를 생성하기 위해 다음을
main.rs
파일에 추가할 수 있습니다.// main.rs
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
fn main() {}
또는 다음 파일 구조를 만듭니다.
src
├── front_of_house
│ ├── mod.rs
│ ├── hosting.rs
│ └── serving.rs
└── main.rs
hosting.rs
및 serving.rs
파일은 모듈이며 위에서 언급한 기능을 포함합니다.mod.rs
파일은 다음과 같은 하위 모듈을 선언해야 합니다.// mod.rs
mod hosting;
mod serving;
main.rs
에서 front_of_house
하위 모듈도 선언해야 합니다.// main.rs
mod front_of_house;
fn main() {}
front_of_house::serving::take_order();
에서 main.rs
함수를 호출할 수 있으려면 함수가 공개되어야 합니다. 또한 해당 기능으로 이어지는 모듈은 공개되어야 합니다.함수를 공개합니다.
// serving.rs
pub fn take_order(){}
fn serve_order(){}
fn take_payment(){}
serving
의 mod.rs
모듈을 공개합니다.// mod.rs
mod hosting;
pub mod serving;
이제
main()
에서 호출할 수 있습니다.mod front_of_house;
fn main() {
// Absolute path
crate::front_of_house::serving::take_order();
// Relative path
front_of_house::serving::take_order();
}
모듈에 대한 자세한 설명을 보려면 다음 게시물을 읽어 보시기 바랍니다.
Clear explanation of Rust's module system
Rust modules explained
공공 구조물
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
}
pub fn eat_at_restaurant() {
// Order a breakfast in the summer with Rye toast
let mut meal = back_of_house::Breakfast::summer("Rye");
// Change our mind about what bread we'd like
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
// The next line won't compile if we uncomment it; we're not allowed
// to see or modify the seasonal fruit that comes with the meal
// meal.seasonal_fruit = String::from("blueberries");
}
공개 열거형
mod back_of_house {
pub enum Appetizer {
Soup,
Salad,
}
}
pub fn eat_at_restaurant() {
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
}
상대 및 절대 경로와 함께 사용
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant_rel() {
// relative
use self::front_of_house::hosting;
hosting::add_to_waitlist();
}
pub fn eat_at_restaurant_abs() {
// absolute
use crate::front_of_house::hosting;
hosting::add_to_waitlist();
}
pub fn eat_at_restaurant_full() {
// full path
use crate::front_of_house::hosting::add_to_waitlist;
add_to_waitlist();
}
여러 모듈과 함께 사용
use std::io::{self, Write};
// Write does not need to be prefixed but you’d still need to do io::BufReader and so on.
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
pub fn seat_at_table() {}
}
}
fn eat_at_restaurant() {
use front_of_house::hosting::{self, add_to_waitlist};
hosting::seat_at_table();
hosting::add_to_waitlist();
add_to_waitlist();
}
Glob 연산자 - 피하십시오
use std::collections::*;
슈퍼와 자기
fn function() {
println!("called `function()`");
}
mod cool {
pub fn function() {
println!("called `cool::function()`");
}
}
mod my {
fn function() {
println!("called `my::function()`");
}
mod cool {
pub fn function() {
println!("called `my::cool::function()`");
}
}
pub fn indirect_call() {
// Let's access all the functions named `function` from this scope!
print!("called `my::indirect_call()`, that\n");
// The `self` keyword refers to the current module scope - in this case `my`.
// Calling `self::function()` and calling `function()` directly both give
// the same result, because they refer to the same function.
self::function();
function();
// We can also use `self` to access another module inside `my`:
self::cool::function();
// The `super` keyword refers to the parent scope (outside the `my` module).
super::function();
// This will bind to the `cool::function` in the *crate* scope.
// In this case the crate scope is the outermost scope.
{
use crate::cool::function as root_function;
root_function();
}
}
}
fn main() {
my::indirect_call();
// prints:
// called `my::indirect_call()`, that
// called `my::function()`
// called `my::function()`
// called `my::cool::function()`
// called `function()`
// called `cool::function()`
}
종속성
crates.io에서
// Cargo.toml
// ...
[dependencies]
time = "0.2.16"
// main.rs
use time;
fn main() {
println!("2020 has {} days", time::days_in_year(2020));
}
현지의
projects
├── hello_utils
│ └── src
│ └── lib.rs
└── my_project
└── src
└── main.rs
// projects/my_project/Cargo.toml
// ...
[dependencies]
hello_utils = { path = "../hello_utils" }
// lib.rs
pub fn hello(){
println!("Hello!");
}
// main.rs
use hello_utils;
fn main() {
hello_utils::hello();
}
작업 공간
add
폴더를 만듭니다.
add
폴더 내에서 cargo new adder
및 cargo new add-one --lib
를 실행합니다.
이렇게 하면 다음 구조가 생성됩니다.
add
├── Cargo.lock
├── Cargo.toml
├── add-one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
// add/Cargo.toml (note that [package] section is missing)
[workspace]
members = [
"adder",
"add-one",
]
// add/add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
// add/adder/src/main.rs
use add_one;
fn main() {
let num = 10;
println!(
"Hello, world! {} plus one is {}!",
num,
add_one::add_one(num)
);
}
// add/adder/Cargo.toml
// ...
[dependencies]
add-one = { path = "../add-one" }
cargo run -p adder
로 실행합니다.
출력: Hello, world! 10 plus one is 11!.
테스트
동일한 파일에 또는 별도로 테스트를 작성할 수 있습니다.
단위 테스트
Put unit tests in the src
directory in each file with the code that they’re testing. The convention is to create a module named tests
in each file to contain the test functions and to annotate the module with #[cfg(test)]
.
// src/lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4, 2 + 2);
}
}
통합 테스트
Integration test use your library in the same way any other code would, which means they can only call functions that are part of your library’s public API. To create integration tests, you need a tests
directory next to your src
directory.
// tests/integration_test.rs
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
다음을 사용하여 테스트 실행:
# runs all tests
cargo test
# runs only library tests
cargo test --lib
# runs only documentation tests
cargo test --doc
프로그램 패닉이 발생하면 테스트에 실패합니다.
#[test]
fn test_that_fails() {
panic!("Make this test fail");
}
어설션
// when you want to ensure that some condition in a test evaluates to true
assert!(4 == 2 + 2);
// compare two arguments for equality
assert_eq!(4, 2 + 2);
// compare two arguments for inequality
assert_ne!(4, 2 + 1);
맞춤 메시지
pub fn greeting(name: &str) -> String {
String::from("Hello!")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`",
result
);
}
}
패닉 테스트
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn greater_than_100() {
Guess::new(200);
}
}
테스트는 결과를 반환할 수 있습니다.
#[cfg(test)]
mod tests {
#[test]
fn it_works() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
}
선적 서류 비치
용도CommonMark .
문서의 테스트
섹션
다음을 사용하여 문서를 생성합니다.
# '--open' opens generated documentation in the browser
cargo doc --open
수업 과정
암호 변환기 - 2부
일
프로그램을 라이브러리로 리팩토링합니다.
converters
모듈 내에서 Converter
특성을 만듭니다.
KasperskyPasswordManager
모듈 내부의 converters::kaspersky
에 대해 이 특성을 구현합니다.
KasperskyPasswordManager
에 대한 문서, 문서 테스트 및 단위 테스트를 작성합니다.
KasperskyPasswordManager
를 일반으로 만듭니다.
해결책
Password converter lib
어드벤처 게임 - 파트 2
일
에서 어드벤처 게임에 전투 장면을 추가합니다.
적이있을 것입니다. 적에게는 공격 피해 범위와 체력이 있습니다.
플레이어는 공격 피해 범위와 체력이 있습니다(각 장면마다 별도).
플레이어는 행동을 선택합니다:
// Cargo.toml
// ...
[dependencies]
time = "0.2.16"
// main.rs
use time;
fn main() {
println!("2020 has {} days", time::days_in_year(2020));
}
projects
├── hello_utils
│ └── src
│ └── lib.rs
└── my_project
└── src
└── main.rs
// projects/my_project/Cargo.toml
// ...
[dependencies]
hello_utils = { path = "../hello_utils" }
// lib.rs
pub fn hello(){
println!("Hello!");
}
// main.rs
use hello_utils;
fn main() {
hello_utils::hello();
}
add
폴더를 만듭니다.add
폴더 내에서 cargo new adder
및 cargo new add-one --lib
를 실행합니다.이렇게 하면 다음 구조가 생성됩니다.
add
├── Cargo.lock
├── Cargo.toml
├── add-one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
// add/Cargo.toml (note that [package] section is missing)
[workspace]
members = [
"adder",
"add-one",
]
// add/add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
// add/adder/src/main.rs
use add_one;
fn main() {
let num = 10;
println!(
"Hello, world! {} plus one is {}!",
num,
add_one::add_one(num)
);
}
// add/adder/Cargo.toml
// ...
[dependencies]
add-one = { path = "../add-one" }
cargo run -p adder
로 실행합니다.출력:
Hello, world! 10 plus one is 11!.
테스트
동일한 파일에 또는 별도로 테스트를 작성할 수 있습니다.
단위 테스트
Put unit tests in the src
directory in each file with the code that they’re testing. The convention is to create a module named tests
in each file to contain the test functions and to annotate the module with #[cfg(test)]
.
// src/lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4, 2 + 2);
}
}
통합 테스트
Integration test use your library in the same way any other code would, which means they can only call functions that are part of your library’s public API. To create integration tests, you need a tests
directory next to your src
directory.
// tests/integration_test.rs
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
다음을 사용하여 테스트 실행:
# runs all tests
cargo test
# runs only library tests
cargo test --lib
# runs only documentation tests
cargo test --doc
프로그램 패닉이 발생하면 테스트에 실패합니다.
#[test]
fn test_that_fails() {
panic!("Make this test fail");
}
어설션
// when you want to ensure that some condition in a test evaluates to true
assert!(4 == 2 + 2);
// compare two arguments for equality
assert_eq!(4, 2 + 2);
// compare two arguments for inequality
assert_ne!(4, 2 + 1);
맞춤 메시지
pub fn greeting(name: &str) -> String {
String::from("Hello!")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`",
result
);
}
}
패닉 테스트
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn greater_than_100() {
Guess::new(200);
}
}
테스트는 결과를 반환할 수 있습니다.
#[cfg(test)]
mod tests {
#[test]
fn it_works() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
}
선적 서류 비치
용도CommonMark .
문서의 테스트
섹션
다음을 사용하여 문서를 생성합니다.
# '--open' opens generated documentation in the browser
cargo doc --open
수업 과정
암호 변환기 - 2부
일
프로그램을 라이브러리로 리팩토링합니다.
converters
모듈 내에서 Converter
특성을 만듭니다.
KasperskyPasswordManager
모듈 내부의 converters::kaspersky
에 대해 이 특성을 구현합니다.
KasperskyPasswordManager
에 대한 문서, 문서 테스트 및 단위 테스트를 작성합니다.
KasperskyPasswordManager
를 일반으로 만듭니다.
해결책
Password converter lib
어드벤처 게임 - 파트 2
일
에서 어드벤처 게임에 전투 장면을 추가합니다.
적이있을 것입니다. 적에게는 공격 피해 범위와 체력이 있습니다.
플레이어는 공격 피해 범위와 체력이 있습니다(각 장면마다 별도).
플레이어는 행동을 선택합니다:
Put unit tests in the src
directory in each file with the code that they’re testing. The convention is to create a module named tests
in each file to contain the test functions and to annotate the module with #[cfg(test)]
.
// src/lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4, 2 + 2);
}
}
Integration test use your library in the same way any other code would, which means they can only call functions that are part of your library’s public API. To create integration tests, you need a tests
directory next to your src
directory.
// tests/integration_test.rs
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
# runs all tests
cargo test
# runs only library tests
cargo test --lib
# runs only documentation tests
cargo test --doc
#[test]
fn test_that_fails() {
panic!("Make this test fail");
}
// when you want to ensure that some condition in a test evaluates to true
assert!(4 == 2 + 2);
// compare two arguments for equality
assert_eq!(4, 2 + 2);
// compare two arguments for inequality
assert_ne!(4, 2 + 1);
pub fn greeting(name: &str) -> String {
String::from("Hello!")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`",
result
);
}
}
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn greater_than_100() {
Guess::new(200);
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
}
용도CommonMark .
문서의 테스트
섹션
다음을 사용하여 문서를 생성합니다.
# '--open' opens generated documentation in the browser
cargo doc --open
수업 과정
암호 변환기 - 2부
일
프로그램을 라이브러리로 리팩토링합니다.
converters
모듈 내에서 Converter
특성을 만듭니다.
KasperskyPasswordManager
모듈 내부의 converters::kaspersky
에 대해 이 특성을 구현합니다.
KasperskyPasswordManager
에 대한 문서, 문서 테스트 및 단위 테스트를 작성합니다.
KasperskyPasswordManager
를 일반으로 만듭니다.
해결책
Password converter lib
어드벤처 게임 - 파트 2
일
에서 어드벤처 게임에 전투 장면을 추가합니다.
적이있을 것입니다. 적에게는 공격 피해 범위와 체력이 있습니다.
플레이어는 공격 피해 범위와 체력이 있습니다(각 장면마다 별도).
플레이어는 행동을 선택합니다:
장면은 특성을 사용하여 코드를 공유합니다.
설명서 및 테스트를 추가합니다.
해결책
Adventure game
GitHub에서 내 학습 Rust 저장소를 확인하세요!
펫7555 / 학습-녹
Reference
이 문제에 관하여(Rust 4 - 모듈, 크레이트, 테스트, 문서화), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/petr7555/rust-4-modules-crates-testing-documentation-36dg텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)