Ačkoliv Rich Hickey říká, že nepíše unit testy, přece jenom do Clojure zahrnul "framework" pro unit testy. Já sám, naopak, jsem již léty TDD infikován a testy píšu rád. Takže, jak se to dělá v Clojure? Nejprve natáhneme knihovnu clojure.test:
Test first! Napíšeme testy (soubor core.clj v adresáři test):
(ns my-tests (:use clojure.test)) ; nil
Aserce (tvrzení)
Základem testů je makro is:(is (= 2 (+ 1 1))) ; true (is (odd? 1)) ; true (is (even? 1) "truth about one") ; ; FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:30) ; truth about one ; expected: (even? 1) ; actual: (not (even? 1)) ; falseVíce assertions/parametrů se dá testovat pomocí makra are:
(are [x y] (= 42 (+ x y)) 21 21 20 22 42 0) ; trueVyhození výjimky se dá otestovat pomocí funkce thrown?:
(is (thrown? ArithmeticException (/ 42 0))) ; #<ArithmeticException java.lang.ArithmeticException: Divide by zero> (is (thrown? ArithmeticException (/ 42 42))) ; ; FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:48) ; expected: (thrown? ArithmeticException (/ 42 42)) ; actual: nil ; nil
Definice testů
OK, to byly tvrzení (assertions). Jak definuji test? Jedna z možností je makro with-test:(with-test (defn add [x y] (+ x y)) (is (= 42 (add 21 21))) (is (= 42 (add 20 22))) (is (= 42 (add 42 0))))Druhou možností je použít makro deftest. Jeho výhodou je, že vytváří funkci (v našem případě ultimate-addition), kterou lze zavolat z libovolného namespace. To umožňuje mít testy v samostatném souboru tak, jak jsme z unit testů zvyklí.
(deftest ultimate-addition (is (= 42 (add 21 21))) (is (= 42 (add 20 22))) (is (= 42 (add 42 0))))
Spuštění testů
Máme definované dva testy (a šest asercí). Jak je spustíme? Testy v aktuálním namespace odpálíme funkcí run-tests:(run-tests) ; ; Testing my-tests ; ; Ran 2 tests containing 6 assertions. ; 0 failures, 0 errors. ; {:type :summary, :pass 6, :test 2, :error 0, :fail 0}Testy v jiném namespace spustíme obdobně:
(run-tests 'some.namespace 'some.other.namespace)
Automatizace testů
Tak. Konec srandiček! Velký kluci buildujou (a spouští testy) Leiningenem. Prvně vytvoříme projekt příkazem lein new lein-tests:Vytvoření a layout projektu |
Test first! Napíšeme testy (soubor core.clj v adresáři test):
(ns lein-tests.test.core (:use [lein-tests.core]) (:use [clojure.test])) (deftest split-line-test (is (= ["foo" "bar"] (split-line "foo;bar" #";"))) (is (= ["foo" "bar"] (split-line "foo,bar" #", ?"))) (is (= ["foo" "bar"] (split-line "foo, bar" #", ?")))) (deftest get-phone-test (is (= "123456789" (get-phone "123456789;Guido"))) (is (= "" (get-phone ";Guido"))))A napíšeme (testované) funkce (soubor core.clj v adresáři src):
(ns lein-tests.core (:use [clojure.string :only (split)])) (defn split-line [line separator] (split line separator)) (defn get-phone [line] (first (split-line line #";")))No a na závěr testy spustíme příkazem lein test. Nádhera!
Spuštění testů |
Žádné komentáře:
Okomentovat
Poznámka: Komentáře mohou přidávat pouze členové tohoto blogu.