In addition to the aforementioned test-driven development (TDD) technique, you could give a look at design by contract, another technique where, basically, one add assertions in the production code to validate at runtime that the contract clauses (inputs, outputs and invariants) between the components are respected. These assertions can be removed, or kept, when the software is delivered.
I'd like to augment my answer to make clear that TDD does not lead to "software that is designed to test itself", but some software, - the unit tests suite, grown along with the production code, that tests another piece of software.