Search code examples
testingclojureclojurescript

tests inside function calls or for statements in clojure not running


I wrote code that looks something like this

(testing "check that for all these roles there's an alert"
    (binding [*profile* account-exceeded-limits]
      (let [overview-page (overview-container sample-form
                                              :role readonly-no-download)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))
      (let [overview-page (overview-container sample-form
                                              :role dataentry)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))
      (let [overview-page (overview-container sample-form
                                              :role editor)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))
      (let [overview-page (overview-container sample-form
                                              :role member)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))
      (let [overview-page (overview-container sample-form
                                              :role collaborator)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))
      (let [overview-page (overview-container sample-form
                                              :role readonly)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))))

I need to refactor this code to make it drier.

So I tried this

(testing "check that for all these roles theres an alert"
    (for [role [dataentry readonly-no-download editor member collaborator
             readonly]]
      (let [overview-page (overview-container sample-form
                                              :role role)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning")))))

It seemed that tests were not ran.

I also tried this:

(testing "check that for all these roles theres an alert"
(map (fn [role]  (let [overview-page (overview-container sample-form
                                              :role role)]
        (is (dommy/has-class?
             (-> overview-page (sel1 [:div#export-list-panel :.panel-body
                                      :.alert]))
             "alert-warning"))) [dataentry readonly-no-download editor member collaborator
             readonly])))

again, it still seemed that tests were not ran.

What could be causing this? is there a way I can make this test dryer? should I be trying to make tests dryer?


Solution

  • In Clojure, the for and map functions are both lazy, and won't run until you do something with the output.

    Since you don't care about the output, you should convert the for into a doseq, which always runs right away (non-lazy) and is intended for side-effects like you want here.

    Be sure to also bookmark the Clojure CheatSheet and always keep it open in a browser tab!

    There are also many other great resources listed here.


    Appendix:

    A very useful cousin to map is mapv. It is nothing more than (vec (map ...)), which forces the output of map into a (non-lazy) vector. I had been using Clojure for quite a while before I first heard about it.

    You can similarly get a non-lazy version of for by using (vec (for ...)). It runs immediately like doseq, but also returns the result sequence (instead of just nil). You can see more details here.