├── .clj-kondo └── imports │ ├── http-kit │ └── http-kit │ │ ├── config.edn │ │ └── httpkit │ │ └── with_channel.clj │ ├── metosin │ └── malli │ │ └── config.edn │ └── rewrite-clj │ └── rewrite-clj │ └── config.edn ├── .github └── FUNDING.yml ├── .gitignore ├── .lsp └── config.edn ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bases └── external-test-runner-cli │ ├── deps.edn │ ├── src │ └── org │ │ └── corfield │ │ └── external_test_runner_cli │ │ └── main.clj │ └── test │ └── org │ └── corfield │ └── external_test_runner_cli │ └── main_test.clj ├── components ├── external-test-runner │ ├── deps.edn │ ├── src │ │ └── org │ │ │ └── corfield │ │ │ └── external_test_runner │ │ │ ├── core.clj │ │ │ └── interface.clj │ └── test │ │ └── org │ │ └── corfield │ │ └── external_test_runner │ │ ├── core_test.clj │ │ ├── ignored_test.cljs │ │ └── interface_test.cljc └── util │ ├── deps.edn │ └── src │ └── org │ └── corfield │ └── util │ ├── colorizer.clj │ └── interface │ └── color.clj ├── deps.edn ├── development ├── config.edn └── src │ └── .keep ├── projects └── runner │ ├── config.edn │ └── deps.edn ├── run-tests.sh └── workspace.edn /.clj-kondo/imports/http-kit/http-kit/config.edn: -------------------------------------------------------------------------------- 1 | 2 | {:hooks 3 | {:analyze-call {org.httpkit.server/with-channel httpkit.with-channel/with-channel}}} 4 | -------------------------------------------------------------------------------- /.clj-kondo/imports/http-kit/http-kit/httpkit/with_channel.clj: -------------------------------------------------------------------------------- 1 | (ns httpkit.with-channel 2 | (:require [clj-kondo.hooks-api :as api])) 3 | 4 | (defn with-channel [{node :node}] 5 | (let [[request channel & body] (rest (:children node))] 6 | (when-not (and request channel) (throw (ex-info "No request or channel provided" {}))) 7 | (when-not (api/token-node? channel) (throw (ex-info "Missing channel argument" {}))) 8 | (let [new-node 9 | (api/list-node 10 | (list* 11 | (api/token-node 'let) 12 | (api/vector-node [channel (api/vector-node [])]) 13 | request 14 | body))] 15 | 16 | {:node new-node}))) 17 | -------------------------------------------------------------------------------- /.clj-kondo/imports/metosin/malli/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as {malli.experimental/defn schema.core/defn} 2 | :linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}} 3 | -------------------------------------------------------------------------------- /.clj-kondo/imports/rewrite-clj/rewrite-clj/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as 2 | {rewrite-clj.zip/subedit-> clojure.core/-> 3 | rewrite-clj.zip/subedit->> clojure.core/->> 4 | rewrite-clj.zip/edit-> clojure.core/-> 5 | rewrite-clj.zip/edit->> clojure.core/->>}} 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: seancorfield 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.jar 3 | .calva/output-window/output.calva-repl 4 | .calva/repl.calva-repl 5 | .clj-kondo/.cache 6 | .cpcache/ 7 | .lein-deps-sum 8 | .lein-failures 9 | .lein-plugins/ 10 | .lein-repl-history 11 | .lsp/.cache 12 | .nrepl-port 13 | .portal/vs-code.edn 14 | .socket-repl-port 15 | /checkouts/ 16 | /classes/ 17 | /lib/ 18 | /target/ 19 | pom.xml 20 | pom.xml.asc 21 | -------------------------------------------------------------------------------- /.lsp/config.edn: -------------------------------------------------------------------------------- 1 | {:source-aliases #{:dev :test}} -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | * v0.7.0 in progress 4 | * Switch from `bricks-to-test` to `bricks-to-test-all-sources` in Polylith 0.2.22. 5 | * Drop support for WS v2.0 (`changes` data moved to `project` in v3.0). 6 | 7 | v0.6.1 d0f51c2 -- 2024-12-02 8 | * Fix [#11](https://github.com/seancorfield/polylith-external-test-runner/issues/11) by supporting `:jvm-opts` in `poly test` property handling. 9 | * Address [#8](https://github.com/seancorfield/polylith-external-test-runner/issues/8) by noting that the standalone `poly` tool cannot be used with external test runners. 10 | 11 | v0.6.0 90e8ac1 -- 2024-11-19 12 | * Add support for [lazytest](https://github.com/noahtheduke/lazytest). 13 | * Polylith 0.2.21 is released and stable: update various references accordingly. 14 | 15 | v0.5.0 d93a147 -- 2024-06-20 16 | * Address [#5](https://github.com/seancorfield/polylith-external-test-runner/issues/5) and [#6](https://github.com/seancorfield/polylith-external-test-runner/issues/6) by adding support for a `:test` settings key of `:org.corfield/external-test-runner` that can specify configuration for this test runner. Currently, it supports `:include-src-dir` (`true`/`false`) and `:focus` which takes a hash map of `:var`, `:include`, `:exclude` keys to match [Cognitect's test runner](https://github.com/cognitect-labs/test-runner). Documentation TBD. 17 | * Polylith 0.2.19 is released and stable: update various references accordingly. 18 | * Update default Clojure version to 1.11.3; also update tools.deps. 19 | 20 | v0.4.0 eb954fe -- 2024-01-25 21 | * Make the runner compatible with both Polylith 0.2.19-SNAPSHOT and 0.2.18/17. 22 | 23 | v0.3.0 9f6391a -- 2023-10-28 24 | * Fix [#4](https://github.com/seancorfield/polylith-external-test-runner/issues/4) by guarding `str/split` with `when java-opts`. 25 | 26 | v0.2.0 f208856 -- 2023-02-23 27 | * Fix [#3](https://github.com/seancorfield/polylith-external-test-runner/issues/3) by switching to `tools.deps` and updating dependencies. 28 | 29 | v0.1.0 337f117 -- 2022-12-09 30 | * First stable release. 31 | 32 | ## Development 33 | 34 | 2022-11-28 35 | * Fix [#2](https://github.com/seancorfield/polylith-external-test-runner/issues/2) by allowing JVM opts to be specified as an alias, and resolved to a vector of strings; added tests for this. 36 | * Fix [#1](https://github.com/seancorfield/polylith-external-test-runner/issues/1) by improving Java discovery. 37 | 38 | 2022-11-15 39 | * Use a JVM property if an environment variable isn't set to specify the JVM options for the `java` subprocess. 40 | 41 | 2022-11-14 42 | * Initial version for testing and discussion around [polyfy/polylith#260](https://github.com/polyfy/polylith/issues/260). 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # polylith-external-test-runner 2 | 3 | An external (subprocess) test runner for [Polylith](https://github.com/polyfy/polylith). 4 | 5 | Avoids classloader, daemon thread, and memory usage issues 6 | by running tests in a (Java) subprocess with only Clojure itself as a 7 | dependency. 8 | 9 | ## Usage 10 | 11 | Ensure you are using a recent version Polylith that supports 12 | external test runners (v0.2.22-SNAPSHOT #2 or later). 13 | 14 | You must be using a `:poly` alias in your `deps.edn` file to run the Polylith 15 | tool and tests, since you need to be able to modify the classpath to add an 16 | external test runnner. You cannot use the standalone `poly` tool for this. 17 | 18 | Add the following dependency to your `:poly` alias to 19 | make this test-runner available: 20 | 21 | ```clojure 22 | io.github.seancorfield/polylith-external-test-runner 23 | {;:git/tag "v0.6.1" :git/sha "d0f51c2" -- supports Polylith 0.2.18 and later 24 | :git/sha "" 25 | :deps/root "projects/runner"} 26 | ``` 27 | 28 | In your `workspace.edn` file, either add this global configuration 29 | to run all of your projects' tests in subprocesses: 30 | 31 | ```clojure 32 | :test 33 | {:create-test-runner 34 | [org.corfield.external-test-runner.interface/create]} 35 | ``` 36 | 37 | Alternatively, to run just specific projects in subprocesses, 38 | add that `:create-test-runner` entry to those specific projects. 39 | 40 | See also **Test Configuration** below for new functionality available with Polylith 0.2.20+. 41 | 42 | ### Finding Java 43 | 44 | The test runner checks the `JAVA_CMD` environment variable and will use 45 | that value if set, else it checks the `JAVA_HOME` environment variable 46 | and will use the value `${JAVA_HOME}/bin/java` is that is set, else it 47 | assumes `java` is on your classpath and can be used as-is. 48 | 49 | ### Passing JVM Options 50 | 51 | Since the tests are executed in a `java` subprocess, you may need to 52 | provide JVM options to control how it runs. You can specify the JVM 53 | options for the subprocess in two ways: 54 | * via the `POLY_TEST_JVM_OPTS` environment variable, 55 | * via the `poly.test.jvm.opts` JVM property. 56 | 57 | The former can be set in your shell process, for the `clojure -M:poly test` command. 58 | The latter can be set in the `:poly` alias via: 59 | ```clojure 60 | :jvm-opts ["-Dpoly.test.jvm.opts=..."] 61 | ``` 62 | 63 | The value of the environment variables or the JVM property should either be: 64 | * a space-separated list of all the JVM options you need, 65 | * a Clojure keyword that will be looked up as an alias in your workspace-level `deps.edn` file. 66 | 67 | The latter allows multiple options to be specified more easily, and also 68 | allows for other aliases to be used in those vectors of options, which are 69 | looked up recursively (a similar ability has been [proposed for `tools.deps.alpha`](https://clojure.atlassian.net/browse/TDEPS-184)). 70 | See this project's [`deps.edn` file](https://github.com/seancorfield/polylith-external-test-runner/blob/main/deps.edn) 71 | for an example (which is used in the tests for this project). 72 | 73 | As of v0.6.1, these aliases can refer to hash maps containing `:jvm-opts` keys, 74 | making it easier to reuse existing aliases for the testing context. 75 | 76 | ## Test Configuration 77 | 78 | > Note: this functionality is new in v0.5.0 and is primarily intended for use with Polylith 0.2.20 or later. 79 | 80 | By default, this test runner only looks for tests in the `test` directories 81 | of bricks and projects. You can configure it to also looks for tests in the 82 | `src` directories as well, using the `:include-src-dir true` option (the 83 | default is `false`). 84 | 85 | In addition, like the [Cognitect's test runner](https://github.com/cognitect-labs/test-runner), 86 | you can specify that only certain tests should be run, either by specifying 87 | a collection of fully-qualified test names (`:var`), or by specifying 88 | keywords to include or exclude tests via metadata (`:include` and `:exclude`). 89 | These can be provided in a `:focus` option as a hash map, and may be combined. 90 | 91 | As of v0.6.0, this test runner also supports [LazyTest](https://github.com/NoahTheDuke/lazytest). 92 | The same `:focus` options are supported for LazyTest as for Cognitect's test runner 93 | (and under the hood `:var` is mapped to `:var-filter` etc). In addition, you can 94 | specify `:output`, under `:focus`, as a symbol to control the reporting of 95 | test passes and failures. Test suites can contain a mix of both 96 | `clojure.test`-compatible tests and LazyTest tests. 97 | 98 | ### Polylith 0.2.20+ 99 | 100 | If you are using the current 0.2.20-SNAPSHOT version of Polylith or later, you can 101 | provide these options in `workspace.edn` under the `:test-configs` key, and 102 | this test runner looks for the `:org.corfield/external-test-runner` key within 103 | those configurations. 104 | 105 | ```clojure 106 | ;; in your deps.edn file: 107 | polylith/clj-poly {:mvn/version "0.2.21"} 108 | 109 | ;; in your workspace.edn file: 110 | :test {:create-test-runner [org.corfield.external-test-runner.interface/create]} 111 | 112 | :test-configs {:source {:org.corfield/external-test-runner 113 | {:include-src-dir true}} 114 | :slow {:org.corfield/external-test-runner 115 | {:focus {:include [:slow]}}}} 116 | ``` 117 | 118 | Now you can use `clojure -M:poly test with:source` to run tests in both `test` and `src` 119 | directories, or `clojure -M:poly test with:slow` to run only tests defined with `^:slow` or 120 | `^{:slow true}` metadata. You can combine these options as well: `clojure -M:poly test with:source:slow`. 121 | 122 | See [Test configuration](https://cljdoc.org/d/polylith/clj-poly/CURRENT/doc/test-runners#test-configuration) 123 | in the Polylith 0.2.20-SNAPSHOT documentation for more details. 124 | 125 | > Note: whether you use a single value or a vector for `:create-test-runner` matters in Polylith 0.2.20+ when you use the new `with` syntax for test configurations. 126 | 127 | ### Configuration Via Environment Variable 128 | 129 | If you are using an earlier version of Polylith, you can provide these options 130 | via the `ORG_CORFIELD_EXTERNAL_TEST_RUNNER` environment variable, as a string 131 | that is read as an EDN hash map: 132 | 133 | ```bash 134 | ORG_CORFIELD_EXTERNAL_TEST_RUNNER="{:include-src-dir true}" clojure -M:poly test 135 | ``` 136 | 137 | > Note: you can also use the environment variable with Polylith 0.2.20+ to override `:include-src-dir` or `:focus` from the `:test-configs` setting, via a simple merge. 138 | 139 | ## License & Copyright 140 | 141 | External test runner copyright (c) 2022-2024, Sean Corfield, 142 | Apache Source License 2.0. 143 | 144 | Colorizer and string util code copyright (c) 2020-2021, Joakim Tengstrand and others, Eclipse Public License 1.0. 145 | -------------------------------------------------------------------------------- /bases/external-test-runner-cli/deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"] 2 | :deps {} 3 | :aliases {:test {:extra-paths ["test"] 4 | :extra-deps {}}}} 5 | -------------------------------------------------------------------------------- /bases/external-test-runner-cli/src/org/corfield/external_test_runner_cli/main.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner-cli.main 2 | (:require [clojure.edn :as edn] 3 | [clojure.set :as set] 4 | [clojure.string :as str] 5 | [clojure.test :as test] 6 | [org.corfield.util.interface.color :as color])) 7 | 8 | (defn execute-fn [function fn-type project-name color-mode] 9 | (if function 10 | (do 11 | (println (str "Running test " fn-type " for the " (color/project project-name color-mode) 12 | " project: " function)) 13 | (try 14 | (if-let [fun (requiring-resolve (symbol function))] 15 | (fun project-name) 16 | (do 17 | (println (color/error color-mode (str "Could not find " fn-type " function: " function))) 18 | false)) 19 | true 20 | (catch Throwable t 21 | (let [message (str (or (some-> t .getCause) (.getMessage t)))] 22 | (println (color/error color-mode (str "\nTest " fn-type " failed: " message))) 23 | false)))) 24 | true)) 25 | 26 | (defn- filter-vars! 27 | "Copied from https://github.com/cognitect-labs/test-runner/blob/7284cda41fb9edc0f3bc6b6185cfb7138fc8a023/src/cognitect/test_runner.clj#L37 28 | and adjusted for a single namespace. 29 | `clojure.test`-only for now." 30 | [ns filter-fn] 31 | (doseq [[_name var] (ns-publics ns)] 32 | (when (:test (meta var)) 33 | (when (not (filter-fn var)) 34 | (alter-meta! var #(-> % 35 | (assoc ::test (:test %)) 36 | (dissoc :test))))))) 37 | 38 | (defn- var-filter 39 | "Copied from https://github.com/cognitect-labs/test-runner/blob/7284cda41fb9edc0f3bc6b6185cfb7138fc8a023/src/cognitect/test_runner.clj#L19C1-L35C32" 40 | [{:keys [var include exclude]}] 41 | (let [test-specific (if var 42 | #((set (keep resolve var)) %) 43 | (constantly true)) 44 | test-inclusion (if include 45 | #((apply some-fn include) (meta %)) 46 | (constantly true)) 47 | test-exclusion (if exclude 48 | #((complement (apply some-fn exclude)) (meta %)) 49 | (constantly true))] 50 | #(and (test-specific %) 51 | (test-inclusion %) 52 | (test-exclusion %)))) 53 | 54 | (defn- restore-vars! 55 | "Copied from https://github.com/cognitect-labs/test-runner/blob/7284cda41fb9edc0f3bc6b6185cfb7138fc8a023/src/cognitect/test_runner.clj#L47 56 | and adjusted for a single namespace. 57 | `clojure.test`-only for now." 58 | [ns] 59 | (doseq [[_name var] (ns-publics ns)] 60 | (when (::test (meta var)) 61 | (alter-meta! var #(-> % 62 | (assoc :test (::test %)) 63 | (dissoc ::test)))))) 64 | 65 | (defn- contains-tests? 66 | "Check if a namespace contains some tests to be executed. 67 | The predicate determines how to identify a test." 68 | [ns pred] 69 | (some pred (-> ns ns-publics vals))) 70 | 71 | (defn -main [& args] 72 | (when-not (<= 3 (count args)) 73 | (println "Requires the color-mode, the project name, and at least one namespace to test") 74 | (System/exit 1)) 75 | 76 | (let [options (-> (System/getProperty "org.corfield.external-test-runner.opts") 77 | (or "{}") 78 | (edn/read-string)) 79 | filter-fn (var-filter (:focus options)) 80 | [color-mode & args] args 81 | [project-name & args] args 82 | [setup-fn & nses] 83 | (if (str/includes? (first args) "/") 84 | args 85 | (cons nil args)) 86 | [teardown-fn nses] 87 | (let [poss-teardown (last nses)] 88 | (if (and poss-teardown (str/includes? poss-teardown "/")) 89 | [poss-teardown (butlast nses)] 90 | [nil nses])) 91 | lazy-run 92 | (try (requiring-resolve 'lazytest.repl/run-tests) 93 | (catch Exception _ nil)) 94 | is-test? ; is var a clojure.test test? 95 | (fn [v] (-> v (meta) :test)) 96 | lazy-find ; is var a lazytest test? 97 | (try (requiring-resolve 'lazytest.find/find-var-test-value) 98 | (catch Exception _ nil)) 99 | lazy-opts {:var :var-filter :namespace :ns-filter} 100 | merge-summaries 101 | (fn [sum1 sum2] 102 | (dissoc (merge-with + sum1 sum2) :skip))] 103 | (if (execute-fn setup-fn "setup" project-name color-mode) 104 | (try 105 | (doseq [test-ns nses] 106 | (let [test-sym (symbol test-ns) 107 | {:keys [error fail pass skip]} 108 | (try 109 | (require test-sym) 110 | (filter-vars! test-sym filter-fn) 111 | ;; assume no tests in ns (test-sym), i.e., skip the ns -- 112 | ;; if we find tests, we'll run the appropriate test runner, 113 | ;; merge those results into the summary and remove :skip 114 | (cond-> {:error 0 :fail 0 :pass 0 :skip true} 115 | (contains-tests? test-sym is-test?) 116 | (merge-summaries (test/run-tests test-sym)) 117 | (and lazy-run lazy-find 118 | (contains-tests? test-sym lazy-find)) 119 | (merge-summaries (lazy-run test-sym 120 | (set/rename-keys (:focus options) 121 | lazy-opts)))) 122 | (catch Exception e 123 | (.printStackTrace e) 124 | (println (str (color/error color-mode "Couldn't run test statement") 125 | " for the " (color/project project-name color-mode) 126 | " project: " test-ns " " (color/error color-mode e)))) 127 | (finally 128 | (restore-vars! test-sym))) 129 | result-str (str "Test results: " pass " passes, " fail " failures, " error " errors.")] 130 | (when-not skip 131 | (when (or (nil? error) 132 | (< 0 error) 133 | (< 0 fail)) 134 | (throw (Exception. (str "\n" (color/error color-mode result-str)))))) 135 | (if skip 136 | (println (str "\nNo " 137 | (when (seq (:focus options)) "applicable ") 138 | "tests found in " test-ns)) 139 | (println (str "\n" (color/ok color-mode result-str)))))) 140 | (finally 141 | (when-not (execute-fn teardown-fn "teardown" project-name color-mode) 142 | (throw (ex-info "Test terminated due to teardown failure" 143 | {:project project-name}))))) 144 | (throw (ex-info (str "Test terminated due to setup failure") 145 | {:project project-name}))) 146 | (shutdown-agents) 147 | (System/exit 0))) 148 | -------------------------------------------------------------------------------- /bases/external-test-runner-cli/test/org/corfield/external_test_runner_cli/main_test.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner-cli.main-test 2 | (:require [clojure.test :refer [deftest is]] 3 | [org.corfield.external-test-runner-cli.main])) 4 | 5 | (deftest ^:integration ^:dev jvm-opts-test 6 | ;; inside the tests, this option should not be set: 7 | (is (= nil (System/getProperty "poly.test.jvm.opts"))) 8 | ;; but this option, set via a keyword, should be: 9 | (is (= "opts" (System/getProperty "example"))) 10 | ;; and so should this, set recursively: 11 | (is (= "more.opts" (System/getProperty "sub.example"))) 12 | ;; and issue #11 should set this too, recursively: 13 | (is (= "even.more.opts" (System/getProperty "nested.example")))) 14 | -------------------------------------------------------------------------------- /components/external-test-runner/deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"] 2 | :deps {org.clojure/tools.deps {:mvn/version "0.21.1449"}} 3 | :aliases {:test {:extra-paths ["test"] 4 | :extra-deps {}}}} 5 | -------------------------------------------------------------------------------- /components/external-test-runner/src/org/corfield/external_test_runner/core.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner.core 2 | (:require [clojure.edn :as edn] 3 | [clojure.java.io :as io] 4 | [clojure.string :as str] 5 | [clojure.test :refer [is]] 6 | [clojure.tools.deps :as deps] 7 | [polylith.clj.core.test-runner-contract.interface :as test-runner-contract] 8 | [polylith.clj.core.util.interface.color :as color] 9 | [polylith.clj.core.util.interface.str :as str-util]) 10 | (:import (java.lang ProcessBuilder ProcessBuilder$Redirect) 11 | (java.util List))) 12 | 13 | (defn- clj-namespace? [{:keys [file-path]}] 14 | (or (str/ends-with? file-path ".clj") 15 | (str/ends-with? file-path ".cljc"))) 16 | 17 | (defn brick-test-namespaces [options bricks test-brick-names] 18 | (let [nses-fn (fn [selectors] 19 | (juxt :name 20 | #(mapcat (fn [selector] 21 | (-> % :namespaces selector)) 22 | selectors))) 23 | selectors (cond-> [:test] 24 | (:include-src-dir options) 25 | (conj :src)) 26 | brick-name->namespaces 27 | (into {} (map (nses-fn selectors)) bricks)] 28 | (into [] 29 | (comp (mapcat brick-name->namespaces) 30 | (filter clj-namespace?) 31 | (map :namespace)) 32 | test-brick-names))) 33 | 34 | (defn project-test-namespaces [options project-name projects-to-test namespaces] 35 | (when (contains? (set projects-to-test) project-name) 36 | (cond-> (mapv :namespace (:test namespaces)) 37 | (:include-src-dir options) 38 | (into (mapv :namespace (:src namespaces)))))) 39 | 40 | (defn components-msg [component-names color-mode] 41 | (when (seq component-names) 42 | [(color/component (str/join ", " component-names) color-mode)])) 43 | 44 | (defn bases-msg 45 | ;; this is a test function in the src directory: 46 | {:test (fn [] (is (= nil (bases-msg [] nil))))} 47 | [base-names color-mode] 48 | (when (seq base-names) 49 | [(color/base (str/join ", " base-names) color-mode)])) 50 | 51 | (defn run-message [project-name components bases bricks-to-test projects-to-test color-mode] 52 | (let [component-names (into #{} (map :name) components) 53 | base-names (into #{} (map :name) bases) 54 | bases-to-test (filterv #(contains? base-names %) bricks-to-test) 55 | bases-to-test-msg (bases-msg bases-to-test color-mode) 56 | components-to-test (filterv #(contains? component-names %) bricks-to-test) 57 | components-to-test-msg (components-msg components-to-test color-mode) 58 | projects-to-test-msg (when (seq projects-to-test) 59 | [(color/project (str/join ", " projects-to-test) color-mode)]) 60 | entities-msg (str/join ", " (into [] cat [components-to-test-msg 61 | bases-to-test-msg 62 | projects-to-test-msg])) 63 | project-cnt (count projects-to-test) 64 | bricks-cnt (count bricks-to-test) 65 | project-msg (if (zero? project-cnt) 66 | "" 67 | (str " and " (str-util/count-things "project" project-cnt)))] 68 | (str "Running tests from the " (color/project project-name color-mode) " project, including " 69 | (str-util/count-things "brick" bricks-cnt) project-msg ": " entities-msg))) 70 | 71 | (defn ns->src [ns-str] 72 | (let [file-sep (System/getProperty "file.separator") 73 | ns-path (-> ns-str 74 | (str/replace "." file-sep) 75 | (str/replace "-" "_") 76 | (str ".clj"))] 77 | (-> ns-path 78 | (io/resource) 79 | (.getFile) 80 | (str/replace (str file-sep ns-path) "")))) 81 | 82 | (defn- find-java [] 83 | (let [java-cmd (or (System/getenv "JAVA_CMD") 84 | (when-let [home (System/getenv "JAVA_HOME")] 85 | (str home "/bin/java")))] 86 | (if (and java-cmd (.exists (io/file java-cmd))) 87 | java-cmd 88 | "java"))) 89 | 90 | (defn- get-project-aliases [] 91 | (let [edn-fn (juxt :root-edn :project-edn)] 92 | (-> (deps/find-edn-maps) 93 | (edn-fn) 94 | (deps/merge-edns) 95 | :aliases))) 96 | 97 | (defn- chase-opts-key 98 | "Given an aliases set and a keyword k, return a flattened vector of 99 | options for that k, resolving recursively if needed, or nil. 100 | Options can be a vector, or a hash map containing :jvm-opts identifying 101 | a vector, of JVM options." 102 | [aliases k] 103 | (let [opts-coll (get aliases k) 104 | ;; per issue #11, unroll :jvm-opts if needed: 105 | opts-coll (or (:jvm-opts opts-coll) opts-coll)] 106 | (when (seq opts-coll) 107 | (into [] (mapcat #(if (string? %) [%] (chase-opts-key aliases %))) opts-coll)))) 108 | 109 | (comment 110 | (let [options {:include-src-dir true}] 111 | (str "-Dorg.corfield.external-test-runner.opts='" 112 | (-> (pr-str (or options {})) 113 | (str/replace "'" "''")) 114 | "'")) 115 | ) 116 | 117 | (defn create 118 | [{:keys [workspace project test-settings] :as all}] 119 | (let [env-opts (-> (System/getenv "ORG_CORFIELD_EXTERNAL_TEST_RUNNER") 120 | (or "{}") 121 | (edn/read-string)) 122 | ws-opts (-> workspace :settings :test) 123 | options (merge (:org.corfield/external-test-runner test-settings) 124 | (:org.corfield/external-test-runner ws-opts) 125 | env-opts) 126 | _ 127 | (when (seq options) 128 | (println "Test runner options:") 129 | (doseq [[k v] options] 130 | (println " " k "=>" v)) 131 | (println "")) 132 | {:keys [bases components]} workspace 133 | {:keys [name namespaces paths projects-to-test]} project 134 | bricks-to-test (if (:include-src-dir options) 135 | (or (:bricks-to-test-all-sources project) 136 | (:bricks-to-test project)) 137 | (:bricks-to-test project)) 138 | 139 | ;; TODO: if the project tests aren't to be run, we might further narrow this down 140 | test-sources-present (-> paths :test seq) 141 | test-nses* (->> [(brick-test-namespaces options (into components bases) bricks-to-test) 142 | (project-test-namespaces options name projects-to-test namespaces)] 143 | (into [] cat) 144 | (delay)) 145 | path-sep (System/getProperty "path.separator") 146 | my-runner-ns "org.corfield.external-test-runner-cli.main" 147 | colorizer-ns "org.corfield.util.interface.color" 148 | java-opts (or (System/getenv "POLY_TEST_JVM_OPTS") 149 | (System/getProperty "poly.test.jvm.opts")) 150 | opt-key (when (and java-opts (re-find #"^:[-a-zA-Z0-9]+$" java-opts)) 151 | (keyword (subs java-opts 1))) 152 | java-opts (if opt-key 153 | (into [] (remove nil?) (chase-opts-key (get-project-aliases) opt-key)) 154 | (when java-opts (str/split java-opts #" "))) 155 | ;; turn the options hash into a vector of JVM options that the CLI 156 | ;; test runner can recognize: 157 | options-as-jvm (cond-> [] 158 | (seq options) 159 | (conj (str "-Dorg.corfield.external-test-runner.opts=" 160 | (pr-str options))))] 161 | 162 | (reify test-runner-contract/TestRunner 163 | (test-runner-name [_] "Polylith org.corfield.external-test-runner") 164 | 165 | (test-sources-present? [_] test-sources-present) 166 | 167 | (tests-present? [this {_eval-in-project :eval-in-project :as _opts}] 168 | (and (test-runner-contract/test-sources-present? this) 169 | (seq @test-nses*))) 170 | 171 | (run-tests [this {:keys [all-paths setup-fn teardown-fn process-ns color-mode] :as opts}] 172 | (when (test-runner-contract/tests-present? this opts) 173 | (let [run-message (run-message name components bases bricks-to-test 174 | projects-to-test color-mode) 175 | _ (println run-message) 176 | classpath (str/join path-sep 177 | (->> all-paths 178 | (cons (ns->src colorizer-ns)) 179 | (cons (ns->src my-runner-ns)))) 180 | test-args (cond-> [color-mode name] 181 | setup-fn 182 | (conj (str setup-fn)) 183 | :always 184 | (into (deref test-nses*)) 185 | teardown-fn 186 | (conj (str teardown-fn))) 187 | java-cmd (-> (cond-> [(find-java)] 188 | java-opts 189 | (into java-opts) 190 | (seq options-as-jvm) 191 | (into options-as-jvm)) 192 | (into ["-cp" classpath 193 | "clojure.main" "-m" process-ns]) 194 | (into test-args)) 195 | pb (doto (ProcessBuilder. ^List java-cmd) 196 | (.redirectOutput ProcessBuilder$Redirect/INHERIT) 197 | (.redirectError ProcessBuilder$Redirect/INHERIT))] 198 | (when-not (-> pb (.start) (.waitFor) (zero?)) 199 | (throw (ex-info "External test runner failed" {:process-ns process-ns})))))) 200 | test-runner-contract/ExternalTestRunner 201 | (external-process-namespace [_] my-runner-ns)))) 202 | -------------------------------------------------------------------------------- /components/external-test-runner/src/org/corfield/external_test_runner/interface.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner.interface 2 | (:require [org.corfield.external-test-runner.core :as core])) 3 | 4 | (defn create [opts] 5 | (core/create opts)) 6 | -------------------------------------------------------------------------------- /components/external-test-runner/test/org/corfield/external_test_runner/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner.core-test 2 | (:require [clojure.test :refer [deftest is]] 3 | [org.corfield.external-test-runner.core])) 4 | 5 | (deftest dummy-test 6 | (is (= 1 1))) 7 | -------------------------------------------------------------------------------- /components/external-test-runner/test/org/corfield/external_test_runner/ignored_test.cljs: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner.ignored-test 2 | (:require [clojure.test :refer [deftest is]] 3 | [org.corfield.external-test-runner.core])) 4 | 5 | (deftest dummy-test 6 | ;; I should not run because I'm ClojureScript 7 | (is (= 1 0))) 8 | -------------------------------------------------------------------------------- /components/external-test-runner/test/org/corfield/external_test_runner/interface_test.cljc: -------------------------------------------------------------------------------- 1 | (ns org.corfield.external-test-runner.interface-test 2 | (:require [clojure.test :refer [deftest is]] 3 | [org.corfield.external-test-runner.interface])) 4 | 5 | (deftest ^:dev dummy-test 6 | ;; I should run because I'm .cljc 7 | (is (= 1 1))) 8 | -------------------------------------------------------------------------------- /components/util/deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"] 2 | :deps {} 3 | :aliases {:test {:extra-paths [] 4 | :extra-deps {}}}} 5 | -------------------------------------------------------------------------------- /components/util/src/org/corfield/util/colorizer.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.util.colorizer 2 | "Copied from Polylith so the subprocess can have basic colorization. 3 | 4 | https://github.com/polyfy/polylith/blob/master/components/util/src/polylith/clj/core/util/colorizer.clj" 5 | (:require [clojure.string :as str])) 6 | 7 | (def color-reset "\u001B[0m") 8 | (def color-black "\u001B[30m") 9 | (def color-cyan "\u001B[36m") 10 | (def color-blue "\u001B[34m") 11 | (def color-green "\u001B[32m") 12 | (def color-grey-light "\u001B[37m") 13 | (def color-grey-dark "\u001b[90m") 14 | (def color-purple "\u001B[35m") 15 | (def color-red "\u001B[31m") 16 | (def color-white "\u001B[37m") 17 | (def color-yellow "\u001B[33m") 18 | 19 | (defn- color [color messages] 20 | (str color (str/join "" messages) color-reset)) 21 | 22 | (defn colored-text 23 | ([color color-mode messages] 24 | (colored-text color color color-mode messages)) 25 | ([color-light color-dark color-mode messages] 26 | (case color-mode 27 | "none" (str/join "" messages) 28 | "light" (color color-dark messages) 29 | "dark" (color color-light messages) 30 | (throw (Exception. (str "Invalid color mode '" color-mode "' for messages '" messages "', expected: 'none', 'light' or 'dark'")))))) 31 | 32 | (defn- clean-color [message color] 33 | (str/replace message color "")) 34 | 35 | (defn clean-colors [message] 36 | (when message 37 | (reduce clean-color message [color-reset color-black, color-cyan, color-blue 38 | color-green color-grey-light color-grey-dark 39 | color-purple color-red color-white color-yellow]))) 40 | 41 | (defn blue [color-mode messages] 42 | (colored-text color-blue color-mode messages)) 43 | 44 | (defn cyan [color-mode messages] 45 | (colored-text color-cyan color-mode messages)) 46 | 47 | (defn green [color-mode messages] 48 | (colored-text color-green color-mode messages)) 49 | 50 | (defn grey [color-mode messages] 51 | (colored-text color-grey-light 52 | color-grey-dark 53 | color-mode messages)) 54 | 55 | (defn purple [color-mode messages] 56 | (colored-text color-purple color-mode messages)) 57 | 58 | (defn red [color-mode messages] 59 | (colored-text color-red color-mode messages)) 60 | 61 | (defn yellow [color-mode messages] 62 | (colored-text color-yellow color-mode messages)) 63 | 64 | (defn ok [color-mode messages] 65 | (colored-text color-green color-mode messages)) 66 | 67 | (defn warning [color-mode messages] 68 | (colored-text color-yellow color-mode messages)) 69 | 70 | (defn error [color-mode messages] 71 | (colored-text color-red color-mode messages)) 72 | 73 | (defn interface [name color-mode] 74 | (yellow color-mode name)) 75 | 76 | (defn component [name color-mode] 77 | (green color-mode name)) 78 | 79 | (defn base [name color-mode] 80 | (blue color-mode name)) 81 | 82 | (defn project [name color-mode] 83 | (purple color-mode name)) 84 | 85 | (defn entity [type name color-mode] 86 | (case (keyword type) 87 | :interface (interface name color-mode) 88 | :component (component name color-mode) 89 | :base (base name color-mode) 90 | :project (project name color-mode) 91 | name)) 92 | 93 | (defn brick [type brick color-mode] 94 | (entity type brick color-mode)) 95 | 96 | (defn profile [name color-mode] 97 | (purple color-mode name)) 98 | 99 | (defn library [name color-mode] 100 | (grey color-mode name)) 101 | 102 | (defn namespc 103 | ([name color-mode] 104 | (grey color-mode name)) 105 | ([interface namespace color-mode] 106 | (grey color-mode (str interface "." namespace)))) 107 | 108 | (def entities->type {"projects" "project" 109 | "bases" "base" 110 | "components" "component"}) 111 | 112 | (defn path [path color-mode] 113 | (let [strings (str/split path #"/") 114 | [entities name] strings 115 | type (entities->type entities) 116 | src (str/join "/" (drop 2 strings))] 117 | (str entities "/" (entity type name color-mode) "/" src))) 118 | -------------------------------------------------------------------------------- /components/util/src/org/corfield/util/interface/color.clj: -------------------------------------------------------------------------------- 1 | (ns org.corfield.util.interface.color 2 | "Copied from Polylith so the subprocess can have basic colorization. 3 | 4 | https://github.com/polyfy/polylith/blob/master/components/util/src/polylith/clj/core/util/interface/color.clj" 5 | (:require [org.corfield.util.colorizer :as colorizer])) 6 | 7 | (def none "none") 8 | 9 | (defn clean-colors [message] 10 | (colorizer/clean-colors message)) 11 | 12 | (defn blue [color-mode & messages] 13 | (colorizer/blue color-mode messages)) 14 | 15 | (defn cyan [color-mode & messages] 16 | (colorizer/cyan color-mode messages)) 17 | 18 | (defn green [color-mode & messages] 19 | (colorizer/green color-mode messages)) 20 | 21 | (defn grey [color-mode & messages] 22 | (colorizer/grey color-mode messages)) 23 | 24 | (defn purple [color-mode & messages] 25 | (colorizer/purple color-mode messages)) 26 | 27 | (defn red [color-mode & messages] 28 | (colorizer/red color-mode messages)) 29 | 30 | (defn yellow [color-mode & messages] 31 | (colorizer/yellow color-mode messages)) 32 | 33 | (defn ok [color-mode & messages] 34 | (colorizer/ok color-mode messages)) 35 | 36 | (defn warning [color-mode & messages] 37 | (colorizer/warning color-mode messages)) 38 | 39 | (defn error [color-mode & messages] 40 | (colorizer/error color-mode messages)) 41 | 42 | (defn entity [type name color-mode] 43 | (colorizer/entity type name color-mode)) 44 | 45 | (defn brick [type name color-mode] 46 | (colorizer/brick type name color-mode)) 47 | 48 | (defn interface [name color-mode] 49 | (colorizer/interface name color-mode)) 50 | 51 | (defn component [name color-mode] 52 | (colorizer/component name color-mode)) 53 | 54 | (defn base [name color-mode] 55 | (colorizer/base name color-mode)) 56 | 57 | (defn project [name color-mode] 58 | (colorizer/project name color-mode)) 59 | 60 | (defn path [path color-mode] 61 | (colorizer/path path color-mode)) 62 | 63 | (defn profile [name color-mode] 64 | (colorizer/profile name color-mode)) 65 | 66 | (defn library [name color-mode] 67 | (colorizer/library name color-mode)) 68 | 69 | (defn namespc 70 | ([name color-mode] 71 | (colorizer/namespc name color-mode)) 72 | ([interface namespace color-mode] 73 | (colorizer/namespc interface namespace color-mode))) 74 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:aliases 2 | {:dev {:extra-paths ["development/src"] 3 | :extra-deps {polylith-external-test-runner.bases/external-test-runner-cli {:local/root "bases/external-test-runner-cli"} 4 | polylith-external-test-runner.components/external-test-runner {:local/root "components/external-test-runner"} 5 | polylith-external-test-runner.components/util {:local/root "components/util"} 6 | org.clojure/clojure {:mvn/version "1.11.4"}}} 7 | :test {:extra-paths [] 8 | :extra-deps {polylith/clj-poly {:mvn/version "0.2.22-SNAPSHOT"} 9 | #_ 10 | {:git/url "https://github.com/polyfy/polylith.git" 11 | :sha "345af4992b5ec97b712cd5b1a2a06f731cdfd61d" 12 | :deps/root "projects/poly"}}} 13 | :example-opts [:sub-opts "-Dexample=opts" :nested-opts] 14 | :sub-opts ["-Dsub.example=more.opts"] 15 | :nested-opts {:jvm-opts ["-Dnested.example=even.more.opts"]} 16 | :poly {:extra-deps {polylith/clj-poly {:mvn/version "0.2.22-SNAPSHOT"} 17 | #_ 18 | {:git/url "https://github.com/polyfy/polylith.git" 19 | :sha "345af4992b5ec97b712cd5b1a2a06f731cdfd61d" 20 | :deps/root "projects/poly"} 21 | io.github.seancorfield/polylith-external-test-runner 22 | {:local/root "projects/runner"}} 23 | :jvm-opts ["-Dpoly.test.jvm.opts=:example-opts"] 24 | :main-opts ["-m" "polylith.clj.core.poly-cli.core"]}}} 25 | -------------------------------------------------------------------------------- /development/config.edn: -------------------------------------------------------------------------------- 1 | {:alias "dev" 2 | :test 3 | {:create-test-runner 4 | [org.corfield.external-test-runner.interface/create]}} 5 | -------------------------------------------------------------------------------- /development/src/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seancorfield/polylith-external-test-runner/c97747aa2b1fdf03c46c7e435cca7c2608740a2a/development/src/.keep -------------------------------------------------------------------------------- /projects/runner/config.edn: -------------------------------------------------------------------------------- 1 | {:alias "r" 2 | :test 3 | {:create-test-runner 4 | [org.corfield.external-test-runner.interface/create]}} 5 | -------------------------------------------------------------------------------- /projects/runner/deps.edn: -------------------------------------------------------------------------------- 1 | {:deps {org.clojure/clojure {:mvn/version "1.11.4"} 2 | 3 | polylith-external-test-runner.bases/external-test-runner-cli {:local/root "../../bases/external-test-runner-cli"} 4 | polylith-external-test-runner.components/external-test-runner {:local/root "../../components/external-test-runner"} 5 | polylith-external-test-runner.components/util {:local/root "../../components/util"}} 6 | 7 | :aliases {:test {:extra-paths [] 8 | :extra-deps {polylith/clj-poly {:mvn/version "0.2.21"}}}}} 9 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for config in source dev dummy 4 | do 5 | clojure -M:poly test :all with:$config 6 | if test $? -ne 0 7 | then 8 | echo "Tests failed with :$config" 9 | exit 1 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /workspace.edn: -------------------------------------------------------------------------------- 1 | {:vcs {:name "git" 2 | :auto-add false} 3 | :top-namespace "org.corfield" 4 | :interface-ns "interface" 5 | :dialects #{"clj" "cljs"} 6 | :default-profile-name "default" 7 | :compact-views #{} 8 | :tag-patterns {:stable "stable-*" 9 | :release "v[0-9]*"} 10 | 11 | :test {:create-test-runner [org.corfield.external-test-runner.interface/create]} 12 | 13 | :test-configs 14 | {:source ; without integration 15 | {:org.corfield/external-test-runner {:include-src-dir true 16 | :focus {:exclude [:integration]}}} 17 | :dev 18 | {:org.corfield/external-test-runner {:focus {:include [:dev]}}} 19 | :dummy 20 | {:org.corfield/external-test-runner 21 | {:focus {:var [org.corfield.external-test-runner.core-test/dummy-test 22 | org.corfield.external-test-runner.interface-test/dummy-test 23 | ignore/me]}}}} 24 | 25 | :projects {"runner" {:alias "r" 26 | ;; must override this with :source and/or :dev 27 | :test {:org.corfield/external-test-runner 28 | {:focus {:include [:none]}}}} 29 | "development" {:alias "dev"}}} 30 | --------------------------------------------------------------------------------