Tes berbasis model tidak dapat berfungsi

Sebagai latihan saya ingin menerapkan pohon 2-3 jari. Ini akan menjadi kesempatan sempurna untuk mencoba pengujian berbasis model FsCheck. Saya memutuskan untuk mencoba versi eksperimental yang lebih baru.

Sejauh ini saya hanya mengkodekan satu perintah untuk mesin uji karena saya sudah gagal dalam membuat perintah tersebut berfungsi—di sisi lain hal ini membuat postingan menjadi singkat. Kode selengkapnya tersedia di 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"

Yang saya pahami adalah ini: Operation<_>.Run dijalankan dua kali untuk membangun ResizeArray dari satu elemen dengan satu elemen. Kemudian Operation<_>.Check dijalankan dua kali dengan nomor yang sama untuk dimasukkan ke dalam satu elemen FingerTree<_>.

Yang pertama dari dua operan. Pohon elemen tunggal masuk, penambahan menjadikannya pohon dua elemen (benar) yang sebanding dengan model setelah perintah pertama.

Perintah kedua selalu gagal. Check dipanggil dengan ResizeList yang lebih besar (sekarang 3 elemen) tetapi Pohon elemen tunggal yang sama seperti pada perintah pertama. Menambahkan satu elemen lagi tentu saja tidak akan membuatnya menjadi ukuran 3 dan pengujiannya gagal.

Saya berharap saya perlu mengembalikan model yang diperbarui dari Check agar perintah yang akan datang. Tapi Anda harus mengembalikan Property jadi itu tidak mungkin.

Apakah saya benar-benar salah memahami cara melakukan pendekatan ini? Bagaimana seharusnya tes berbasis model kerja ditulis?


person primfaktor    schedule 11.10.2016    source sumber


Jawaban (1)


Pengujian berbasis model mengasumsikan bahwa "sistem yang sedang diuji" dimodifikasi sebagai efek samping ketika Check dipanggil pada operasi tertentu, dan diinisialisasi untuk pengujian yang dijalankan ketika Setup.Actual() dipanggil. Ini dimaksudkan untuk menangani sistem yang bisa berubah - seperti objek yang bisa berubah - dan gaya tersebut, meskipun agak membingungkan di sini, berfungsi cukup baik dengan sistem seperti itu.

Karena jenis pohon jari Anda tidak dapat diubah, saran saya adalah mendefinisikan ulang SutType menjadi:

type SutType = Ref<FingerTree<TestType>>

dan memodifikasi sisanya sesuai.

person Kurt Schelfthout    schedule 11.10.2016
comment
Senang mendengarnya! Apakah itu disebutkan dalam dokumen di suatu tempat? Mungkin itu harus lebih menonjol. Terima kasih. - person primfaktor; 12.10.2016
comment
Jelas tidak cukup menonjol jika Anda melewatkannya :) - person Kurt Schelfthout; 13.10.2016