Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM · Pelajaran

Ujian Berasaskan Sifat dengan clojure.test.check

Pelajari cara menulis ujian teguh yang mengesahkan sifat kod anda merentas pelbagai input menggunakan `clojure.test.check`

Pelajaran 3 daripada 411 langkah

Ujian Berasaskan Sifat dengan clojure.test.check ialah pelajaran Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM merangkumi sejumlah 4 pelajaran.

Melangkaui Ujian Contoh Ringkas

Selamat datang ke Pengujian Berasaskan Sifat (PBT)! Ujian unit tradisional menggunakan contoh khusus untuk menyemak sama ada kod anda berfungsi. PBT menggunakan pendekatan yang berbeza.

Daripada menggunakan contoh, anda mentakrifkan sifat yang harus sentiasa dipatuhi oleh kod anda, tanpa mengira input. Kemudian, alat PBT menjana pelbagai input untuk cuba mematahkan sifat tersebut.

PBT berbanding Pengujian Berasaskan Contoh

Fikirkan begini:

  • Pengujian Berasaskan Contoh (seperti clojure.test): "Adakah (my-add 2 3) mengembalikan 5?" Anda memilih input.
  • Pengujian Berasaskan Sifat (dengan clojure.test.check): "Adakah (my-add a b) sentiasa sama dengan (my-add b a) untuk sebarang integer a dan b?" Alat tersebut menjana a dan b.

PBT sangat baik untuk menemukan kes tepi yang mungkin tidak terlintas dalam fikiran anda secara manual.

Mentakrifkan Sifat dengan for-all

Dalam clojure.test.check, anda mentakrifkan sifat menggunakan makro for-all. Makro ini menerima vektor pengikatan (pemboleh ubah yang dipasangkan dengan penjana) dan predikat (fungsi yang harus mengembalikan true jika sifat itu dipenuhi).

Cuba jalankan sifat mudah ini yang menyemak sama ada integer yang dijana sememangnya integer.

(ns my-project.core
  (:require [clojure.test.check :as tc]
            [clojure.test.check.properties :refer [for-all]]
            [clojure.test.check.generators :as gen]))

(defn run-int-property-check []
  (let [result (tc/quick-check 100
                               (for-all [x gen/int]
                                 (<= x (inc x))))] ; Property: x is always <= x+1
    (println "Property check result:" result)))

(defn -main [& args]
  (run-int-property-check))

Membina dengan Penjana

Penjana (daripada clojure.test.check.generators, yang lazimnya diberi alias sebagai gen) ialah fungsi yang menghasilkan data rawak daripada jenis tertentu. Penjana merupakan teras input PBT.

Penjana yang biasa termasuk gen/int, gen/boolean, gen/string dan banyak lagi. Anda juga boleh menggabungkannya!

(ns my-project.core
  (:require [clojure.test.check.generators :as gen]))

(defn generate-and-print []
  (println "Random int:" (gen/generate gen/int))
  (println "Random boolean:" (gen/generate gen/boolean))
  (println "Random string:" (gen/generate gen/string {:max-size 10}))) ; Limit string size for display

(defn -main [& args]
  (generate-and-print))

Melaksanakan Semakan Sifat

Setelah mentakrifkan sifat dengan for-all, anda perlu menjalankannya. clojure.test.check menyediakan fungsi seperti quick-check dan check.

  • tc/quick-check N property: Menjalankan sifat itu sebanyak N kali dan mengembalikan ringkasan.
  • tc/check property: Menyediakan hasil yang lebih terperinci, terutamanya apabila sifat gagal.

Di sini, kita menyemak sama ada operasi tambah adalah kalis tukar tertib (a + b = b + a).

(ns my-project.core
  (:require [clojure.test.check :as tc]
            [clojure.test.check.properties :refer [for-all]]
            [clojure.test.check.generators :as gen]))

(defn check-sum-property []
  (let [sum-property (for-all [a gen/int b gen/int]
                               (= (+ a b) (+ b a)))] ; Addition is commutative
    (println "Checking sum property...")
    (let [result (tc/quick-check 100 sum-property)]
      (println "Result:" result))))

(defn -main [& args]
  (check-sum-property))

Sifat Praktikal: Kebolehbalikan

Satu sifat yang biasa dan berkuasa untuk diuji ialah kebolehbalikan. Jika anda menggunakan suatu operasi dan kemudian songsangannya, anda sepatutnya memperoleh semula input asal.

Mari kita takrifkan fungsi encode dan decode yang mudah (yang hanya menyongsangkan rentetan), lalu semak sama ada (decode (encode s)) sentiasa menghasilkan s.

(ns my-project.core
  (:require [clojure.test.check :as tc]
            [clojure.test.check.properties :refer [for-all]]
            [clojure.test.check.generators :as gen]))

(defn encode [s] (apply str (reverse s))) ; Simple reverse string
(defn decode [s] (apply str (reverse s)))

(defn check-encode-decode-property []
  (let [prop (for-all [s (gen/string-alphanumeric 0 20)] ; Limit string size
                          (= s (decode (encode s))))]
    (println "Checking encode/decode property...")
    (let [result (tc/quick-check 100 prop)]
      (println "Result:" result))))

