nbb

ray 2022-08-19T10:53:12.431899Z

I am having some bizarre behaviour when trying to order test fixtures

ray 2022-08-19T10:54:28.393389Z

(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))))))))

ray 2022-08-19T10:55:07.465319Z

if I have one deftest in the upload-pre-selected-customer-test ns, it all works fine

ray 2022-08-19T10:55:19.745349Z

if I have two ... all hell breaks loose

ray 2022-08-19T10:55:58.312969Z

any ideas would be welcome cos I'm having a real head scratcher here

ray 2022-08-22T16:15:53.118779Z

(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)))))))

ray 2022-08-22T16:16:08.733859Z

replaced postgres tests with this

ray 2022-08-22T16:16:23.959849Z

(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))

ray 2022-08-22T16:17:41.193549Z

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

ray 2022-08-22T16:18:02.817229Z

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.

ray 2022-08-22T16:19:33.440649Z

p2 is called after tests conclude and then the finally and the p2 are in a race

ray 2022-08-22T16:20:00.675209Z

so big question for me ... am I holding it wrong?

borkdude 2022-08-22T16:22:14.396789Z

I'll try locally

borkdude 2022-08-22T16:25:06.352689Z

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?

borkdude 2022-08-22T16:25:42.886859Z

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

borkdude 2022-08-22T16:27:35.852669Z

sorry, I didn't notice you posted multiple files

borkdude 2022-08-22T16:27:52.922719Z

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

👍🏼 1
ray 2022-08-22T17:03:34.520339Z

I'll make a small repo

ray 2022-08-22T18:51:46.822419Z

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.

borkdude 2022-08-22T18:52:48.922839Z

That's what I'm seeing locally. What is unexpected?

ray 2022-08-22T18:52:56.811359Z

no harm here but bad things happen when p2 is not resolved reliably before the let bindings are completed

ray 2022-08-22T18:53:26.776979Z

should see p1, p2 ... then TESTS concude

ray 2022-08-22T18:54:08.140339Z

unless I am missing something about the p/let contract

borkdude 2022-08-22T18:54:15.323739Z

ah ok, now looking into it then

ray 2022-08-22T18:54:53.292939Z

thanks... I would love for it to be one of these

ray 2022-08-22T18:54:59.801359Z

facepalm

borkdude 2022-08-22T18:55:01.859649Z

run-tests does not return a promise, so awaiting that doesn't really wait on anything

borkdude 2022-08-22T18:56:04.605329Z

https://cljs.github.io/api/cljs.test/#run-tests

ray 2022-08-22T18:56:28.071859Z

