-3

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

与以下代码相同但不使用随机数生成器的策略需要看起来像什么?(不言而喻,随机数生成器不适合基于属性的测试。)

没有 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方法没有帮助,因为仍然不知道正确的大小。

4

1 回答 1

0

解决此问题的一种方法是用策略替换每个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<Value=Vec<T>>可以从vec函数(向量策略)或策略向量生成 An!在上面的代码中,我通过使用which 是一个策略result来做到这一点。因此,类型类似于not (迂腐:策略可能不是类型)。pushhash_set(..)Vec<Strategy<T>>Strategy<Vec<T>>

于 2020-09-16T18:42:54.243 回答