This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-19
Channels
- # aws (2)
- # babashka (4)
- # babashka-sci-dev (7)
- # beginners (92)
- # biff (7)
- # calva (64)
- # cider (2)
- # cljsrn (14)
- # clojure (8)
- # clojure-australia (5)
- # clojure-europe (14)
- # clojure-norway (8)
- # clojure-spec (36)
- # clojurescript (19)
- # component (15)
- # cursive (1)
- # data-science (6)
- # girouette (5)
- # hyperfiddle (3)
- # juxt (5)
- # leiningen (10)
- # lsp (7)
- # malli (12)
- # nbb (90)
- # polylith (1)
- # portal (11)
- # rdf (7)
- # reagent (6)
- # reitit (40)
- # remote-jobs (1)
- # shadow-cljs (21)
- # specter (5)
- # squint (83)
- # tools-deps (17)
- # vim (7)
(defn -main
[_]
(p/let [db-ok? (db-fixture/create-test-db)]
(when db-ok?
(-> (p/let [;; Run DB required tests. In order for simpler reporting
_ (upload-pre-selected-customer-test/run-tests)])
(p/finally
(fn [_ _]
(when db-ok?
(db-fixture/drop-test-db))))))))
(defn -main
[_]
(p/let [;; Run non-DB tests. In order for simpler reporting
p1 (p/promise 1)]
(when p1
(-> (p/let [;; Run DB required tests. In order for simpler reporting
tests1 (postgres-test/run-tests)]
(js/console.log "TESTS conclude" tests1))
(p/finally (fn [_ _]
(js/console.log "FINALLY Called Now")
(p/promise 1)))))))
(ns postgres-test
(:require
[cljs-bean.core :as cb]
[cljs.test :as t :refer [async deftest is testing]]
[postgres]
[promesa.core :as p]))
(deftest p1
(testing "p1"
(async done
(-> (p/let [p1 (p/promise 1)]
(js/console.log "p1")
(is (= 1 p1)))
(p/finally done)))))
(deftest p2
(testing "p2"
(async done
(-> (p/let [p1 (p/promise 1)]
(js/console.log "p2")
(is (= 1 p1)))
(p/finally done)))))
(defn run-tests
[]
(t/run-tests 'postgres-test))
I checked this with other tests and any time you have more than one deftest
using a promise the finally executes after the first promise is resolved
npx nbb --classpath src:test -m runner Testing postgres-test p1 TESTS conclude true p2 FINALLY Called Now Ran 2 tests containing 2 assertions. 0 failures, 0 errors.
When I run this:
(ns postgres
(:require
[cljs.test :as t :refer [async deftest is testing]]
[promesa.core :as p]))
(deftest p1
(testing "p1"
(async done
(-> (p/let [p1 (p/promise 1)]
(js/console.log "p1")
(is (= 1 p1)))
(p/finally done)))))
(deftest p2
(testing "p2"
(async done
(-> (p/let [p1 (p/promise 1)]
(js/console.log "p2")
(is (= 1 p1)))
(p/finally done)))))
(t/run-tests 'postgres)
I get:
$ nbb /tmp/postgres.cljs
Testing postgres
p1
p2
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
which looks good?If you want to provide a more complete repro, please make a github repo which I can clone locally so we're speaking about exactly the same thing
it would be easier for me to be able to clone it though, than to replicate the same setup by copy/pasting things from slack
npx nbb -m runner
Testing promise-test
p1
TESTS conclude true
p2
FINALLY Called Now
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
no harm here but bad things happen when p2 is not resolved reliably before the let bindings are completed
run-tests does not return a promise, so awaiting that doesn't really wait on anything
> >
To detect test
> completion add a :end-run-tests method case to the cljs.test/report
> multimethod.
> It would be pretty nice to have a promise-based test runner instead of the cljs.test one
(defmethod t/report [::t/default :end-run-tests]
[m]
(p/let [ok? (t/successful? m)]
(if ok?
(println "Tests passed!")
(println "FAIL"))))
What you're seeing is purely co-incidental, just add a _ (p/delay 1000)
in one of those tests and you'll see that it doesn't work with p/let
+ true
This works:
(def end-resolve (atom nil))
(def end-promise (js/Promise. (fn [resolve _reject]
(reset! end-resolve resolve))))
(defmethod t/report [:cljs.test/default :end-run-tests]
[m]
(let [ok? (t/successful? m)]
(if ok?
(println "Tests passed!")
(println "FAIL"))
(@end-resolve)))
(defn run-tests
[]
(t/run-tests 'promise-test)
end-promise)
So, in the multimethod you resolve the promise and in run-tests you return the promise that will be fulfilled
Blimey, I'm gonna need a minute 🤯 Thanks for digging into it. Like you say, dealing with this stuff is annoying compared to what a promise based library could offer.
actually I think the finally shit is me holding it wrong - I should use per ns fixtures instead
(ns runner
(:require
[promesa.core :as p]
[promise-second-test]
[promise-test]))
(defn -main
[_]
(-> (p/let [_ (promise-test/run-tests)
_ (promise-second-test/run-tests)]
(js/console.log "TESTS conclude"))
(p/finally (fn [_ _]
(js/console.log "Finally TESTS conclude")))))
it's more of a curiosity at this point cos the tests and fixtures all run and behave how I want
I'm seeing:
$ nbb -m runner
Testing promise-test
stand up promise-test
tear down promise-test
Tests passed!
Ran 3 tests containing 3 assertions.
0 failures, 0 errors.
Testing promise-second-test
stand up promise-second-test
tear down promise-second-test
Tests passed!
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
Can you explain what is unexpected?so what you're doing here is that a defmethod in the first ns overrides the defined method of the other ns
Yes, like I say it gets messy when you do more things. Usually you should be able to scope these things to the specific ns
the whole point of this is to run two test suites with promises and for them to conclude in an orderly manner
it's not so urgent in the sense that we have a workable test suite now but I feel like the silent console is trying to tell us something
This is probably because you're overriding one defmethod + dispatch with another one so one of the promises never gets fulfilled
If you want to have one promise per ns, you should resolve a namespace specific promise in the defmethod
If you like to run tests from different namespaces in order, you can just do:
(run-tests 'namespace-one 'namespace-two)
that test runner plus the fixtures .... everything just seems to work without the need for the promise resolving hack
I know I could do it but if you have a version that runs all the test nses .... would be nice
You probably know already but all of the promise hacks are not needed in that case
core.async isn't supported in nbb. the recommended approach is to use promises directly in combination with promesa.core
I recall there was an example out there of building a binary from a nbb script. If I remember right, the library for that started with a c
and is an alternative to something like nexe
. Anyone remember what it was?