Both require
and assert
are used to perform certain checks during runtime to verify certain conditions.
So what is the basic difference between them?
The only one I see is that require
throws IllegalArgumentException
and assert
throws AssertionError
.
How do I choose which one to use?
assert is a precondition in Scala that evaluates a boolean expression as true or false. It's generally used to validate the execution of the program during runtime. We can see assert is used commonly in testing the functionality of programs.
assert() macro is used to test the conditions or assumptions that should not occur in a program. For example, the array index should always be > 0. Another assumption can be 2+2 == 3+1. So using assert () we can test such assumptions and as long as they evaluate to true, our program runs normally.
That an “Assert” is used only for validations, where an “If” clause is used for the logic within our code. We can use an “If” clause to determine whether our automation should follow one path or another, but an “Assert” statement to validate the elements within those paths.
JUnit assertions are intended to be used in test code, but not in production code. Using JUnit assertions outside of test scope may be confusing.
As Kigyo mentioned there is a semantic difference
There is also a major technical difference:
assert
is annotated with @elidable(ASSERTION)
meaning you can compile your program with -Xelide-below ASSERTION
or with -Xdisable-assertions
and the compiler will not generate the bytecode for the assertions. This can significantly reduce bytecode size and improve performance if you have a large number of asserts.
Knowing this, you can use an assert
to verify all the invariants everywhere in your program (all the preconditions/postconditions for every single method/function calls) and not pay the price in production.
You would usually have the "test" build with all the assertions enabled, it would be slower as it would verify all the assertions at all times, then you could have the "production" build of your product without the assertions, which you would eliminate all the internal state checks done through assertion
require
is not elidable, it makes more sense for use in libraries (including internal libraries) to inform the caller of the preconditions to call a given method/function.
This is only my subjective point of view.
I use require
whenever I want a constraint on parameters.
As an example we can take the factorial for natural numbers. As we do not want to address negative numbers, we want to throw an IllegalArgumentException
.
I would use assert
, whenever you want to make sure some conditions (like invariants) are always true during execution. I see it as a way of testing.
Here is an example implementation of factorial with require
and assert
def fac(i: Int) = { require(i >= 0, "i must be non negative") //this is for correct input @tailrec def loop(k: Int, result: Long = 1): Long = { assert(result == 1 || result >= k) //this is only for verification if(k > 0) loop(k - 1, result * k) else result } loop(i) }
When result > 1
is true, then the loop was executed at least once. So the result has to be bigger or equal to k
. That would be a loop invariant.
When you are sure that your code is correct, you can remove the assert
, but the require
would stay.
You can see here for a detailed discussion within Scala language.
I can add that, the key to distinguish between require
and assert
is to understand these two. These two are both tools of software quality but from different toolboxes of different paradigms. In summary assert
is a Software testing tool which takes a corrective approach, whereas require
is a design by contract tool which takes a preventive approach.
Both require
and assert
are means of controlling validity of state. Historically there were 2 distinct paradigms for dealing with invalid states. The first one which is mainstream collectively called software testing discipline methodologies and tools. The other, called design by contract. These are two paradigms which are not comparable.
Software testing ensures a code versatile enough to be capable of error prone actions, were not misused. Design by contract controls code from having such capability. In other words Software testing is corrective, and design by contract is preventive.
assert
is used to write unit tests, i.e. if a method passes all tests each written by an assert
expression, the code is qualified as error free. So assert
seats besides operational code, and is an independent body.require
is embedded within code and part of it to assure nothing harmful can happen.In very simple language:
Require
is used to enforce a precondition on the caller of a function or the creator of an object of some class. Whereas, assert
is used to check the code of the function itself.
So, if a precondition fails, then you get an illegal argument exception
. Whereas, if an assertion fails and it's not the caller's fault and consequently you get an assertion error
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With