This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-02
Channels
- # announcements (3)
- # aws (2)
- # babashka (60)
- # beginners (21)
- # cljs-dev (35)
- # cljsrn (3)
- # clojure (53)
- # clojure-android (2)
- # clojure-australia (3)
- # clojure-europe (45)
- # clojure-france (4)
- # clojure-nl (4)
- # clojure-uk (6)
- # clojurescript (33)
- # core-typed (1)
- # cursive (13)
- # datomic (6)
- # duct (1)
- # emacs (2)
- # fulcro (10)
- # introduce-yourself (3)
- # jobs (2)
- # jobs-discuss (13)
- # leiningen (1)
- # malli (19)
- # missionary (63)
- # music (1)
- # off-topic (21)
- # pathom (3)
- # polylith (18)
- # practicalli (12)
- # proletarian (1)
- # reagent (40)
- # reitit (23)
- # releases (1)
- # remote-jobs (1)
- # ring (14)
- # ring-swagger (1)
- # shadow-cljs (13)
- # sql (30)
- # testing (27)
- # tools-deps (31)
- # vim (10)
- # xtdb (4)
Hey guys, so I’m attempting to build a web server purely using Clojure libraries. Now there’s a twist. I’m doing it in a strictly test-driven, way. Now I want to write the simplest test I can to show that a server exists. Should I make a get request? Or something simpler?
Answering in two parts: 1. The most direct way I can think of to see if a server exists is to try and open up a socket to that port. 2. While it's an interesting exercise, I suspect your time will be better spent testing things farther up the stack. This is essentially testing the web server itself, which has probably already received a lot of attention by many people.
Now a follow up question. How should I configure my test suite to make sure my server is running on each test run. I’m probably gonna use httpkit, so would I just call run-server
from my test file?
If you really want end-to-end tests, then yes. use-fixtures
can help structure this code, if you feel it's repetetive: https://clojuredocs.org/clojure.test/use-fixtures. That said, it's common to structure clojure code such that most of the pieces are purely functional, and can be tested independent of any kind of fixture situation. For example, you'll probably have request handlers that are little more than a function. Most testing can be done on that function directly. Of course the integration tests should still exist, but people usually don't write as many of those.
Well thank you for your help, and thank you for introducing me to use-fixtures
!
That’s a really big help for me.
For basic smoke test I recommend adding a simple route like /status that would return pkain text “ok” on GET
If you do end up using fixtures, the following link might be helpful. https://stuartsierra.com/2016/05/19/fixtures-as-caches
question on the testing
macro. The docstring states:
> Adds a new string to the list of testing contexts. May be nested,
> but must occur inside a test function (deftest).
but a co-worker put it outside a group of deftest
s and said it works e.g.
(testing "desc"
(deftest "case1"
(testing "this tests x" ...))
(deftest "case2"
(testing "y holds as well" ...)))
I went looking at the source (in CLJS), and it doesn’t seem like it has to be in a deftest
since testing
updates the :testing-contexts
in the current-env (https://github.com/clojure/clojurescript/blob/r1.10.866/src/main/cljs/cljs/test.cljc#L216-L225)
Just trying to get an understanding if this is really safe or coincidentally safe; does anybody have experience with this?A deftest
inside a testing
seems quite weird. It can also complicate a little bit on async tests in ClojureScript, so I would recommend against it
Also, testing
updates the :testing-contexts
but inside a dynamic var. What it means, in practice, is the following (using your first example):
; Here, it'll update the testing context to ["desc"]
(testing "desc"
(deftest "case1"
; Here, it'll update the testing context to ["desc" "this texts x"]
(testing "this tests x"
...
) ; Here, it'll be back to ["desc"]
)
) ; And here, to []
As the testing-context is a global, dynamic var, this "binding-rebinding" will work *if* (and that's a big IF) ClojureScript loads the file AND run the tests at the same time. Most of the time, that's not the case, so what it'll happen is something like this:
; Here, it'll update the testing context to ["desc"]
(testing "desc"
(deftest case1 ; Here, it'll just define the var
(testing "this tests x" ... )
)
); Back to []
When it's time to run the test, your testing context is empty, so you won't see "desc this tests x". So, officially, the first testing
serves no purpose on this example.I think they just wrote that for reading context, and wrapping a let
that covers the deftest
with shared context
it was agreed to back it out, but it piqued my curiosity enough that I wanted to get a deeper understanding. 😉
Kinda, but the testing
description appears when a test fails also
For example:
user=> (deftest sum-numbers (testing "1+2" (testing "must be 3" (is (= 2 (+ 1 2))))))
#'user/sum-numbers
user=> (run-tests)
Testing user
FAIL in (sum-numbers) (NO_SOURCE_FILE:1)
1+2 must be 3
expected: (= 2 (+ 1 2))
actual: (not (= 2 3))
yeah, again I am not sure if they did that for extra description context, or more the idea of wrapping a let
block
I think they did, otherwise I see no value on adding that :testing-contexts
element
they were able to run it they said; but the docstring said inside deftest
only, so felt like it would be a loophole that might be able to be exploited, but didn’t feel like we should be counting on it…
If you look at git blame, it seems it was intentional
It's inside deftest
because otherwise the description will not be added to failures
https://github.com/clojure/clojurescript/blob/v1.10/src/main/cljs/cljs/test.cljs#L269-L275
looks like it expects that the *current-env*
dynvar is specified here
so it looks like it “works” if you’ve imported/required clojure.test
, but probably not otherwise
ah, thought you couldn’t find the definition, my apologies.
also new to production support Clojure/ClojureScript vs just doing personal abandonware to solve problems; so part of it is a question on how safe it it to depend on the implementation… I know Clojure is stable, wasn’t sure if this is one of those that is implementation stable, vs keep to the contract in the Docstrings, specs, etc. stable. 😉