【问题标题】:How to run Rust tests with an explicit time zone using chrono?如何使用 chrono 以明确的时区运行 Rust 测试?
【发布时间】:2019-11-04 18:08:15
【问题描述】:

我正在构建一些使用 chrono crate 在 Rust 中进行时间戳转换的测试。我需要确保他们考虑到本地时区,但测试将在多个时区运行,因此对于大多数测试人员来说都会失败。如何在运行测试时强制代码中的 Rust 或 chrono 使用特定时区?

我知道设置env TZ=CST 或类似的。由于我无法控制所有运行 cargo test 的执行环境的那部分,我认为这对我们不起作用。

【问题讨论】:

  • 为什么不在每次测试开始时使用std::env::set_var 设置变量?或者甚至是一个懒惰的静态?
  • 我不明白你的问题
  • @OptimisticPeach 我认为这行不通,因为测试默认并行运行(除非您强制它们不这样做),在这种情况下,它们会不确定地覆盖相同的环境变量。跨度>
  • @OptimisticPeach 只要在您设置TZ 之前没有其他内容读取本地时间,该方法就可以工作。我曾假设(错误地)在 chrono 中创建 Local 时区会导致在我更改它之前读取它。我现在已经实际测试过,它可以工作,但如果操作顺序发生变化,它可能会很脆弱。

标签: testing time rust automated-tests


【解决方案1】:

如果所有测试都应在相同时区运行,您可以使用std::sync::Once 来初始化TZ-环境变量,如 cmets 中所指出的。从技术上讲,由于没有竞争条件,所有测试都可以将 env 初始化为该时区。

如果测试需要设置自己的时区 - 仅对那个测试有效 - 仍然修改整个过程的时区可能是最安全的(包括chrono,但在libc 的某个地方,龙可以访问tz 也是如此)。正如您自己指出的那样,多个测试需要在它们的共享环境上同步。您可以使用lazy_static

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref TZ_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
}

fn with_tz<R, F: FnOnce() -> Result<(), R>>(tz: &str, f: F) -> Result<(), R> {
    let tz_lock = TZ_LOCK.lock();
    std::env::set_var("TZ", tz);
    f()
}

#[test]
fn foobar() -> Result<(), ()> {
    with_tz("CET", || {
        Ok(())
    })
}

您可以通过使用更复杂的TZ_LOCK 来获得更多乐趣,其中当前想要在同一时区下运行的所有线程都可以同时运行。

【讨论】:

  • 确实,chrono 并不直接访问 tz,它是通过旧时间的 crate 进行的,它可能仍然依赖于 libc 函数来更便携地完成脏工作。然而,AFAIK,libc 仅在首次使用时加载一次时区,因此不可能在单个测试中更改它。
猜你喜欢
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2020-04-26
  • 1970-01-01
  • 2020-08-22
  • 2019-07-02
  • 1970-01-01
  • 2021-03-17
相关资源
最近更新 更多