Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing with lots of use cases

Tags:

unit-testing

I am working on a java application which has a lot of use cases. Inputs to the application are different kinds of events occuring at different times. This kind of input gives rise to hundreds of test cases. Has anybody faced this kind of scenario? Do you make sure all the test cases are covered before making a release to the QA team? So my question is: what is the best approach for testing programs with lots of test cases?

like image 534
Geos Avatar asked Jul 31 '09 18:07

Geos


People also ask

Should unit tests cover all cases?

Unit tests should validate all of the details, the corner cases and boundary conditions, etc. Component, integration, UI, and functional tests should be used more sparingly, to validate the behavior of the APIs or application as a whole.

Is there such a thing as too many unit tests?

Yes, it is possible to have too many unit tests - a simple thought experiment shows that you can continue adding tests that don't provide additional value, and that all those added tests can inhibit at least some refactorings.

How many unit tests should you have?

I write at least one test per method, and somtimes more if the method requires some different setUp to test the good cases and the bad cases. But you should NEVER test more than one method in one unit test. It reduce the amount of work and error in fixing your test in case your API changes.


1 Answers

Don't try to cover with unit tests the whole application from the beginning. Do it in small, incremental steps. Set a small milestone to reach in within a week or two and then start writing tests for the first functionality of that milestone. Then start implementing that functionality. It should be something like this:

Small, incremental steps

  1. Break down the application into smaller feature milestones that you can see at that moment
  2. Choose the most pressing feature that has to be implemented at that moment
  3. Break that feature into smaller tasks
  4. Write a test for one of the tasks
  5. Run the test. It should fail (RED). If it pass your test is broken.
  6. Start write the least amount of code in order for that test to pass. Hard coded values are allowed.
  7. Run the tests (GREEN). They should pass (especially when using hard-coded values). Now you know you have a safety net for future refactorings.
  8. Start refactoring (REFACTOR) your code if there's a need, otherwise go to step 4.

Prepare for change

The advantage of this method, breaking a huge task into manageable pieces is that it gives you the chance to have something finished in within a week or two. Later on, the management may rethink they priorities and you'll have to reorganize the list from the first point above. Another advantage is that having at every step a unit test that backs you up gives confidence an a sense that you are actually accomplishing something, and you may actually deliver something to your management faster than you'd believe because at every step you have a (somewhat) working version of your program. They can see progress and this is very important for both you and them. They see that work is actually being done, and you get the feedback that you need for your application (requirements always change, let's keep them changing as early as possible).

As Gren said, you're probably confusing use cases with unit testing. The actions that a user may take on an application may just as well be handled by a single method in the domain model. So the situation may not be as bad as it seems.

No up front design, even for unit tests

Anyway, don't try to write all of your tests from the beginning. That's the way I was doing it and it was a big fail. Once you do small iterations (test method/ method implementation) you'll become much more productive and self-confident. When writing all of your tests up front, you may notice that due to factorizations necessary to make your first tests pass, you'll need to rethink the whole API that you envisioned when writing the tests in the first place, whereas writing a test, then the implementation, a test, then the implementation, you end up with what it's called emergent design. And this is the best kind of design. This is how design patterns appeared. Design patterns did not emerge from someone who stood all day long and thought about ways to solve the problem.

like image 84
Ionuț G. Stan Avatar answered Nov 12 '22 03:11

Ionuț G. Stan