Slide 1

Slide 1 text

DMPKVSFTQFDͷ࿩ Ծ OJTIJTIJOKVDMPKVSF !BUIPT

Slide 2

Slide 2 text

ࣗݾ঺հ ‣ 5XJUUFS!BUIPT ‣ χϟϯύεגࣜձࣾॴଐ ‣ $MPKVSFίϯτϦϏϡʔλ

Slide 3

Slide 3 text

ૣ଎Ͱ͕͢

Slide 4

Slide 4 text

$MPKVSFͷҰ൪ ϜΧͭ͘ͱ͜Ζͬͯʁ

Slide 5

Slide 5 text

Τϥʔϝοηʔδ ࠾༻ εΫϦϓτΛ࡞Δ೉͠͞ υΩϡϝϯτɾνϡʔτϦΞϧ ੩తܕ͕ͳ͍ $MPKVSFTVSWFZʮ$MPKVSFͷҰ൪ϜΧͭ͘ͱ͜Ζ͸ʁʯ

Slide 6

Slide 6 text

Τϥʔϝοηʔδ

Slide 7

Slide 7 text

‣ $MPKVSFͷΤϥʔͷ෼͔Γʹ͘͞͸Α͘ࢦఠ͞ΕΔ ‣ $MPKVSFͷ૊ࠐΈؔ਺ͷଟ͘͸ΨʔϕδΠϯΨʔϕδ Ξ΢τ ‣ Ҿ਺νΣοΫΛೖΕΔͱɺ+*5ίϯύΠϥͷ࠷దԽΛ ્֐͠ɺύϑΥʔϚϯεʹӨڹ͢ΔͨΊ

Slide 8

Slide 8 text

Կ͕ωοΫ͔ʁ ‣ ύϑΥʔϚϯε໘͔Βߟ͑Δͱ࣮ߦ࣌ͷνΣοΫ͸ ۃྗආ͚͍ͨ ‣ ͔͠͠ɺ੩తܕ͕ͳ͍Ҏ্ίϯύΠϧ͚࣌ͩͰνΣο Ϋ͖͠Δͷ͸೉͍͠ ‣ ։ൃ͚࣌ͩΦϯʹͰ͖ΔҾ਺νΣοΫͷ࢓૊Έ͕͋ Ε͹͍͍

Slide 9

Slide 9 text

DMPKVSFTQFD

Slide 10

Slide 10 text

DMPKVSFTQFD ‣ ࣍ظϦϦʔε$MPKVSFͰͷಋೖ͕ਐΊΒΕ͍ͯΔ৽ػೳ ‣ ੩తܕͰͳ͘ɺड़ޠͷ૊Έ߹ΘͤʹΑͬͯσʔλܕͷ࢓༷ Λهड़͢Δ ‣ Ұ౓࢓༷ εϖοΫ Λॻ͚͹ҰཻͰԿ౓΋͓͍͍͠  υΩϡϝϯςʔγϣϯ  ܖ໿ϓϩάϥϛϯά  ϓϩύςΟϕʔεςετ  ϚΫϩͷߏจνΣοΫ

Slide 11

Slide 11 text

DMPKVSFTQFDͷ࢖͍ํ ‣ [org.clojure/clojure “1.9.0-alphaXX”] Λ:dependenciesʹ௥Ճ ‣ ࠷৽൛͸BMQIB ݱࡏ  ‣ (require ‘[clojure.spec :as s])

Slide 12

Slide 12 text

DMPKVSFTQFDೖ໳

Slide 13

Slide 13 text

ड़ޠ ‣ ड़ޠ CPPMΛฦؔ͢਺ ͸ͦͷ··ͰεϖοΫͱͯ͠ ࢖͑Δ user=> (s/valid? integer? 42) true user=> (s/valid? integer? “foo”) false

Slide 14

Slide 14 text

WBMJE FYQMBJO ‣ WBMJE ͸εϖοΫΛຬ͔ͨ͢Ͳ͏͔Λฦ͢ ‣ FYQMBJO͸εϖοΫΛຬͨ͞ͳ͍ՕॴΛࢦఠ͢Δ user=> (s/valid? integer? “foo”) false user=> (s/explain integer? “foo”) val: "foo" fails predicate: :clojure.spec/unknown nil user=> (s/explain integer? 42) Success! nil

Slide 15

Slide 15 text