(defn -main [& args]
  (check-encode-decode-property))

Menemukan Kegagalan Minimum (Pengecilan)

Salah satu ciri paling bernilai bagi clojure.test.check ialah pengecilan. Apabila sesuatu sifat gagal, alat ini bukan sekadar memberikan input pertama yang gagal. Alat ini cuba menemukan input paling kecil yang masih menyebabkan kegagalan.

Ini membantu anda mengenal pasti punca utama pepijat dengan cepat. Jalankan contoh ini: my-buggy-function mempunyai pepijat halus apabila input ialah 0.

(ns my-project.core
  (:require [clojure.test.check :as tc]
            [clojure.test.check.properties :refer [for-all]]
            [clojure.test.check.generators :as gen]))

(defn my-buggy-function [x]
  (if (= x 0) 100 x)) ; Bug: returns 100 if input is 0

(defn check-buggy-property []
  (let [prop (for-all [x gen/int]
                          (> (my-buggy-function x) 0))] ; Property: result is always > 0
    (println "Checking buggy property (expecting failure)...")
    (let [result (tc/quick-check 100 prop)]
      (println "Result (look for 'smallest' failing input):" result))))

(defn -main [& args]
  (check-buggy-property))

Mencipta Penjana Tersuai

Anda tidak terhad kepada penjana asas. Anda boleh mengarangnya atau mengubah outputnya untuk mencipta penjana bagi jenis data yang lebih khusus menggunakan fungsi seperti gen/fmap dan gen/such-that.

gen/fmap (pemetaan fungsi) menggunakan suatu fungsi pada nilai yang dihasilkan oleh penjana lain. Di sini, kita mencipta penjana untuk integer positif.

(ns my-project.core
  (:require [clojure.test.check :as tc]
            [clojure.test.check.properties :refer [for-all]]
            [clojure.test.check.generators :as gen]))

(def gen-positive-int
  (gen/fmap #(inc %) gen/nat)) ; gen/nat produces non-negative numbers, inc makes them positive

(defn check-positive-property []
  (let [prop (for-all [x gen-positive-int]
                          (> x 0))] ; Property: x is always greater than 0
    (println "Checking positive integer property...")
    (let [result (tc/quick-check 100 prop)]
      (println "Result:" result))))

(defn -main [& args]
  (check-positive-property))

Mengarang Penjana

Untuk struktur data yang kompleks, anda boleh menggabungkan berbilang penjana. gen/vector mencipta vektor item yang dijana, gen/tuple mencipta jujukan bersaiz tetap, dan gen/hash-map mencipta peta dengan kunci serta nilai yang dijana.

Berikut ialah contoh penjanaan data 'orang' yang mudah.

(ns my-project.core
  (:require [clojure.test.check.generators :as gen]))

(def gen-person
  (gen/hash-map :name (gen/string-alphanumeric 3 10)
                :age (gen/choose 1 100)))

(defn generate-people []
  (println "Generating 3 people:")
  (dotimes [n 3]
    (println "  " (gen/generate gen-person))))

(defn -main [& args]
  (generate-people))

Semak Pemahaman Anda

Pengujian Berasaskan Sifat mengubah secara asas cara kita memikirkan input ujian.

Imbas Kembali: Pengujian Kukuh dengan PBT

Dalam pelajaran ini, kita meneroka Pengujian Berasaskan Sifat dengan clojure.test.check.

  • Anda belajar mentakrifkan sifat menggunakan for-all.
  • Kita melihat cara penjana (gen/int, gen/string dan sebagainya) mencipta input yang pelbagai.
  • Anda menggunakan quick-check untuk menjalankan sifat anda.
  • Kita membincangkan manfaat pengecilan untuk menemukan kes kegagalan minimum.
  • Akhir sekali, anda belajar mencipta dan mengarang penjana tersuai untuk data kompleks.

PBT ialah alat berkuasa untuk menulis aplikasi Clojure yang lebih kukuh dan boleh dipercayai dengan menguji tingkah laku merentasi julat input yang tidak terhingga!

Percuma untuk bermula

Pelajari Clojure dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
12
Pelajaran
48

Soalan Lazim

Adakah pelajaran “Ujian Berasaskan Sifat dengan clojure.test.check” percuma?

Ya — teks penuh “Ujian Berasaskan Sifat dengan clojure.test.check” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM, tingkat taraf kepada CoddyKit PRO. Kursus Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Ujian Berasaskan Sifat dengan clojure.test.check”?

Pelajari cara menulis ujian teguh yang mengesahkan sifat kod anda merentas pelbagai input menggunakan `clojure.test.check` Anda berlatih Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Ujian Berasaskan Sifat dengan clojure.test.check” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM ini?

Ya. Setiap pelajaran Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Transduser untuk Pemprosesan Cekap
  2. Monad dan Abstraksi Fungsian
  3. Ujian Berasaskan Sifat dengan clojure.test.check
  4. Jujukan Malas dan Strim Tidak Terhingga
← Kembali ke Pengaturcaraan Fungsian Clojure dan Pembangunan Bahagian Belakang JVM