SUnit can be used as a tool for doing Design By Contract. SUnit is really good at testing existing code, but it was originally built (by Kent Beck) as a tool to support TestDrivenDevelopment.
Writing the tests before you write the method bodies is what Design By Contract (DBC) is. In DBC and its associated Eiffel programming language, the contracts are part of the language and part of the methods themselves.
In DBC, Items always receive state that is in assured condition - it meets pre-conditions. Which you can define as contracts. After the method is finished with the data, it is intended to meet the defined post-conditions, i.e. the method does consistency checking on its data, based on its own specifically defined rules, once it has completed. This helps ensure that the data is correct before any future method has to deal with it. And so the data has a much better chance of meeting the next pre-condition it meets.
All the methods in Eiffel are intended to meet pre-conditions, essentiually by receiving post-conditioned from other methods and objects. i.e. it would have been checked for consistency with its own rules from what results could be provided, before it was passed to the next object.
So if you think of SUnit as a tool for doing design contracts :
TestCase setup provides preconditioned data (tho' test data)
Tests are run on the output of the methods' work. These tests act as postconditions.
In Eiffel, pre-and post conditions were dealt with as
assertions of a positive statement
the NOT of a positive case.
In SUnit, we
assert: the positive cases,
deny: the negative cases.
Eiffel also had invariants. I kind of think of the Class-level tests in SUnit as its equivalent of invariants.. (Or maybe the analogy is with TestCase's teardown method, where it tidies everything up after itself, ready for the next run of the tests).
SUnit also has assert:description: and deny:description: keyword messages. The description parameter provides the Transcript with a message when individual tests pass or fail.