【问题标题】:Proptest: Strategy to generate vectors of vectorsProptest:生成向量向量的策略
【发布时间】:2021-01-02 18:41:04
【问题描述】:

我想用proptest 生成 DAG。我选择的算法是this。我在下面编写了简单的算法——但我需要帮助将其转换为 proptest strategy

在不使用随机数生成器的情况下,策略需要与以下代码相同吗? (不用说,随机数生成器不适合基于属性的测试。)

没有proptest策略的标准代码: (https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2de4a757a96d123bf83b5157e0633d33)

use rand::Rng;

fn main() {
    println!("{:?}", random_vec_of_vec());
}

fn random_vec_of_vec() -> Vec<Vec<u16>> {
    const N: u16 = 30;
    const K: usize = 3;
    let mut rng = rand::thread_rng();

    let length: u16 = rng.gen_range(0, N);
    let mut outer = vec![];
    for index in 1..length {
        let mut inner = vec![0u16; rng.gen_range(0, K)];
        for e in &mut inner {
            *e = rng.gen_range(0, index);
        }
        // De-duplicate elements. Particularly a problem with `index < K`.
        inner.sort();
        inner.dedup();
        outer.push(inner);
    }
    outer
}

以前的工作

我尝试使用vec 函数,但我需要嵌套两个vec 函数。而且,内部的 vec 函数只能生成到外部向量中索引的值。

use proptest::collection::vec;
// INDEX should be the value of the position of the inner vector
// in the outer vector. How could the be found?
let strategy = vec(vec(1..INDEX, 0..K), 0..N);

index 方法没有帮助,因为仍然不知道正确的大小。

【问题讨论】:

  • 这里有什么问题?是how to use proptest吗?还是更具体一些?
  • 正如我在之前的评论中所写,我知道文档、书籍和logrocket-post。不知道为什么那条评论被删除了——毕竟是别人在骂我。接下来我会回答你的问题。
  • @Jmb 我开始使用 proptest 没有问题。这种策略的问题在于,三种策略必须在不同层次上结合起来。我会发布一个答案——因为我设法解决了这个问题。对我来说这样做的方法是保持基于 rand 的代码的结构。

标签: rust property-based-testing proptest


【解决方案1】:

解决此问题的一种方法是将每个 rng.gen_range() 调用替换为策略。然后必须将嵌套策略与prop_flat_map 连接。

在下面的代码中,我替换了我的模式 let length = rng.gen_range(0, N); for i in 1..length { .. },带有一个新函数 vec_from_length(length: usize),它返回一个策略。

#[cfg(test)]
mod tests {
    use super::*;
    use proptest::collection::hash_set;
    use proptest::prelude::*;
    use std::collections::HashSet;

    proptest! {
        #[test]
        fn meaningless_test(v in vec_of_vec()) {
            let s = sum(&v);  // sum of the sum of all vectors.
            prop_assert!(s < 15);
        }
    }

    fn vec_of_vec() -> impl Strategy<Value = Vec<Vec<u16>>> {
        const N: u16 = 10;

        let length = 0..N;
        length.prop_flat_map(vec_from_length).prop_map(convert)
    }

    fn vec_from_length(length: u16) -> impl Strategy<Value = Vec<HashSet<u16>>> {
        const K: usize = 5;
        let mut result = vec![];
        for index in 1..length {
            // Using a hash_set instead of vec because the elements should be unique.
            let inner = hash_set(0..index, 0..K);

            result.push(inner);
        }
        result
    }

    /// Convert Vec<HashSet<T>> to Vec<Vec<T>>
    fn convert(input: Vec<HashSet<u16>>) -> Vec<Vec<u16>> {
        let mut output = vec![];
        for inner in input {
            output.push(inner.into_iter().collect())
        }
        output
    }
}

还有一点:impl Strategy&lt;Value=Vec&lt;T&gt;&gt; 可以从 vec 函数(向量策略)或策略向量生成!在上面的代码中,我通过将result 设置为pushed 和hash_set(..) 这是一个策略来做到这一点。因此,该类型类似于Vec&lt;Strategy&lt;T&gt;&gt; 而不是Strategy&lt;Vec&lt;T&gt;&gt;(迂腐:策略可能不是一种类型)。

【讨论】:

    猜你喜欢
    • 2012-07-18
    • 2013-02-03
    • 1970-01-01
    • 2015-07-11
    • 2016-11-21
    • 2011-03-26
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    相关资源
    最近更新 更多