msg: { actual, expected ? { }, asString ? false, asJSON ? false , removeDunders ? false, safeToPrint ? true, throws ? false }: let preProcess = v: if removeDunders then undunder v else if asString then toString v else if asJSON then builtins.toJSON v else v; a = preProcess actual; e = preProcess expected; undunder = v: if builtins.isAttrs v then builtins.removeAttrs v [ "__toString" "__functor" ] else v; out = (if safeToPrint then builtins.toJSON (undunder (if throws then (builtins.tryEval actual).value else actual)) else ''{"msg": "refusing to print"}''); success = if throws then (builtins.tryEval actual).success == false else (a == e); in if success then '' echo 'it ${msg}' '' else builtins.trace "FAILED ${msg}" '' echo FAILED ${msg} echo '${out}' | jq '.' ''