Both asserts and unit tests serve as documentation for a codebase, and a means of discovering bugs. The main differences are that asserts function as sanity checks and see real inputs, whereas unit tests run on specific simulated inputs and are tests against a single well-defined "right answer". What are the relative merits of using asserts vs. unit tests as the main means of verifying correctness? Which do you believe should be emphasized more heavily?
Unit-testing – Are asserts or unit tests more important
assertionstestingunit testing
Related Solutions
Neither asserts nor unit tests are appropriate in that case. Both are meant to check that your code actually does what you want it to do. This is not part of your application, and only run at development/debugging time.
Unit tests check some small chunk of code does what is needed, provided other components are correct.
Asserts document that you designed your code so that some condition is always (meant to) be true at that time, taking into account the interactions between components.
A third party system failing to initialize is out of your direct control.
You just have to detect it (check a status ?, catch exception ?,...) and handle it (intelligently abort the program with appropriate information, propose some degraded mode, ...). This is part of your application release code and runs in production.
To apply the same method to a collection, you can use LINQ to great effect.
If you want to compare everything to the same instance you can do this:
productList.Select(item => IsSameDescription(productA, item)).ToList();
The CollectionAssert
also has a variant that takes a comparator function:
CollectionAssert(expectedProductList, actualProductList, IsSameDescription);
Clarification about custom exceptions:
The primary reason to use custom assertions rather than the generic AssertTrue
or Assert.IsTrue
is that the error messages provide more detail as to what exactly the problem was. For example, Assert.AreEqual(obj1, obj2)
or Assert.That(obj1).IsEqualTo(obj2)
will tell you both what the expected answer was and what the actual value was. That should be the goal you are looking for with any custom assertion.
There are several assertion libraries, so you might have to re-invent the wheel. Some test libraries have the assertion library included (Like NUnit, JUnit, etc.).
I would much rather see intelligent use of a standard assertion library than writing custom assertions for everything. Using the example you provided:
Assert.AreEqual(product1.Description, product2.Description);
Is as expressive as you need.
Best Answer
Asserts are useful for telling you about the internal state of the program. For example, that your data structures have a valid state, e.g., that a
Time
data structure won't hold the value of25:61:61
. The conditions checked by asserts are:Preconditions, which assure that the caller keeps its contract,
Postconditions, which assure that the callee keeps its contract, and
Invariants, which assure that the data structure always holds some property after the function returns. An invariant is a condition that is a precondition and a postcondition.
Unit tests are useful for telling you about the external behavior of the module. Your
Stack
may have a consistent state after thepush()
method is called, but if the size of the stack doesn't increase by three after it is called three times, then that is an error. (For example, the trivial case where the incorrectpush()
implementation only checks the asserts and exits.)Strictly speaking, the major difference between asserts and unit tests is that unit tests have test data (values to get the program to run), while asserts do not. That is, you can execute your unit tests automatically, while you cannot say the same for assertions. For the sake of this discussion I've assumed that you are talking about executing the program in the context of higher-order function tests (which execute the whole program, and do not drive modules like unit tests). If you are not talking about automated function tests as the means to "see real inputs", then clearly the value lies in automation, and thus the unit tests would win. If you are talking about this in the context of (automated) function tests, then see below.
There can be some overlap in what is being tested. For example, a
Stack
's postcondition may actually assert that the stack size increases by one. But there are limits to what can be performed in that assert: Should it also check that the top element is what was just added?For both, the goal is to increase quality. For unit testing, the goal is to find bugs. For assertions, the goal is to make debugging easier by observing invalid program states as soon as they occur.
Note that neither technique verifies correctness. In fact, if you conduct unit testing with the goal to verify the program is correct, you will likely come up with uninteresting test that you know will work. It's a psychological effect: you'll do whatever it is to meet your goal. If your goal is to find bugs, your activities will reflect that.
Both are important, and have their own purposes.
[As a final note about assertions: To get the most value, you need to use them at all critical points in your program, and not a few key functions. Otherwise, the original source of the problem might have been masked and hard to detect without hours of debugging.]