This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-14
Channels
- # admin-announcements (2)
- # beginners (32)
- # boot (217)
- # cider (20)
- # cljsjs (25)
- # cljsrn (9)
- # clojure (87)
- # clojure-android (7)
- # clojure-austin (4)
- # clojure-belgium (10)
- # clojure-canada (13)
- # clojure-dev (28)
- # clojure-dusseldorf (2)
- # clojure-greece (119)
- # clojure-nl (1)
- # clojure-russia (22)
- # clojure-spain (3)
- # clojure-spec (81)
- # clojure-uk (54)
- # clojurescript (32)
- # community-development (2)
- # core-async (19)
- # cursive (18)
- # datascript (5)
- # datomic (1)
- # dirac (22)
- # emacs (22)
- # hoplon (198)
- # incanter (1)
- # instaparse (4)
- # jobs (3)
- # keechma (15)
- # ldnclj (2)
- # lein-figwheel (14)
- # mount (8)
- # om (78)
- # om-next (4)
- # onyx (37)
- # other-languages (1)
- # pedestal (6)
- # re-frame (22)
- # reagent (25)
- # ring-swagger (17)
- # robots (1)
- # slack-help (1)
- # spacemacs (7)
- # specter (50)
- # spirituality-ethics (3)
- # uncomplicate (5)
- # untangled (1)
- # yada (17)
It’s too bad (s/describe (s/spec #(< % 3)))
has to return something that doesn’t quite look like an anonymous function literal
I’m not sure what to make of the fact that
(s/def ::a (s/and #(> % 2) #(< % 5)))
(s/def ::b #(and (> % 2) (< % 5)))
look the same. Perhaps it is OK because they behave the same way.hi guys, how do we use variable inside of (s/def (s/keys))
like this
(def a [::first-name])
(s/def ::user (s/keys :req a))
It's a value in a macro in a macro. And I'm no macro master ...I have an error while trying to generate from clojure.spec, I think this would be the try out such-that limitation in clojure.spec implementation.
(defn str-limit [lower upper] (s/and string? #(<= lower (count %) upper)))
(s/def :project/description (us/str-limit 116 1000)) ;; the gen doesn't work if the lower value is around above 100
(s/def ::project-gen (s/keys :req [:project/description]))
(gen/generate (s/gen ::project-gen))
;; -- error
ExceptionInfo Couldn't satisfy such-that predicate after 100 tries. clojure.core/ex-info (core.clj:4703)
@nxqd: This is because string?
generates totally random strings and then checks the second predicate to see if they conform, and gives up after 100 tries. Consider wrapping the spec with s/with-gen
and providing your own generator.
@stathissideris: thanks !
hi guys, am playing with clojure spec and running into an un-expected behavior: (s/valid? #{nil "a" "b"} nil) ;; returns false when it should be true
@minimal yeah, I tried that and it works.. but it should return true when a set is used in specs too right?
If you are relying on the value returned from the set then it needs to be truthy to be valid
The not-found
value of a set is also nil so it is troublesome if you don’t expicitly check using contains?
.
i'm using sets in specs to define an enum of values with the possibility of nil.... so it looked like a convenient way. guess, I'll have to either use s/or nil? ...
or #(contains?)
or you can use a defualt value that isn’t nil. (#{} 1) => nil
(get #{} 1 :not-found) => :not-found
only because the contains?
behavior is right but when a set is used as a function call it's not.
Using set as a predicate is a convenience but you are relying on an implicit conversion to boolean based on the value in the set
either choice is surprising
to somebody
depending on whether you expect the set to be treated specially or to be treated like a predicate
the implicit conversion to boolean is being done by the internal clojure implementation..
@minimal: but I get it, it won't be considered a defect. so I'll just use a different way. thanks!
@mfikes from your question way back on describe - s/form is useful for distinguishing these
@skapoor: you could also wrap s/nilable around the set (s/nilable #{"a"})
@alexmiller: what’s the rationale behind instrument only checking :args?
shift in perspective - instrument is about checking invocations are correct, not verifying the function itself is correct. (this is similar to how only the :args are checked in macro fdefs). The check and test functions are for verifying functionality of the code.
@alexmiller: this seems to severely hamper spec’ing non-pure functions (i.e. things that are difficult/impossible to write generators for)
@bfabry: no, but that was not really the intention of instrument
, which is about verifying that callers of a function are calling it correctly. If you want to test the the behavior of your functions are in accordance with your specs, you should use the spec.test functions to test your functions.
@alexmiller: sure, and no doubt were we to use spec we would use the spec.test functions. but like @arohner mentioned not all functions are pure, and if I'm going to write all those specs then I might as well get some extra value from them for free by having them always be checked in lower environments where I do not care about performance
@arohner: there are still more things coming that will help with verifying aspects of non-pure functions
@alexmiller: one nice feature of schema is that you can choose to use validation at e.g. user-input boundaries, in production. Instrument seems more designed for dev-time atm
@arohner spec does not remove the need to write tests for your functions. those tests can use invoke specs to validate as appropriate
@arohner: instrument is only designed for dev time
you should not instrument in production
you can choose to explicitly conform with spec at boundaries if you like
there will be a conform-ex
that validates or throws if not, not quite in yet
if I explicitly conform, then it will happen in production, when I only want it in staging. it also adds a whole bunch of boilerplate to every single function. I don't really understand the reasoning here, being able to reuse the :ret and :fn specs for extra checking when performance isn't a consideration just seems like an obvious win. and I mean, I definitely can still do that, writing my own macro that wraps all functions or whatever, but it sounds like I won't be the only one
there is an assertion facility still coming as well
the point is that checking ret/fn every time should be redundant to what you have (presumably) already confirmed in testing - that your function works.
I'm maybe a bit skeptical that adding generative testing (while definitely awesome) is going to straight away mean I stop writing functions that produce unexpected outputs when they encounter production data. and I'm a big fan of fail fast with a good error message when that does happen
you (will be) able to assert that return (if instrumented at dev time) or choose to explicitly validate it at production time if you want
it's unclear to me if you're talking about dev or prod
fair enough - so you can turn on instrumentation in staging
that will check args on functions
on my laptop/travis I run unit and generative tests, in master/staging the application runs "production-like" but with assertions turned on for :args :ret :fn, production the app runs with no assertions <-- this is my ideal scenario
there will be an assertion facility that you can use to (explictly) check ret/fn for instrumented functions
As the channel is a little bit louder this evening, I thought I'd pose a question I asked yesterday again:
What is the intended usage of :fn
in fdef
- In the docs it says something like 'relationships between args and the return'. Is the idea here to restrict it to type-y properties (e.g arity 1 of map returning a transducer rather than a seq)?
The reason I ask is it's possible to define many more general properties of functions as part of the spec. As spec gets richer I imagine it may be possible to auto-generate the code for many properties (idempotency is easy if you have spec'd the args)
I think what I'm talking about is close to that, but varies in that ret/fn are not automatically checked but require an explicit assert (which is not active in production)
right. and so I'll probably end up writing a macro that wraps every function to add that explicit assert, and I've got a feeling that a whole lot of people will do that. we use plumatic/schema atm which checks arg/return values when validation is turned on, and I'd say the same number of bugs are caught by the return value checking as the arg value checking. aaaanyway, writing the macro is nbd, and maybe it'll turn out I don't actually need it or I'm the only person who does 🙂
one question I have is whether you're getting the same level of generative testing from schema that you can get from spec (that is, whether more of those bugs could/should have been caught earlier)
also keep in mind that the return value often is an input to another function, which can check its args
no, we're definitely not. but like I said I'm just a bit skeptical that generative testing will suddenly mean these issues disappear, and it costs me like an extra $5 per month to run extra validation in the staging environment so why not? the return value will likely be the input value to another function, but maybe that function doesn't have a spec yet, because we didn't feel it was worth the time to write yet, or maybe it's too broadly defined etc. If I believed I could perfectly specify every function up front so that bugs were impossible I'd be writing haskell 😆
maybe you should just write your code without the bugs?
hey people, does anyone here found/created a generator for cljs to create strings from regexps? I was hoping to use the string-from-regexp
from test.chuck
but I just realised it's implementation is for CLJ only
I would ask @gfredericks
thanks Alex, I opened an issue on test.chuck
, he will see it I think 🙂
one more thing, given I have my fdef
all spec set, I remember seeing a simple command to test that function but I'm not finding it, what's the simplest way to run generative specs on a function?
clojure.spec.test/check-var
@alexmiller: thanks, would you consider adding that to the clojure spec guide?
yeah, that's on the todo list - I was actually working on some alpha6 related updates right now
nice 🙂
If I have understood correctly, the registry doesn’t have any tools for handling duplicate definitions?
@ikitommi: yeah just replaces https://github.com/clojure/clojure/blob/master/src/clj/clojure/spec.clj#L261
Is this good? should the specs be immutable by default? If there are name clashes, depending on the import order of namespaces, the specs might mean different thing.
@ikitommi: this is the reason they are encouraging namespaced keywords I think, do you have a situation where the same namespace is loaded on multiple files?
does anyone have examples of using fdef
and check-var
? I'm having trouble getting it to work in my test suite
@wilkerlucio: true that - the specs must have a namespace, but it doesn’t have to be a clojure namespace. One might have multiple :order/id
s in a large system. Should not, but could.
@bsima: check this snippet, may help you:
@ikitommi: that's some sort of thinking shift, moving from those to fully qualified, there are going to be some nice helpers to deal with longer namespaces in 1.9
yes, the problem exists like you said, but it's the same for def
as mentioned by @bfabry, I guess it's just about people starting moving towards fully qualified namespaces to avoid name clashes, I believe when it's the norm will be very positive for everyone