(defn run-tests
  []
  (p/let [_ (t/run-tests 'promise-test)]
    true))

borkdude 2022-08-22T18:56:33.785589Z

> >

To detect test
> completion add a :end-run-tests method case to the cljs.test/report
> multimethod.
>

ray 2022-08-22T18:56:34.875379Z

does the job

borkdude 2022-08-22T18:57:12.835229Z

This returns true immediately, before the tests run (or somewhere in the middle)

ray 2022-08-22T18:57:19.416469Z

ha! ok, thanks ... I'll do that too

borkdude 2022-08-22T18:57:40.260429Z

It's indeed a facepalm but mostly because CLJS doesn't really embrace promises here

borkdude 2022-08-22T18:59:12.213659Z

You could solve this by resolving a promise inside that multimethod though

borkdude 2022-08-22T18:59:26.864379Z

It would be pretty nice to have a promise-based test runner instead of the cljs.test one

💯 1
ray 2022-08-22T18:59:32.137029Z

yes, that's what I'll do

ray 2022-08-22T19:00:13.854829Z

thanks for your help - totally excellent

❤️ 1
ray 2022-08-22T19:13:06.795599Z

funny

ray 2022-08-22T19:13:13.960069Z

(defn run-tests
  []
  (p/let [_ (t/run-tests 'promise-test)]
    true))

ray 2022-08-22T19:13:22.691359Z

reliably produces the correct results

ray 2022-08-22T19:13:40.537349Z

adding a promise to that multimethod has no effect

ray 2022-08-22T19:14:01.688689Z

(defmethod t/report [::t/default :end-run-tests]
  [m]
  (p/let [ok? (t/successful? m)]
    (if ok?
      (println "Tests passed!")
      (println "FAIL"))))

ray 2022-08-22T19:14:16.373059Z

no change in the chaos

borkdude 2022-08-22T19:16:22.676769Z

Do you see the println?

ray 2022-08-22T19:29:04.932339Z

Yes

ray 2022-08-22T19:30:18.194019Z

Does it work for you?

borkdude 2022-08-22T19:32:10.091569Z

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

👍🏼 1
borkdude 2022-08-22T19:36:45.152829Z

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)

borkdude 2022-08-22T19:37:57.375309Z

So, in the multimethod you resolve the promise and in run-tests you return the promise that will be fulfilled

🙏🏼 1
ray 2022-08-22T21:02:04.814109Z

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.

ray 2022-08-23T11:00:51.837389Z

It is a mess when there are two test nses with N deftests

ray 2022-08-23T11:02:37.588399Z

both the clause after the let bindings and the finally on the runner never executes

borkdude 2022-08-23T11:12:23.838909Z

Repro or it didn't happen. :)

ray 2022-08-23T11:24:04.944179Z

actually I think the finally shit is me holding it wrong - I should use per ns fixtures instead

ray 2022-08-23T11:59:13.457659Z

In this case we should be seeing some console output

ray 2022-08-23T11:59:19.746719Z

(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")))))

ray 2022-08-23T11:59:25.476019Z

but there is none

ray 2022-08-23T11:59:49.601639Z

it's more of a curiosity at this point cos the tests and fixtures all run and behave how I want

ray 2022-08-23T11:59:59.248239Z

I have pushed the updates

borkdude 2022-08-23T16:03:05.253109Z

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?

borkdude 2022-08-23T16:05:21.694349Z

oh yes, I see, the console logs from the runner

👍🏼 1
borkdude 2022-08-23T16:06:23.547719Z

when I remove #_#__ (promise-second-test/run-tests) I do see the output... hmm

borkdude 2022-08-23T16:08:31.902259Z

so what you're doing here is that a defmethod in the first ns overrides the defined method of the other ns

ray 2022-08-23T17:45:39.117239Z

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

ray 2022-08-23T17:46:11.218359Z

or maybe more to the point that's what I would like to be able to do

ray 2022-08-23T17:47:04.407779Z

the whole point of this is to run two test suites with promises and for them to conclude in an orderly manner

ray 2022-08-23T17:47:37.420159Z

otherwise the async is leaking

ray 2022-08-23T17:49:54.392329Z

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

borkdude 2022-08-23T18:17:53.019479Z

This is probably because you're overriding one defmethod + dispatch with another one so one of the promises never gets fulfilled

borkdude 2022-08-23T18:20:35.152729Z

If you want to have one promise per ns, you should resolve a namespace specific promise in the defmethod

🤷🏼‍♂️ 1
borkdude 2022-08-23T18:27:43.615759Z

If you like to run tests from different namespaces in order, you can just do:

(run-tests 'namespace-one 'namespace-two)

ray 2022-08-24T06:45:13.863139Z

I should just run all tests. I think this runner is overly complex

borkdude 2022-08-19T11:23:11.451539Z

More details or repro? Afk now but can check later when you have one

ray 2022-08-19T11:46:12.591669Z

will try to make a repro

ray 2022-08-25T13:24:45.138449Z

ha, the adjustments are falling over after I have three. 😿

ray 2022-08-25T13:27:14.298829Z

forget that ... just using run-tests after the various adjustments is working

ray 2022-08-25T15:19:53.754509Z

You probably know already but all of the promise hacks are not needed in that case

👍 1
ray 2022-08-24T10:23:29.767679Z

that test runner plus the fixtures .... everything just seems to work without the need for the promise resolving hack

👍 1
ray 2022-08-24T16:39:02.960639Z

I know I could do it but if you have a version that runs all the test nses .... would be nice

ray 2022-08-24T16:47:41.130069Z

not to worry, I've adjusted it

sirwobin 2022-08-19T12:54:44.729059Z

Is there a simple way to include core.async in nbb scripts?

borkdude 2022-08-19T12:55:14.100819Z

core.async isn't supported in nbb. the recommended approach is to use promises directly in combination with promesa.core

sirwobin 2022-08-19T12:55:33.486879Z

Righto, thank you.

2022-08-19T21:44:44.867029Z

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?

2022-08-19T21:45:57.736389Z

Thanks! Exactly what I was trying to remember. Was looking in the examples folder, should have also checked docs.

borkdude 2022-08-19T21:46:09.346719Z

no problem :)