我正在通过单元测试学习 Rust,下面的代码是这个问题的解决方案,稍作修改。
struct User {
name: String,
age: u8,
weight: f32
}
impl User {
fn new(name: String, age: u8, weight: f32) -> Self {
User {name: name, age: age, weight: weight}
}
fn get_name(&self) -> &str {
&self.name
}
fn get_age(&self) -> u8 {
self.age
}
fn get_weight(&self) -> f32 {
self.weight
}
fn set_name(&mut self, new_name: String) {
self.name = new_name
}
fn set_age(&mut self, new_age: u8) {
self.age = new_age
}
fn set_weight(&mut self, new_weight: f32) {
self.weight = new_weight
}
}
#[test]
fn test_user_get_name() {
let user = User::new(String::from("Bob"), 20, 150.23);
assert_eq!(user.get_name(), "Bob")
}
#[test]
fn test_user_set_name() {
let mut user = User::new(String::from("John"), 24, 150.23);
user.set_name("Jane".to_string()); // no performance cost compared to String::from
assert_eq!(user.get_name(), "Jane")
}
#[test]
fn test_user_get_age() {
let user = User::new(String::from("Bob"), 20, 150.23);
assert_eq!(user.get_age(), 20)
}
#[test]
fn test_user_set_age() {
let mut user = User::new(String::from("Bob"), 20, 150.23);
user.set_age(25);
assert_eq!(user.get_age(), 25)
}
#[test]
fn test_user_get_weight() {
let user = User::new(String::from("Bob"), 20, 150.23);
assert_eq!(user.get_weight(), 150.23)
}
#[test]
fn test_user_set_weight() {
let mut user = User::new(String::from("Bob"), 20, 150.23);
user.set_weight(160.8);
assert_eq!(user.get_weight(), 160.8)
}
Run Code Online (Sandbox Code Playgroud)
我可以执行测试并且所有测试都通过:
rustc --test health_stats.rs --verbose -o health_stats_test
./health_stats_test
Run Code Online (Sandbox Code Playgroud)
如何创建setup()具有可变对象的函数,例如:
let mut user = User::new(String::from("Bob"), 20, 150.23);
Run Code Online (Sandbox Code Playgroud)
这样我就可以在测试中调用get和set方法而无需重复代码?
首先,一些小挑剔:
struct和你所有的impls pub,否则它们毫无意义,而且我不喜欢这些警告:)那么,抛开这个问题,我们来实际讨论一下测试。
setupRust 中没有用于 test /的内置机制teardown,但您自己实现非常容易。您只需编写一个简单的setup()函数,该函数返回一个上下文对象,并drop提供拆卸的实现。
您可以创建用户并将其存储在上下文对象中。此外,您可以运行任何类型的副作用。我将在这里通过打印一些消息来演示这一点。
setup在这里,这就是我实现/机制的方式teardown:
pub struct User {
name: String,
age: u8,
weight: f32,
}
impl User {
pub fn new(name: String, age: u8, weight: f32) -> Self {
User {
name: name,
age: age,
weight: weight,
}
}
pub fn get_name(&self) -> &str {
&self.name
}
pub fn get_age(&self) -> u8 {
self.age
}
pub fn get_weight(&self) -> f32 {
self.weight
}
pub fn set_name(&mut self, new_name: String) {
self.name = new_name
}
pub fn set_age(&mut self, new_age: u8) {
self.age = new_age
}
pub fn set_weight(&mut self, new_weight: f32) {
self.weight = new_weight
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestContext {
user: User,
}
impl Drop for TestContext {
fn drop(&mut self) {
println!("Test teardown ...");
}
}
fn setup() -> TestContext {
println!("Test setup ...");
TestContext {
user: User::new(String::from("Bob"), 20, 150.23),
}
}
#[test]
fn test_user_get_name() {
let ctx = setup();
assert_eq!(ctx.user.get_name(), "Bob")
}
#[test]
fn test_user_set_name() {
let mut ctx = setup();
ctx.user.set_name("Jane".to_string()); // no performance cost compared to String::from
assert_eq!(ctx.user.get_name(), "Jane")
}
#[test]
fn test_user_get_age() {
let ctx = setup();
assert_eq!(ctx.user.get_age(), 20)
}
#[test]
fn test_user_set_age() {
let mut ctx = setup();
ctx.user.set_age(25);
assert_eq!(ctx.user.get_age(), 25)
}
#[test]
fn test_user_get_weight() {
let ctx = setup();
assert_eq!(ctx.user.get_weight(), 150.23)
}
#[test]
fn test_user_set_weight() {
let mut ctx = setup();
ctx.user.set_weight(160.8);
assert_eq!(ctx.user.get_weight(), 160.8)
}
}
Run Code Online (Sandbox Code Playgroud)
> cargo test
running 6 tests
test tests::test_user_get_age ... ok
test tests::test_user_get_name ... ok
test tests::test_user_get_weight ... ok
test tests::test_user_set_age ... ok
test tests::test_user_set_name ... ok
test tests::test_user_set_weight ... ok
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Run Code Online (Sandbox Code Playgroud)
如果添加--nocapture,您可以看到安装/拆卸消息的输出println:
> cargo test -- --nocapture
running 6 tests
Test setup ...
Test teardown ...
Test setup ...
Test teardown ...
Test setup ...
Test teardown ...
Test setup ...
Test teardown ...
test tests::test_user_get_age ... okTest setup ...
Test setup ...
Test teardown ...
Test teardown ...
test tests::test_user_get_name ... ok
test tests::test_user_get_weight ... ok
test tests::test_user_set_age ... ok
test tests::test_user_set_weight ... ok
test tests::test_user_set_name ... ok
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Run Code Online (Sandbox Code Playgroud)
默认情况下,cargo test在多个线程上并行运行测试。如果您的setup/teardown方法具有非线程安全的副作用,您可能需要使用以下标志强制执行单线程测试--test-threads 1:
> cargo test -- --nocapture --test-threads 1
running 6 tests
test tests::test_user_get_age ... Test setup ...
Test teardown ...
ok
test tests::test_user_get_name ... Test setup ...
Test teardown ...
ok
test tests::test_user_get_weight ... Test setup ...
Test teardown ...
ok
test tests::test_user_set_age ... Test setup ...
Test teardown ...
ok
test tests::test_user_set_name ... Test setup ...
Test teardown ...
ok
test tests::test_user_set_weight ... Test setup ...
Test teardown ...
ok
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2367 次 |
| 最近记录: |