εϖοΫͷ߹੒ ‣ BOE΍PSΛ࢖ͬͯෳ਺ͷεϖοΫΛ૊Έ߹ΘͤՄೳ user=> (s/valid? (s/and integer? even?) 0) true user=> (s/valid? (s/and integer? even?) 1) false user=> (s/valid? (s/or :int integer? :str string?) “foo”) true

Slide 16

Slide 16 text

εϖοΫʹ໊લΛ͚ͭΔ ‣ EFGͰεϖοΫʹ໊લΛ͚ͭΔ͜ͱ͕Ͱ͖Δ ‣ εϖοΫࣗମΛ࠶ར༻Ͱ͖Δ user=> (s/def ::answer-to-everything (fn [x] (= x 42)) :user/answer-to-everything user=> (s/valid? ::answer-to-everything 43) false user=> (s/valid? ::answer-to-everything 42) true

Slide 17

Slide 17 text

ίϨΫγϣϯͷεϖοΫ ‣ coll-ofmap-ofͰίϨΫγϣϯͷཁૉ͕εϖοΫ Λຬ͍ͨͯ͠Δ͔νΣοΫͰ͖Δ user=> (s/valid? (s/coll-of integer?) [1 2 3]) true user=> (s/valid? (s/coll-of integer?) [1 :a]) false user=> (s/valid? (s/map-of keyword? integer?) {:a 0, :b 1}) true user=> (s/valid? (s/map-of keyword? integer?) {:a 0, :b “foo”}) false

Slide 18

Slide 18 text

ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯ஋ͷܕ͕ҧ͏ϚοϓͷεϖοΫ΋ఆٛՄೳ user=> (s/def ::x integer?) :user/x user=> (s/def ::y string?) :user/y user=> (s/explain (s/keys :req-un [::x ::y]) {:x 1, :y 2}) In: [:y] val: 2 fails spec: :user/y at: [:y] predicate: string? nil user=> (s/valid? (s/keys :req-un [::x ::y]) {:x 1, :y “foo”}) true

Slide 19

Slide 19 text

DMPKVSFTQFDʹΑΔ ܖ໿ϓϩάϥϛϯά

Slide 20

Slide 20 text

ܖ໿ϓϩάϥϛϯάͱ͸ ‣ ؔ਺ͷݺͼग़͠ʹؔͯ͠ɺࣄલ৚݅ɾࣄޙ৚݅ɾෆ ม৚݅ΛܾΊɺݺͼग़͢ଆͱݺͼग़͞ΕΔଆͷٛ຿ Λ໌֬ʹ͢Δख๏  ݺͼग़͢ଆɿ ؔ਺Λݺͼग़͢લʹࣄલ৚݅ͱෆม৚݅Λຬͨٛ͢຿Λෛ͏  ݺͼग़͞Εͨଆɿ ؔ਺͔Β໭ͬͨޙʹࣄޙ৚݅ͱෆม৚݅Λຬͨٛ͢຿Λෛ͏

Slide 21

Slide 21 text

ؔ਺ʹର͢ΔεϖοΫ ‣ fizzbuzzؔ਺ͷεϖοΫ͸্ͷΑ͏ʹఆٛͰ͖Δ ‣ :args :ret͕ͦΕͧΕࣄલ৚݅ɾࣄޙ৚݅ʹରԠ (s/fdef fizzbuzz :args (s/cat :n (s/and integer? #(> % 0))) :ret (s/or :int integer? :key keyword?)) (defn fizzbuzz [n] (cond (= (mod n 15) 0) :fizzbuzz (= (mod n 5) 0) :buzz (= (mod n 3) 0) “fizz” ;;←όά :else n))

Slide 22

Slide 22 text

JOTUSVNFOU ‣ ؔ਺ʹҾ਺͕εϖοΫΛຬ͍ͨͯ͠Δ͔ͷνΣοΫ ΛΦϯɾΦϑͰ͖Δ user=> (require ‘[clojure.spec.test :as t]) nil user=> (t/instrument) [user/fizzbuzz] user=> (fizzbuzz 15) “fizzbuzz” user=> (fizzbuzz “foo”) ExceptionInfo Call to #'user/fizzbuzz did not conform to spec: In: [0] val: "foo" fails at: [:args :n] predicate: integer? :clojure.spec/args ("foo") … user=>

Slide 23

Slide 23 text

DIFDL ‣ Ҿ਺ͷεϖοΫΛຬͨ͢஋Λࣗಈੜ੒ͯ͠ɺͦͷ஋Λؔ਺ʹ ౉ͨ݁͠Ռ͕໭Γ஋ͷεϖοΫΛຬ͔ͨ͢νΣοΫ͢Δ user=> (t/check) ({:spec … :clojure.spec.test.check/ret {:result #error {:cause "Specification-based check failed” :data {:clojure.spec/problems (… {:path [:ret :key], :pred keyword?, :val “fizz", :via [], :in [], :clojure.spec.test/args (3), :clojure.spec/failure :check-failed}…)} user=>

Slide 24

Slide 24 text

DIFDL ‣ Ҿ਺ͷεϖοΫΛຬͨ͢஋Λࣗಈੜ੒ͯ͠ɺͦͷ஋Λؔ਺ʹ ౉ͨ݁͠Ռ͕໭Γ஋ͷεϖοΫΛຬ͔ͨ͢νΣοΫ͢Δ user=> (t/check) ({:spec … :clojure.spec.test.check/ret {:result #error {:cause "Specification-based check failed” :data {:clojure.spec/problems (… {:path [:ret :key], :pred keyword?, :val “fizz", :via [], :in [], :clojure.spec.test/args (3), :clojure.spec/failure :check-failed}…)} user=> Ͱݺͼग़ͨ͠ͱ͖ʹ ࣦഊ͢Δ͜ͱΛݕग़

Slide 25

Slide 25 text

DMPKVSFTQFDʹΑΔ ϓϩύςΟϕʔεςετ

Slide 26

Slide 26 text

ϓϩύςΟϕʔεςετͱ͸ ‣ ී௨ͷςετ FYBNQMFCBTFEUFTUJOH ͷΑ͏ʹɺ ۩ମతͳςετέʔεʹର͢ΔςετͰ͸ͳ͘ɺ೚ ҙͷೖྗʹରͯ͠੒Γཱͭੑ࣭Λهड़ͨ͠ςετ ‣ ೖྗ஋ͷϥϯμϜʹͨ͘͞Μੜ੒͠ɺͦͷ஋ʹର͠ ͯςετΛ࣮ߦ͢Δ ‣ )BTLFMMͷ2VJDL$IFDL͕༗໊ ‣ $MPKVSFͰ͸UFTUDIFDLΛ࢖͏ͷ͕ελϯμʔυ

Slide 27

Slide 27 text

p[[CV[[ؔ਺ͷςετ ‣ εϖοΫΛຬͨ͢஋Λࣗಈੜ੒͠ɺ͢΂ͯͷ஋ʹର ͯ͠ੑ࣭͕੒Γཱ͔ͭͲ͏͔νΣοΫ͢Δ (ns fizzbuzz-test (:require [clojure.test.check.clojure-test :refer [defspec]] [clojure.test.check.properties :as prop] [clojure.spec :as s] [fizzbuzz :as fb])) (defspec fizzbuzz-prop (prop/for-all [n (s/gen (s/and integer? #(> % 0)))] (let [v (fb/fizzbuzz n)] (cond (= (mod n 3) 0) (contains? #{:fizz :fizzbuzz} v) (= (mod n 5) 0) (contains? #{:buzz :fizzbuzz} v) :else (= n v)))))

Slide 28

Slide 28 text

·ͱΊ ‣ DMPKVSFTQFD͸σʔλܕ΍ؔ਺ͷ࢓༷Λड़ޠͷ૊Έ ߹ΘͤͰهड़͢Δํ๏Λఏڙ͢Δ ‣ Ұ౓εϖοΫΛॻ͘ͱɺίʔσΟϯάத͚ͩͰͳ͘ɺ υΩϡϝϯςʔγϣϯ΍ςετ౳ʹ΋໾ཱͯΒΕΔ ‣ $MPKVSFͷ૊ࠐΈؔ਺ʹର͢ΔεϖοΫ͕༻ҙ͞Ε Ε͹Τϥʔϝοηʔδ΋վળ͞ΕΔ͔΋ʁ

Slide 29

Slide 29 text

ࠓ೔࿩͞ͳ͔ͬͨ͜ͱ ‣ TDPOGPSN ‣ γʔέϯεʹର͢ΔεϖοΫ ‣ εϖοΫʹΑΔϚΫϩͷߏจղੳ ଓ͖͸ͷ-JTQNFFUVQͰʂʂ