Writing Unit Tests for Existing Code?
out-of-order asks: "I recently became a member of a large software organization which has placed me in the role of preparing the Unit Test effort for a component of software. Problem is that everything that I've read about Unit Testing pertains to 'test-driven' design, writing test cases first, etc. What if the opposite situation is true? This organization was writing code before I walked in the door and now I need to test it. What methodology is there for writing test cases for code that already exists?"
I don't see TestFirst as a Test Strategy, but as a design technique. Writing Tests first forces you to think differently about what you want to write.
This forces you to write testable code - writing tests afterwards does not force you to do that.
Of course, having the tests available later proves valuable for testing your application, but the tests main purpose is to lead you to a testable design
You'll most likely experience severe difficulties in adding Unit Tests to previously untested code. It might be easier to add acceptance tests (e.g. high-level scripts that utilize the application), especially if you want to cover more than small partitions of the application quickly
Write the tests as if the code _hadn't_ been written. Get the requirements and then write the tests from them.
Then if they fail the tests you'll have to discover if the requirements are wrong or if it's the code that's at fault. But at least you'll have something to start from - and you'll probably find some bugs they missed.
My Journal
Unit testing is a method you use to achive something. Is the current component very buggy and you need to rewrite it or do you need to extend production quality software without breaking existing functionality?
If you are testing a component try to figure out if it is possible to in some schematic way. If you can figure out a way for the "business" people to write the tests for you that will take a lot of knowledge off your shoulders.
If it is an existing component maybe you could explore if it is possible to make some mechanism that "records" actions to the component and then later be able to "replay" them and check if the results are the same with your new or changed component as the production quality one.
I recently started as a contractor on a J2EE project that has lots of problems. The application has a classic backend with lots of ugly EJB anti-patterns and everything. The frontend is a VB client that communicates via. a simple webservice.
In a couple of days I was able to make a regression test engine that can save the xml-communication that our business-clever testers make to the server and then at any given time later run the same requests to the server and check if the responens match the originally recorded ones.
It works wonders and I now have free hands to clear out a lot of the technical mess while always having proof that I havn't broken anything.
Think about what your goals are. Then find the best tool to get there.
Often there aren't detailed enough requirements.
With requirements at a typical business level, you could have X totally different systems that meet them (and most better given hindsight). And often that level is as much as you're going to get when the original team has left.
Anyway recreating requirements at a detailed technical level could be a waste of time - because some module could be required to do something stupid by another module. Once you fix things all round, this requirement will be thrown out.
At one of my workplaces I made major changes in behaviour of some modules - e.g. instead of N^2 it's just N. And some things I just threw out because they were redundant.
I suppose, you could rewrite the requirements (after figuring things out), and then rewrite the code. But that's quite different from _getting_ the requirements.
It was good thing since QA categorically refused to "test" the software by trying to break it, they would only tested to see if it could work if the customer did everything right.
What kind of testing is that? You have to assume that the customer won't do everything right if you're going to find bugs. Just because you're using automated code testing, it doesn't mean that the unit tests themselves have been written correctly or all the code works perfectly together. A good QA team needs to have attitude that everything will be tested and everyone else can kiss ass.
My suggestion that random banging on the keyboard, pushing buttons, and unexpectedly closing windows would be a good thing was not appreciated because there was no way to write it up as a test plan, or describe it as a repeatable bug.
In the video game industry, that's called button smashing. Programmers hated it because it meant that their input code didn't consider multiple buttons being pressed at the same time, and, worst, it was usually time dependent. Nintendo is very good at finding button smashing bugs.