Fork me on GitHub
#boot
<
2015-12-19
>
seancorfield00:12:13

I’m very excited by this: Ran 1162 tests containing 1162 assertions in 35134 msecs <— That’s one of the World Singles suites of Expectations, run via Boot instead of Leiningen.

micha00:12:56

what elapsed time is normal for that suite?

seancorfield00:12:36

with Leiningen? About 65000ms

micha00:12:51

oh wow, that's great

seancorfield00:12:22

Well, 65s on the first run and 37-45s on the second run.

micha00:12:46

it would be interesting to run your tests in incremental mode

micha00:12:52

boot watch test

micha00:12:33

do you do AOT for the tests?

seancorfield00:12:09

We AOT one namespace only. We specify that with :aot in project.clj (what’s the equivalent in Boot?)

micha00:12:27

there is an aot task

micha00:12:32

which you can add to the pipeline

micha00:12:40

boot aot -n foo.bar test

micha00:12:28

or (boot (aot :namespace #{'foo.bar}) (test))

micha00:12:31

in the repl

seancorfield00:12:10

@micha: Thanks. That works. I just need to remember to compose all these things simple_smile

seancorfield00:12:35

So my build.boot file requires boot-expectations and I have a testing task to set up the test dependencies etc, and boot testing expectations works as expected, and I can also do boot testing repl and get a REPL where (boot (expectations)) runs the suite as expected...

seancorfield00:12:55

…however, in that REPL (doc expectations) returns nil (without printing anything)

seancorfield00:12:25

Even tho’ boot expectations -h from the command line does show the docstring.

micha00:12:28

can you paste the build.boot of the project where you're running boot repl from?

seancorfield00:12:51

No, it includes all sorts of World Singles stuff.

micha00:12:51

what happens if you do (meta #'expectations) in the repl?

micha00:12:02

do you see the docstrings in there?

seancorfield00:12:36

Ah, if it helps, (doc expectations) works in bare boot repl but not in boot testing repl

seancorfield00:12:53

This is the testing task (nothing proprietary in it:

(deftask testing
  "Provide testing execution context."
  []
  (with-pass-thru fs
    (set-env! :source-paths #{"test"}
              :dependencies #(into % '[[expectations "2.1.3" :scope "test"]
                                       [javax.servlet/servlet-api "2.5" :scope "test"]
                                       [org.clojure/test.check "0.8.2" :scope "test"]]))
    (require '[expectations :as e])
    (let [disable-run-on-shutdown (resolve 'e/disable-run-on-shutdown)]
      (disable-run-on-shutdown))))

micha01:12:04

hm interesting

seancorfield01:12:30

Here’s the meta output:

{:boot.core/task true, :line 15, :column 1, :file "seancorfield/boot_expectations.clj", :name expectations, :ns #object[clojure.lang.Namespace 0x529f2fa5 "seancorfield.boot-expectations"], :doc "Run Expectations test in a pod.\n  \n  There are no options for this task at present.\n  \n  Keyword Args:\n    :help  bool  Print this help info.", :arglists ([& {:as *opts*, :keys [help]}]), :argspec [[:short-opt "-h" :id :help :long-opt "--help" :required nil :desc "Print this help info." :parse-fn #object[boot.cli$parse_fn$fn__86 0x2a41290c "boot.cli$parse_fn$fn__86@2a41290c"] :assoc-fn #object[boot.cli$assoc_fn$fn__96 0x35bf5269 "boot.cli$assoc_fn$fn__96@35bf5269"]]]}

micha01:12:30

i don't see anything in there that looks like it would affect the docs

micha01:12:51

:doc is in there

micha01:12:04

ah maybe it's some interaction with the repl

micha01:12:00

i wonder if this is an obscure bug in nrepl or clojure.repl maybe

seancorfield01:12:18

So here’s another question… Since cider-jack-in seems to want to do boot repl, is there a way to override the behavior of the repl task so it sets some special stuff up?

micha01:12:08

sure, you can (let [orig-repl repl] (deftask repl ...

micha01:12:21

then you can call orig-repl in your task

seancorfield01:12:27

Hahaha… OK… Sneaky!

micha01:12:46

you can use all the programming tricks now

micha01:12:15

you can also do alter-var-root if you want

micha01:12:24

might be cleaner that way

seancorfield01:12:35

The let trick doesn’t work… I get clojure.lang.ExceptionInfo: repl already refers to: #'boot.task.built-in/repl in namespace: boot.user so I assume I need an ns-unmap as well?

micha01:12:55

ah right yeah

micha01:12:13

also tasks have a special binding, *opts*

micha01:12:19

like for example:

micha01:12:08

(deftask foo
  [a asdf bool "Enable asdf behavior."]
  (with-pass-thru [_]
    (prn *opts*)))

micha01:12:25

if you do boot foo -a you will see {:asdf true}

micha01:12:57

you'll probably be able to use that with clojure.core/apply if you choose to wrap the repl task

seancorfield01:12:25

Hmm, I can’t seem to unmap that symbol...

seancorfield01:12:23

Listing out publics, interns, and aliases and I don’t see repl in any of those...

micha01:12:08

hm, it's referred into the boot.user namespace

seancorfield01:12:40

Yeah, found it in ns-refers...

micha01:12:24

maybe like (ns-unmap (the-ns 'boot.user) 'repl) or something?

micha01:12:35

maybe it's not picking up the right ns?

seancorfield01:12:29

Nope. I still get that error.

seancorfield01:12:52

Maybe alter-var-root is the right approach at this point simple_smile

micha01:12:57

strange, i've used the ns-unmap trick before

micha01:12:57

not with repl, no

seancorfield01:12:45

This finally did the trick:

(def orig-repl repl)
(deftask ws-repl
  "World Singles REPL task."
  []
  (System/setProperty "lein.profile.repl" "true")
  (orig-repl))
(alter-var-root #'repl (constantly ws-repl))

seancorfield01:12:22

I couldn’t get (apply orig-repl *opts*) to work.

micha01:12:04

right, you need to unroll the map into a seq of key/vals

micha01:12:22

(apply f (mapcat identity *opts*))

micha01:12:36

because f expects kwargs

micha01:12:43

which are like an unzipped map kind of

seancorfield01:12:24

But I need to specify all the same args to ws-repl that I would otherwise want to pass to repl, yes?

seancorfield01:12:55

As it is, boot ws-repl -s just starts a regular interactive REPL, not a server

micha01:12:09

ah right yes

seancorfield01:12:20

I think I’ll just give in and use customize-variable in Emacs

seancorfield02:12:43

If I have a task in BOOT_HOME/profile.boot and a redefinition of that task in {project}/build.boot, I assume that’s safe and reasonable?

seancorfield02:12:04

Ah, I get a warning it was overridden. That’s acceptable.

alandipert02:12:41

@seancorfield re: customizing repl, this is what i've done in that situation:

(alter-var-root #'repl
                (fn [old-repl]
                  (fn [& args]
                    ;; Do stuff here before running REPL
                    (apply old-repl args))))

alandipert02:12:21

oh wohops, sounds like you're doing that exactly already

seancorfield02:12:31

Yeah, it did not behave the way I expected (nor the way @micha expected either, it seems).

seancorfield02:12:12

I ended up following the CIDER REPL notes on the wiki and I’ll update my Emacs Live config to customize the setting...

seancorfield02:12:55

Is it possible to do multi-version testing with Boot? We normally test against Clojure master as well as a particular version.

seancorfield02:12:16

Seems like I’d have to run Boot twice and use the BOOT_CLOJURE_VERSION env var for that?

seancorfield02:12:13

Hmm, that won’t work unless the Sonatype repo is available to Boot directly since it can’t find the SNAPSHOT of Clojure to start itself up...

seancorfield02:12:58

It’s not a big deal but it was a nice to have simple_smile

micha03:12:48

@seancorfield you can use any version of clojure in your pod

micha03:12:12

just add the version you want to the pod dependencies

micha03:12:20

so you can make any number of loss pools and run your tests in parallel in all the pod with different versions of clojure

micha03:12:30

i mean pod pools

micha03:12:45

not loss pools, autocorrect

micha03:12:23

pods can have a different version of clojure than the main one

seancorfield03:12:20

OK, given boot-expectations already uses pods I’ll have to figure out how to pour in different versions of Clojure. Our test suite won’t actually run in parallel but that’s also an interesting option.

micha03:12:42

yeah you can run the testsn series too

seancorfield03:12:15

Given boot-expectations creates a pod from the current environment but adds expectations and tools.namespace dependencies, how would you recommend I deal with changing the Clojure dependency? Define an option on the task that lets you override the default Clojure version?

micha03:12:59

that sounds like a good way to do it

seancorfield03:12:13

(mapv (fn [[artifact version]] (if (= 'org.clojure/clojure artifact) [artifact new-version] [artifact version])) (core/get-env)) ; like so?

seancorfield03:12:33

Is it considered good practice to expose task dependencies? boot-expectations currently relies on expectations 2.1.3 but the user might want a different version — should I expose an option to alter that too?

micha03:12:57

ther eis a function you can use

seancorfield03:12:01

What happens if the user’s project env already has a tools.namespace dependency and I add a new one for my pod?

micha03:12:06

boot.pod/dependency-loaded?

micha03:12:16

so you can do like this:

micha03:12:30

`(defn pod-deps []

micha03:12:12

(defn pod-deps []
  (remove boot.pod/dependency-loaded? '[[foo "1.2.3"] ...]))

micha03:12:37

that dependency-loaded? function will return true if the dependency is already on the classpath

seancorfield03:12:49

Interesting… OK...

micha03:12:56

that could be true though if it's a transitive dependency

micha03:12:05

which you may or may not want in this case

micha03:12:32

like if the project has a dependency which in turn depends on foo

micha03:12:23

if the project already has a dependency on tools.namespace i think the first one wins

micha03:12:36

like the first one in the dependencies vector

seancorfield03:12:34

boot show -p is pretty impressive. It seems Selmer and Expectations don’t like each other much right now… simple_smile

seancorfield05:12:42

I think I’m in love with boot watch build

seancorfield05:12:59

…where build is (comp (pom) (jar) (install)).

seancorfield06:12:11

Uh-oh! My colleague(s) are here...

seancorfield06:12:07

boot-expectations 1.0.0 is available: https://clojars.org/seancorfield/boot-expectations — you can include/exclude namespaces via regex; you can specify the version of Clojure to use in your tests; you can see namespaces as they finish "expecting".

flyboarder06:12:50

how are expectations different from assertions?

seancorfield06:12:20

I find the syntax more natural and it suits BDD well...

seancorfield06:12:56

We use Expectations for the majority of our unit tests at World Singles.

seancorfield06:12:16

We only use clojure.test for our WebDriver tests since they’re side-effecty and assert-y.

seancorfield06:12:34

We even "expect" clojure.test.check results in some of our tests.

seancorfield07:12:59

https://www.refheap.com/112923 — Expectations using test.check

flyboarder07:12:48

reads and learns

flyboarder07:12:04

and reads more

flyboarder07:12:17

seems much simpler to setup than clojure.test

seancorfield07:12:39

Assertions feel very "imperative" to me: do something, assert the current state, so something else, assert the new state.

seancorfield07:12:25

Expectations feel more "functional": expect this value/condition when you evaluate this expression.

flyboarder07:12:00

yeah i see what you mean, well thanks for the boot task, it will come in handy!!

nha12:12:43

When doing a plugin, how can I see what is in the fileset ? ex. I have :

(core/deftask my-task []
  (core/with-pre-wrap [fs]
    ;; how can I see what is in fs ?
    (util/info "Task files : " (seq (core/input-files fs)))
    fs))
But it prints no files : Task files :

martinklepsch12:12:15

@nha: the show task has a -f/--fileset(?) option

martinklepsch12:12:02

if there are no files printed with your snippet there simply are no input files (could that be?)

martinklepsch12:12:26

@nha: what you can also do is just inspect the fileset as a record. e.g. (-> fs :tree keys) will give you a list of paths of files in the fs

nha12:12:47

Ah interesting, thanks simple_smile

martinklepsch12:12:19

the values of the map in :tree are the corresponding TmpFile records then

nha12:12:13

I tried (keys fs) but it failed to print also, did not know about :tree. That should get me started simple_smile

martinklepsch12:12:39

@nha: are you on 2.5.0 btw?

nha12:12:32

Boot App Version: 2.3.0
Boot Lib Version: 2.3.0
Clojure Version:  1.7.0
Time to upgrade it seems

martinklepsch12:12:58

I think the (with-pre-wrap [fs] ...) style is new with 2.5.0

nha12:12:19

oops sorry

martinklepsch12:12:23

before it was just (with-pre-wrap fs ...) so that might be why it's not properly printing anything

nha12:12:24

right. I was also missing the boot.properties file.

nha12:12:57

unless it is not needed for plugins ?

martinklepsch12:12:04

@nha: it's not required but can be used to pin boot on a per project basis

nha12:12:45

@martinklepsch: Thanks for your help simple_smile

martinklepsch12:12:24

@nha: you're welcome simple_smile

robin15:12:26

Hi people I'm getting this error

Load failed: Jsloader error (code #0): Error while loading script /cloject.out/cloject/main.js?zx=2fluunlj7n0y

robin15:12:58

My build.boot starts with:

(set-env!
  :target-path "static"
  :source-paths #{"src"}

robin15:12:42

and in src/cloject.cljs.edn it contains:

{:require [cloject.main]
 :compiler-options {:asset-path "/static/cloject.out"}}

robin15:12:59

Oh and the error occurs, on reload when I save the file

robin15:12:23

the path should be /static/cloject.out/cloject/main.js instead of what's in the error message.

danielsz18:12:51

Did anyone notice that M-x . in cider on a boot project now takes you to point in the filesystem and not in the fileset like it used to?

alandipert20:12:00

@micha: what's the best way to make an empty fileset?

micha20:12:33

do you have a fileset already?

micha20:12:47

you can do (assoc fs :tree {})

alandipert20:12:51

the purpose would be to start making tests for the builtin tasks

micha20:12:07

you really need to start with one that is already set up

micha20:12:23

cause of all the directories it needs

micha20:12:55

will boot core be loaded?

micha20:12:33

there is the boot.core/new-fileset function

micha20:12:46

but core needs to have been initialized

alandipert20:12:52

maybe the best way to drive the tests is with actual files on disk and the boot function

alandipert20:12:54

that would be the most realistic

alandipert20:12:25

i was just imagining that maybe it would be useful to be able to make a fileset in source code, to test little things like the sift flags

micha20:12:29

perhaps the tests could be in a boot task

micha20:12:48

then you can call core fns and stuff, and it will be all initialized correctly

alandipert20:12:05

that sounds good

micha20:12:19

if you never comit! the fileset then the directories aren't necessary