在 Rust 的测试中创建、读取和删除文件时的奇怪行为
Weird behavior when creating, reading and deleting files in tests in Rust
我正在尝试对模块编写测试,模块本身并不重要。
测试部分是这样的。在这两个测试中,我试图做完全相同的事情:创建一个 JSON 文件,读取并删除它(这些不是真正的测试,但这些操作需要从测试到测试重复)。
src/archive.rs
#[cfg(test)]
mod tests {
use super::*;
use std::{fs, path};
use crate::tests;
#[test]
fn test_archive_tar_archive_test1() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}"#,
);
println!("reading {}", fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap());
tests::delete_custom_settings();
}
#[test]
fn test_archive_tar_archive_test2() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}"#,
);
println!("reading {}", fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap());
tests::delete_custom_settings();
}
}
第二个文件与第一个文件一样基本,这些是多个模块中使用的公共部分:
src/tests.rs
use std::fs;
pub const CUSTOM_SETTINGS_PATH: &str = "/tmp/hvtools_custom_settings.json";
pub fn create_custom_settings(file_data: &str) {
println!("writing {}", file_data);
match fs::write(CUSTOM_SETTINGS_PATH, file_data) {
Ok(_) => {},
Err(e) => panic!(
"Could not create custom settings file under '{}': {}",
CUSTOM_SETTINGS_PATH, e
),
};
}
pub fn delete_custom_settings() {
match fs::remove_file(CUSTOM_SETTINGS_PATH) {
Ok(_) => {},
Err(e) => panic!(
"Could not delete custom settings file under '{}': {}",
CUSTOM_SETTINGS_PATH, e
),
};
}
当 运行 这些测试每次都让我大致相同,但略有不同:
running 2 tests
writing {
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}
writing {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
thread 'archive::tests::test_archive_tar_archive_test2' panicked at 'Could not delete custom settings file under '/tmp/hvtools_custom_settings.json': No such file or directory (os error 2)', src/tests.rs:19:19
正如我们所见:
- 第一次测试读取文件returns第二次测试写入的值
- 在第二次测试中尝试删除 JSON 文件失败(在阅读作品时)
有时两个测试都读取第一个测试中写入的内容,有时第一个读取尝试 returns 一个空字符串(结果因代码更改而异):
running 2 tests
writing {
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}
writing {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
这是一个物理文件系统(没有 NFS 共享或其他东西)。另外,作为旁注,如果我将第二个测试的内容移动到第一个测试中:
fn test_archive_tar_archive_test1() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}"#,
);
println!(
"reading {}",
fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap()
);
tests::delete_custom_settings();
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}"#,
);
println!(
"reading {}",
fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap()
);
tests::delete_custom_settings();
}
一切正常。尝试添加 thread::sleep
,结果似乎没有改变。
我做错了什么?
并行测试运行,因此访问相同路径的两个测试很可能会相互干扰。在每个测试中使用不同的路径来防止这种情况。
或者,您可以强制测试 运行 在单个线程中按顺序进行测试:
cargo test -- --test-threads=1
我正在尝试对模块编写测试,模块本身并不重要。
测试部分是这样的。在这两个测试中,我试图做完全相同的事情:创建一个 JSON 文件,读取并删除它(这些不是真正的测试,但这些操作需要从测试到测试重复)。
src/archive.rs
#[cfg(test)]
mod tests {
use super::*;
use std::{fs, path};
use crate::tests;
#[test]
fn test_archive_tar_archive_test1() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}"#,
);
println!("reading {}", fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap());
tests::delete_custom_settings();
}
#[test]
fn test_archive_tar_archive_test2() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}"#,
);
println!("reading {}", fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap());
tests::delete_custom_settings();
}
}
第二个文件与第一个文件一样基本,这些是多个模块中使用的公共部分:
src/tests.rs
use std::fs;
pub const CUSTOM_SETTINGS_PATH: &str = "/tmp/hvtools_custom_settings.json";
pub fn create_custom_settings(file_data: &str) {
println!("writing {}", file_data);
match fs::write(CUSTOM_SETTINGS_PATH, file_data) {
Ok(_) => {},
Err(e) => panic!(
"Could not create custom settings file under '{}': {}",
CUSTOM_SETTINGS_PATH, e
),
};
}
pub fn delete_custom_settings() {
match fs::remove_file(CUSTOM_SETTINGS_PATH) {
Ok(_) => {},
Err(e) => panic!(
"Could not delete custom settings file under '{}': {}",
CUSTOM_SETTINGS_PATH, e
),
};
}
当 运行 这些测试每次都让我大致相同,但略有不同:
running 2 tests
writing {
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}
writing {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
thread 'archive::tests::test_archive_tar_archive_test2' panicked at 'Could not delete custom settings file under '/tmp/hvtools_custom_settings.json': No such file or directory (os error 2)', src/tests.rs:19:19
正如我们所见:
- 第一次测试读取文件returns第二次测试写入的值
- 在第二次测试中尝试删除 JSON 文件失败(在阅读作品时)
有时两个测试都读取第一个测试中写入的内容,有时第一个读取尝试 returns 一个空字符串(结果因代码更改而异):
running 2 tests
writing {
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}
writing {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
reading
reading {
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}
这是一个物理文件系统(没有 NFS 共享或其他东西)。另外,作为旁注,如果我将第二个测试的内容移动到第一个测试中:
fn test_archive_tar_archive_test1() {
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp1",
"archive_tmp_path": "/tmp1"
}"#,
);
println!(
"reading {}",
fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap()
);
tests::delete_custom_settings();
tests::create_custom_settings(
r#"{
"tmp_path": "/tmp2",
"archive_tmp_path": "/tmp2"
}"#,
);
println!(
"reading {}",
fs::read_to_string(tests::CUSTOM_SETTINGS_PATH).unwrap()
);
tests::delete_custom_settings();
}
一切正常。尝试添加 thread::sleep
,结果似乎没有改变。
我做错了什么?
并行测试运行,因此访问相同路径的两个测试很可能会相互干扰。在每个测试中使用不同的路径来防止这种情况。
或者,您可以强制测试 运行 在单个线程中按顺序进行测试:
cargo test -- --test-threads=1