【问题标题】:Cannot get model based test working无法使基于模型的测试工作
【发布时间】:2017-02-19 22:15:33
【问题描述】:

作为练习,我想实现一个 2-3 指树。这应该是尝试FsCheck 的基于模型的测试的绝佳机会。我决定尝试更新的experimental version

到目前为止,我只为测试机器编写了一个命令,因为我已经无法完成这项工作 - 另一方面它使帖子保持简短。完整代码可在GitHub 获得。

open CmdQ
open Fuchu
open FsCheck
open FsCheck.Experimental

type TestType = uint16
type ModelType = ResizeArray<TestType>
type SutType = FingerTree<TestType>

let spec =
    let prepend (what:TestType) =
        { new Operation<SutType, ModelType>() with
            override __.Run model =
                // Also tried returning the same instance.
                let copy = model |> ResizeArray
                copy.Insert(0, what)
                copy

            override __.Check(sut, model) =
                let sutList = sut |> Finger.toList
                let newSut = sut |> Finger.prepend what
                let newSutList = newSut |> Finger.toList
                let modelList = model |> Seq.toList
                let areEqual = newSutList = modelList
                areEqual |@ sprintf "prepend: model = %A, actual = %A (incoming was %A)" modelList newSutList sutList

            override __.ToString() = sprintf "prepend %A" what
        }

    let create (initial:ModelType) =
        { new Setup<SutType, ModelType>() with
            override __.Actual () = initial |> Finger.ofSeq

            override __.Model () = initial //|> ResizeArray // Also tried this.
        }

    let rndNum () : Gen<TestType> = Arb.from<uint16> |> Arb.toGen

    { new Machine<SutType, ModelType>() with
        override __.Setup =
            rndNum()
            |> Gen.listOf
            |> Gen.map ResizeArray
            |> Gen.map create
            |> Arb.fromGen

        override __.Next _ = gen {
            let! cmd = Gen.elements [prepend]
            let! num = rndNum()
            return cmd num
        }
    }

[<Tests>]
let test =
    [spec]
    |> List.map (StateMachine.toProperty >> testProperty "Finger tree")
    |> testList "Model tests"

我的理解是:Operation&lt;_&gt;.Run 运行两次以从一个具有单个元素的ResizeArray 构建。然后Operation&lt;_&gt;.Check 使用相同的数字运行两次以插入单个元素FingerTree&lt;_&gt;

两次传球中的第一次。单元素树传入,添加使其成为(正确的)二元素树,在第一个命令之后与模型进行了很好的比较。

第二个命令总是失败的。 Check 使用更大的 ResizeList(现在是 3 个元素)调用,但与第一个命令中的单元素 Tree 相同。再添加一个元素当然不会使其大小为 3,并且测试失败。

我原以为我需要从Check 返回更新的模型才能收到命令。但是你需要返回一个Property,所以这是不可能的。

我完全误解了如何处理这个问题吗?应该如何编写基于模型的工作测试?

【问题讨论】:

    标签: f# immutability mutable fscheck model-based-testing


    【解决方案1】:

    基于模型的测试假定“被测系统”在特定操作上调用Check 时被修改为副作用,并在调用Setup.Actual() 时为该测试运行初始化。它旨在处理可变的系统(例如可变对象),这种风格虽然在这里有些令人困惑,但在此类系统中效果很好。

    由于您的手指树类型是不可变的,我的建议是将SutType 重新定义为:

    type SutType = Ref<FingerTree<TestType>>
    

    并相应地修改其余部分。

    【讨论】:

    • 很高兴知道!在某处的文档中提到了吗?也许它应该更突出。谢谢。
    • 如果你错过了,显然不够突出:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    相关资源
    最近更新 更多