I have created test equipment that has two programs, one for testing the hardware and software in one go, then the main program that is to control I/O and communications.
This took a while but was well worth it in the end as hundreds of units are being built each year. As the test equipment was thrown together and does the job I am currently creating a new piece of hardware (Software driven) that completes the task in under a minute (The existing test can take +10 minutes), this in mind requires me to think of all possible I/O and communications needed to complete the tests. What I have found is to test the test equipment in stages, only adjust 1 part of the code at a time and to document any findings. This way when looking back at the hardware and code you will know why it was done that way.
For example: I developed a test PCB with a PIC16 that tested all ports for dead shorts, this was then displayed on the LCD to indicate which pins were connected, however this was not as easy as first thought. From the above I documented each stage and completed the code and hardware this enabled me to create the finished product that we still use after 5 years. The hardware test was to short each pin to verify that it worked.
Likewise with RS232, RS485, MODBUS, Timers, RTOS systems *TCP/IP (*Which I am currently working on) are all tested as a block - documented and verified before moving on to the next stage. During this process the schematic is being developed and documented. Once I have determined all is ok a PCB will be made and populated, I will then test all functionality before production.
So the best thing to do is to test each and every part and each and every bit of code until you are 100% satisfied and that the hardware is 100% reliable.
Waffling on a bit there.. If you are only interested in digital I/O then you can create a bridged connection that outputs from one and inputs to another, This will test all of the I/O and allow you to test your code too. The use of resistor networks can also be used so that you have to drive the outputs to 0V in order to complete the input and output test. 10K resistor network should be more than enough.