返回介绍

12. Testing

发布于 2023-07-23 16:03:27 字数 9670 浏览 0 评论 0 收藏 0

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:

File: 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

:node-test

: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 "-test$".

:autorun

(boolean, optional) Run the tests via node when a build completes. This is mostly meant to be used in combination with watch. The node process exit code will not be returned as that would have to forcefully kill the running JVM.

:main

(qualified symbol, optional) Function called on startup to run the tests, defaults to shadow.test.node/main which runs tests using cljs.test.

Test config matching all *-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

:browser-test

: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 shadow.test.browser.

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 an index.html file present. By default the generated file loads the tests and runs init 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

:karma

: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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文