malli

Eric Dvorsak 2024-11-01T10:42:12.901799Z

Is there a simple flow to run generative testing on a function defined with mx/defn? mi/check can only run it for all instrumented functions

Eric Dvorsak 2024-11-01T11:12:26.901779Z

Unless I am missing something, there is no way to get the schema of a function defined with mx/defn as the schema is registered as a side effect?

escherize 2024-11-01T18:50:29.277219Z

we have our own malli/defn at metabase that I wrote some code to do that with

escherize 2024-11-01T18:50:42.238519Z

it is all open source, let me find the gist with the generative testing stuff

escherize 2024-11-01T19:02:34.887819Z

then calling it:

(mu/defn square :- :int
  [x :- [:int {:min 0 :max 100}]]
  (if (= x 3) "woops, 3 doesn't work" (* x x)))

(check-fn #'square)
returns
{:total-nodes-visited 2,
 :depth 0,
 :pass? false,
 :result "Invalid output: [\"should be an integer, got: \\\"woops, 3 doesn't work\\\"\"]",
 :time-shrinking-ms 0,
 :smallest [(3)],
 :malli.core/result #error {
 :cause "Invalid output: [\"should be an integer, got: \\\"woops, 3 doesn't work\\\"\"]"
 :data {:type :metabase.util.malli.fn/invalid-output, :error {:schema :int, :value "woops, 3 doesn't work", :errors ({:path [], :in [], :schema :int, :value "woops, 3 doesn't work"})}, :humanized ["should be an integer, got: \"woops, 3 doesn't work\""], :schema :int, :value "woops, 3 doesn't work", :fn-name square}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "Invalid output: [\"should be an integer, got: \\\"woops, 3 doesn't work\\\"\"]"
   :data {:type :metabase.util.malli.fn/invalid-output, :error {:schema :int, :value "woops, 3 doesn't work", :errors ({:path [], :in [], :schema :int, :value "woops, 3 doesn't work"})}, :humanized ["should be an integer, got: \"woops, 3 doesn't work\""], :schema :int, :value "woops, 3 doesn't work", :fn-name square}
   :at [metabase.permissions.util_test$fn__186566$fn__186569 invoke "NO_SOURCE_FILE" 229]}]
 :trace }

Eric Dvorsak 2024-11-01T19:28:20.697909Z

Thanks for sharing! I wonder what the memory issue is with mx/defn, its a private slack convo? Maybe it has been fixed now? I ended up doing this:

;; using :malli/schema in metadata: instrumentation not reloaded when schema changes
;; using mx/defn: hard to access function schema
(defn get-schema-from-var [v]
  (let [m (meta v)]
    (get-in (m/function-schemas)
            [(symbol (str (:ns m)))
             (symbol (:name m))
             :schema])))

(defmacro check
  "Given a function, it will grab its schema from the registry of
  instrumented functions and run generative testing on it"
  [func]
  `(let [func# (meta (var ~func))
         ns# (:ns func#)
         schema# (get-in (m/function-schemas)
                               [(symbol (str ns#))
                                (symbol (:name func#))
                                :schema])]
     (assert schema# ~(str func " is not instrumented"))
     (tests
      ~(str "Generative testing of " func)
      (mg/check schema# ~func) := nil)))
so when I want a function to be tested with generative testing I do
(check my-function)

mloughlin 2024-11-01T21:15:21.195939Z

I'm trying to write a Malli spec to parse IRC commands for fun How can I express optional sequence items when it involves the sequence ending? I've tried a lot of things and can't seem to figure out how to make the end of sequence nil value validate e.g.

["ADMIN"] => valid
["ADMIN" "mike"] => also valid

mloughlin 2024-11-12T17:31:58.685159Z

Thanks!

2024-11-07T07:48:24.564899Z

Looks like this: [:cat [:= "ADMIN"] [:? [:= "mike"]]] Or I misunderstood what do you want

👍🏻 1