Movatterモバイル変換


[0]ホーム

URL:


ClojureScript
Testing

Testing

ClojureScript now ships with a port ofclojure.test in the form ofcljs.test. It attempts to preserve most of the functionality providedbyclojure.test along with enhancements for asynchronous testing in asingle threaded environment.

Most of the functionality is provided via macros ascljs.test relieson compiler reflection and static vars to provide most of itsfunctionality.

For example your testing ns form will probably look something like thefollowing:

(ns my-project.tests  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))

Writing Tests

You can write tests withcljs.test/deftest andcljs.test/is same aswithclojure.test.

For example here is a trivial test with one assertion:

(deftest test-numbers  (is (= 1 1)))

Running Tests

You can run tests by using thecljs.test/run-tests macro. This may bedone in your REPL or at the end of your file. If you have many testnamespaces it’s idiomatic to create a test runner namespace whichimports all of your test namespaces and then invokesrun-tests.

You may have to add(enable-console-print!) before callingrun-tests

Fixtures

You can declare fixtures with thecljs.test/use-fixtures macro. Youcan declare either:once fixtures or:each fixtures.:oncefixtures are run only around all tests within a namespace.:eachfixtures are run around each test. Unlikeclojure.test fixtures aresplit into two parts:before and:after. This is so that fixtureswill work correctly even when used asynchronously.

(use-fixtures :once  {:before (fn [] ...)   :after  (fn [] ...)})

Async Testing

As client-side code tends to be highly asynchronous and JavaScript issingle-threaded, it’s important thatcljs.test provide asynchronoustesting support. You can use thecljs.test/async macro to create anasynchronous block. If you write an asynchronous test the last value youreturnmust be the async block.

(deftest test-async  (async done    (http/get "http://foo.com/api.edn"      (fn [res]        (is (= res :awesome))        (done)))))

done is a function that you may invoke when you are ready torelinquish control and allow the next test to run.done can be calledanything, but it probably makes sense to keep to the convention. All ofyour testing code must be in the async block. If you launch multipleasychronous processes in your async block you will need to coordinatethem. This is a good reason to usecljs.core.async:

(deftest test-async  (let [url0 "http://foo.com/api.edn"        url1 "http://bar.com/api.edn"        res0 (http/get url0)        res1 (http/get url1)]    (async done      (go        (is (= (<! res0) :awesome))        (is (= (<! res1) :cool))        (done)))))

NOTE: You cannot have more than one async test perdeftest form oronly the first one will run.

Bad:

(deftest test-async  (testing "the API is awesome" ; <-- only this test will run    (let [url "http://foo.com/api.edn"          res (http/get url)]      (async done        (go          (is (= (<! res) :awesome))          (done)))))    (testing "the API is cool"      (let [url "http://bar.com/api.edn"            res (http/get url)]        (async done          (go            (is (= (<! res1) :cool))            (done))))))

Good:

(deftest test-async-awesome  (testing "the API is awesome"    (let [url "http://foo.com/api.edn"          res (http/get url)]      (async done        (go          (is (= (<! res) :awesome))          (done))))))(deftest test-async-cool  (testing "the API is cool"    (let [url "http://bar.com/api.edn"          res (http/get url)]      (async done        (go          (is (= (<! res1) :cool))          (done))))))

Async Fixtures

Often establishing your testing environment means you need your fixturesto be asynchronous too. This is easily accomplished:

(use-fixtures :once  {:before   #(async done      ...      (done))   :after   #(do ...)})

In this case:before will need to complete before any test can run.:after will complete immediately after all tests have run since itdoes not use an async block.

Detecting Test Completion & Success

Often it’s useful to be able to run some code after all tests havecompleted successfully (or unsuccessfully). Because tests may run asynccljs.test/run-tests does not return a meaningful value. You canhowever add a test report event listener by adding a method to thecljs.test/report multimethod.

(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m]  (if (cljs.test/successful? m)    (println "Success!")    (println "FAIL")))
Documentation
OverviewReferenceToolsGuides
Community
ResourcesContributingCompaniesEvents
Code
API CheatsheetSourceChangelog
ETC
ClojureTV
Legal
LicensePrivacy Policy
 
Copyright Rich Hickey |Privacy Policy
Published 2025-05-16
Site design by Tom Hickey

[8]ページ先頭

©2009-2025 Movatter.jp