无法获得基于模型的测试工作 [英] Cannot get model based test working

查看:108
本文介绍了无法获得基于模型的测试工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As an exercise I wanted to implement a 2-3 finger tree. That should be the perfect opportunity to try out FsCheck's model-based testing. I decided to try the newer experimental version.

到目前为止,我只为测试机器编写了一个命令,因为我已经无法使该工作正常进行;另一方面,它使发布的内容很短.完整代码可在 GitHub 上找到.

So far I only coded one command for the test machine because I already fail at making that work—one the other hand it keeps the post short. The full code is available on 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<_>.Run运行两次,以一个元素创建一个ResizeArray.然后Operation<_>.Check用相同的数字运行两次,以插入到单个元素FingerTree<_>中.

What I understand is this: Operation<_>.Run is run twice to build up a ResizeArray from one with a single element. Then Operation<_>.Check is run twice with the same numbers to insert into a single element FingerTree<_>.

两次通过中的第一个.单元素树的传入,添加使之成为(正确的)两元素树,与第一个命令后的模型相比,它具有很好的比较性.

The first of the two passes. Single-element tree incoming, adding makes it a (correct) two-element tree which compares well against the model after the first command.

第二个命令总是一个失败的命令. Check用更大的ResizeList(现在为3个元素)调用,但与第一个命令中的单个元素树相同.当然再增加一个元素并不能使尺寸达到3,并且测试失败.

The second command is always the one failing. Check is called with the bigger ResizeList (now 3 elements) but the same single-element Tree as in the first command. Adding one more element of course does not get it to size 3 and the test fails.

我希望我需要从Check返回更新的模型,以使命令生效.但是您需要返回Property,所以这是不可能的.

I would have expected that I need to return the updated model from Check for the commands to come. But you need to return a Property so that's not possible.

我是否完全误解了该如何处理?应该如何编写基于工作模型的测试?

Did I completely misunderstand how to approach this? How should a working model-based test be written?

推荐答案

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

The model-based testing assumes that the "system under test" is modified as a side-effect when Check is called on a particular operation, and initialized for that test run when Setup.Actual() is called. It is intended for dealing with systems that are mutable - like a mutable object - and that style while somewhat bewildering here works out quite nicely with such systems.

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

Since your finger tree type is immutable, my advice would be to redefine SutType to:

type SutType = Ref<FingerTree<TestType>>

并相应地修改其余部分.

and modify the rest accordingly.

这篇关于无法获得基于模型的测试工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