ไม่สามารถรับการทดสอบตามแบบจำลองได้

ในแบบฝึกหัดฉันต้องการใช้ต้นไม้นิ้ว 2-3 นั่นควรเป็นโอกาสอันดีที่จะลองใช้การทดสอบตามแบบจำลองของ FsCheck ฉันตัดสินใจลองใช้เวอร์ชันทดลองที่ใหม่กว่า

จนถึงตอนนี้ ฉันเขียนโค้ดเพียงคำสั่งเดียวสำหรับเครื่องทดสอบเพราะฉันล้มเหลวในการทำงานนั้น ในทางกลับกัน มันทำให้การโพสต์สั้นลง รหัสเต็มมีอยู่ที่ 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<_>

ครั้งแรกของทั้งสองผ่านไป ขาเข้าของแผนผังองค์ประกอบเดียว การเพิ่มทำให้เป็นแผนผังสององค์ประกอบ (ถูกต้อง) ซึ่งเปรียบเทียบได้ดีกับโมเดลหลังจากคำสั่งแรก

คำสั่งที่สองคือคำสั่งที่ล้มเหลวเสมอ Check ถูกเรียกด้วย ResizeList ที่ใหญ่กว่า (ตอนนี้มี 3 องค์ประกอบ) แต่เป็น Tree องค์ประกอบเดียวเดียวกันกับในคำสั่งแรก แน่นอนว่าการเพิ่มอีกหนึ่งองค์ประกอบไม่ได้ทำให้เป็นขนาด 3 และการทดสอบล้มเหลว

ฉันคาดหวังว่าจะต้องส่งคืนโมเดลที่อัปเดตจาก Check เพื่อให้คำสั่งมา แต่คุณต้องส่งคืน Property ดังนั้นจึงไม่สามารถทำได้

ฉันเข้าใจผิดโดยสิ้นเชิงว่าจะเข้าใกล้สิ่งนี้อย่างไร? การทดสอบตามแบบจำลองการทำงานควรเขียนอย่างไร?


person primfaktor    schedule 11.10.2016    source แหล่งที่มา


คำตอบ (1)


การทดสอบตามแบบจำลองจะถือว่า "ระบบที่อยู่ระหว่างการทดสอบ" ได้รับการแก้ไขเป็นผลข้างเคียงเมื่อมีการเรียกใช้ Check ในการดำเนินการเฉพาะ และเตรียมใช้งานสำหรับการทดสอบนั้นเมื่อเรียกใช้ Setup.Actual() มันมีไว้สำหรับจัดการกับระบบที่ไม่แน่นอน - เช่นเดียวกับวัตถุที่ไม่แน่นอน - และสไตล์นั้นในขณะที่ค่อนข้างสับสนที่นี่ก็ใช้ได้ผลดีกับระบบดังกล่าว

เนื่องจากประเภท Finger Tree ของคุณไม่เปลี่ยนรูป คำแนะนำของฉันคือให้กำหนด SutType ใหม่เป็น:

type SutType = Ref<FingerTree<TestType>>

และแก้ไขส่วนที่เหลือตามนั้น

person Kurt Schelfthout    schedule 11.10.2016
comment
ดีแล้วที่รู้! มีการกล่าวถึงในเอกสารบางแห่งหรือไม่? บางทีก็ควรจะโดดเด่นกว่านี้ ขอบคุณ. - person primfaktor; 12.10.2016
comment
เห็นได้ชัดว่าไม่โดดเด่นพอถ้าคุณพลาด :) - person Kurt Schelfthout; 13.10.2016