- 1. Introduction
- 2. Installation
- 3. Usage
- 4. REPL
- 5. Configuration
- 6. Build Configuration
- 7. Targeting the Browser
- 8. Targeting JavaScript Modules
- 9. Targeting React Native
- 10. Targeting node.js
- 11. Embedding in the JS Ecosystem The :npm-module Target
- 12. Testing
- 13. JavaScript Integration
- 14. Generating Production Code All Targets
- 15. Editor Integration
- 16. Troubleshooting
- 17. Publishing Libraries
- 18. What to do when things don’t work?
- 19. Hacking
12. Testing
shadow-cljs
provides a few utility targets to make building tests a little easier.
All test targets generate a test runner and automatically add all namespaces matching the configurable :ns-regexp
. The default test runners were built for cljs.test
but you can create custom runners if you prefer to use other test frameworks.
The default :ns-regexp
is "-test$"
, so your first test could look like:
src/test/demo/app_test.cljs
(ns demo.app-test
(:require [cljs.test :refer (deftest is)]))
(deftest a-failing-test
(is (= 1 2)))
In the Clojure world it is common to keep test files in their own source paths so the above example assumes you have configured :source-paths ["src/main" "src/test"]
in your shadow-cljs.edn
config. Your usual app code goes into src/main
and the tests go into src/test
. This however is optional and it is totally fine to keep everything in src
and just use :source-paths ["src"]
.
12.1. Testing in node.js
This target will create a test runner including all test namespaces matching the given regular expression.
The relevant configuration options are:
:target |
|
:output-to | The final output file that will be used to run tests. |
:ns-regexp | (optional) A regular expression matching namespaces against project files. This only scans files, and will not scan jars. Defaults to |
:autorun | (boolean, optional) Run the tests via |
:main | (qualified symbol, optional) Function called on startup to run the tests, defaults to |
*-spec
namespaces{...
:builds
{:test
{:target :node-test
:output-to "out/node-tests.js"
:ns-regexp "-spec$"
:autorun true}}}
The :node-test
target only generates the test file. You can run it via node
.
$ shadow-cljs compile test
# or
$ shadow-cljs release test
# run tests manually, :autorun will do this automatically
$ node out/node-tests.js
# compile & test combined
$ shadow-cljs compile test && node out/node-tests.js
The node
process exit code will be set to 0
when successful and 1
on any failures. (The node
process exit code will not be returned when using :autorun
.)
12.2. Testing in the Browser
This target is meant for gathering up namespaces that contain tests (based on a filename pattern match), and triggering a test runner. It contains a built-in runner that will automatically scan for cljs.test
tests and run them.
The relevant configuration options are:
:target |
|
:test-dir | A folder in which to output files. See below. |
:ns-regexp | (optional) A regular expression matching namespaces against project files. This only scans files, and will not scan jars. Defaults to "-test$". |
:runner-ns | (optional) A namespace that can contain a start, stop, and init function. Defaults to |
The normal :devtools
options are supported, so you will usually create an http server to serve the files. In general you will need a config that looks like this:
{...
;; tests are served via http://localhost:8021
:dev-http {8021 "out/test"}
:builds
{:test
{:target :browser-test
:test-dir "out/test"}}}
If you choose to supply a custom :runner-ns
, it might look like this:
(ns tests.client-test-main
{:dev/always true}
(:require [shadow.test :as st]
[shadow.test.env :as env]
[cljs-test-display.core :as ctd]
[shadow.dom :as dom]))
(defn start []
(-> (env/get-test-data)
(env/reset-test-data!))
(st/run-all-tests (ctd/init! "test-root")))
(defn stop [done]
; tests can be async. You must call done so that the runner knows you actually finished
(done))
(defn ^:export init []
(dom/append [:div#test-root])
(start))
Then in the build config add :runner-ns tests.client-test-main
.
It just has init
, start
, stop
methods. init
will be called once on startup, stop
will be called before any code is reloaded and start
will be called after all code was reloaded.
Tip | :runner-ns is optional, just leave it out to use the default. |
12.2.1. Generated output in :test-dir
The output includes two primary artifacts in your test-dir
folder:
index.html
- If and only if there was not already anindex.html
file present. By default the generated file loads the tests and runsinit
in the:runner-ns
. You may edit or add a custom version that will not be overwritten.js/test.js
- The Javascript tests. The tests will always have this name. The entries for the module are auto-generated.
Any webserver is fine, :dev-http is just a convenient option.
12.3. Targeting Tests to Karma for Continuous Integration
When you want to run your CLJS tests against a browser on some kind of CI server you’ll need to be able to run the tests from a command line and get back a status code. Karma is a well-known and supported test runner that can do this for you, and shadow-cljs
includes a target that can add the appropriate wrappers around your tests so they will work in it.
12.3.1. Installing Karma
See their website for full instructions. You’ll typically need something like this in your package.json
:
{
"name": "CITests",
"version": "1.0.0",
"description": "Testing",
...
"devDependencies": {
"karma": "^2.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-cljs-test": "^0.1.0",
...
},
"author": "",
"license": "MIT"
}
So, you need Karma, a browser launcher, and the cljs-test integration.
12.3.2. The Build
The build options are:
:target |
|
:output-to | A path/filename for the js file. |
:ns-regexp | (optional) A regex to match the test namespaces, defaults to "-test$ |
So you might have something like this:
{...
:builds
{:ci
{:target :karma
:output-to "target/ci.js"
:ns-regexp "-spec$"}}}
You also need a karma.conf.js
:
module.exports = function (config) {
config.set({
browsers: ['ChromeHeadless'],
// The directory where the output file lives
basePath: 'target',
// The file itself
files: ['ci.js'],
frameworks: ['cljs-test'],
plugins: ['karma-cljs-test', 'karma-chrome-launcher'],
colors: true,
logLevel: config.LOG_INFO,
client: {
args: ["shadow.test.karma.init"],
singleRun: true
}
})
};
then you can run the tests as follows (assuming you’ve installed global executables of the tools):
$ shadow-cljs compile ci
$ karma start --single-run
12 01 2018 01:19:24.222:INFO [karma]: Karma v2.0.0 server started at http://0.0.0.0:9876/
12 01 2018 01:19:24.224:INFO [launcher]: Launching browser ChromeHeadless with unlimited concurrency
12 01 2018 01:19:24.231:INFO [launcher]: Starting browser ChromeHeadless
12 01 2018 01:19:24.478:INFO [HeadlessChrome 0.0.0 (Mac OS X 10.12.6)]: Connected on socket TcfrjxVKmx7xN6enAAAA with id 85554456
LOG: 'Testing boo.sample-spec'
HeadlessChrome 0.0.0 (Mac OS X 10.12.6): Executed 1 of 1 SUCCESS (0.007 secs / 0.002 secs)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论