# \[ANN\] SmartAsserts: A drop-in replacement for \`@assert\` that prints out additional information upon failure

**URL:** <https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821>\
**Category:** Package Announcements\
**Created:** [February 4, 2022, 8:59pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821 "2022-02-04T20:59:52Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 4, 2022, 8:59pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/1 "2022-02-04T20:59:52Z")

</div>

Hi all, I just published [SmartAsserts](https://github.com/MrVPlusOne/SmartAsserts.jl) to the general registry. It provides a convenient macro `@smart_assert` that automatically prints out argument values upon assertion failure (without re-evaluating the original expression) and can be used as a drop-in replacement for `@assert`. Unlike `@assert` , these smart assertions can also be easily turned off at compile-time. Hope you will find it useful!

An assertion failure example using `@smart_assert`:

```julia
julia> let a = 1.0, rtol=0.1
           @smart_assert isapprox(a, sin(a), atol=0.05; rtol)
       end
ERROR: AssertionError: Condition `isapprox(a, sin(a), atol = 0.05; rtol)` failed due to:
        `a` evaluates to 1.0
        `sin(a)` evaluates to 0.8414709848078965
        `0.05` evaluates to 0.05
        `rtol` evaluates to 0.1
Stacktrace:
 [1] top-level scope
   @ REPL[177]:2

```

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [February 4, 2022, 10:05pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/2 "2022-02-04T22:05:04Z")

</div>

One feature I’d like to have is to disable assertions in release mode, like in C. I know there are tricks to enable this, but it would be a nice built-in feature.

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 4, 2022, 10:24pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/4 "2022-02-04T22:24:57Z")

</div>

One easy way to implement this would be via an `enabled::Ref{Bool}` that is checked at run-time and skips the tests if set to false. However, there would still be a small amount of overhead due to this run-time check even if it’s set to false. Would this be sufficient for your common use cases?

Alternatively, to truly get rid of any run-time cost, I can add an `enabled` keyword argument to the macro, but the user will need to make sure it’s set to a compile-time constant.

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 4, 2022, 10:45pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/5 "2022-02-04T22:45:17Z")

</div>

Another solution that’s more similar to what you described would be using a constant `ENABLE_ASSERTS=false` defined inside module `M` to control whether to disenable all smart\_asserts inside `M`. This way, the package author can easily control whether to turn off all their smart\_asserts by setting the value of this constant inside their module (e.g., via environment variables using `const ENABLE_ASSERTS = ENV["ENABLE_ASSERTS"]`).

---

<div class="post-metadata">

**Author:** ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)\
**Post date:** [February 4, 2022, 11:29pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/6 "2022-02-04T23:29:38Z")

</div>

`@static if ` is evaluated at compile time, but I’m not sure how it can help in this case.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 4, 2022, 11:52pm UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/7 "2022-02-04T23:52:56Z")

</div>

```julia
@debug @assert

```

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 5, 2022, 12:45am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/8 "2022-02-05T00:45:36Z")

</div>

I think under the hood this one still relies on run-time level checks. The code generated by `@debug` contains the line `if std_level >= _min_enabled_level[] ...`.

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 5, 2022, 2:24am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/9 "2022-02-05T02:24:55Z")

</div>

Ok, I just released a patch to support [turning off the assertions at compile time](https://github.com/MrVPlusOne/SmartAsserts.jl#turning-off-the-assertions-at-compile-time).

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [February 5, 2022, 3:28am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/10 "2022-02-05T03:28:29Z")

</div>

> [@greatpet](#):
>
> One feature I’d like to have is to disable assertions in release mode, like in C. I know there are tricks to enable this, but it would be a nice built-in feature.

There is a PR to Base to do that for `@assert`, by the way: [RFC: implement proper debug mode for packages (with support for re-precompilation) by KristofferC · Pull Request #37874 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/37874)

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [February 5, 2022, 5:59am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/11 "2022-02-05T05:59:57Z")

</div>

There is also [ArgCheck.jl](https://github.com/jw3126/ArgCheck.jl):

```julia
julia> using ArgCheck

julia> a = 1.0; rtol = 0.1
0.1

julia> @check isapprox(a, sin(a), atol=0.05; rtol)
ERROR: CheckError: isapprox(a, sin(a), atol = 0.05; rtol) must hold. Got
rtol => 0.1
a => 1.0
sin(a) => 0.8414709848078965
Stacktrace:
 [1] top-level scope
   @ ~/.julia/packages/ArgCheck/5xEDR/src/checks.jl:243

```

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 5, 2022, 6:27am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/12 "2022-02-05T06:27:27Z")

</div>

Wow, I did not know it exists! Thanks for the info! Looks like ArgCheck’s `@check` does something very similar to my `@smart_assert`! Maybe I should merge my package into that one instead? Most of my code is very similar to theirs anyway…

---

<div class="post-metadata">

**Author:** ![MrVPlusOne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrvplusone/32/20400_2.png) [@MrVPlusOne](https://discourse.julialang.org/u/MrVPlusOne)\
**Post date:** [February 5, 2022, 6:53am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/13 "2022-02-05T06:53:00Z")

</div>

I noticed that in the result produced by `@check`, the stack trace seems to point to ArgCheck’s source location instead of the assertion’s. Also, the values of keyword arguments are printed out before the positional args. Would you consider these as issues that are worthwhile to fix? If so, I’d be happy to make a pull request (I have addressed these in `@smart_assert` and I think they should be easy to fix in ArgCheck as well).

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [February 5, 2022, 7:02am UTC](https://discourse.julialang.org/t/ann-smartasserts-a-drop-in-replacement-for-assert-that-prints-out-additional-information-upon-failure/75821/14 "2022-02-05T07:02:15Z")

</div>

Sure please go ahead and fix these!
