Posts Tagged ‘testing’

Finding tests related to code you are changing

Sunday, December 7th, 2008

Often, when working on a well tested codebase, you find that you want to know what tests may exist that test the code you are going to modify.

Often a quick search on usages of a method or class is sufficient. You look at the tests briefly to see what is going on, and then you make a new test to assert the new behavior that is going to be added.

Sometimes, when there are a lot of tests, I just prefer to remove the code I’m going to modify, and see what tests fail.

This technique provides some quick and useful information. For instance:

  1. What tests were written that test the code? Are there any applicable tests?
  2. Are there other tests that implicitly test the code and should not?
  3. Are the current tests testing all the conditions?
  4. Is there a test that no longer applies?
  5. Is there a test who’s expectation are changing? That test can be modified instead of writing a new test.

This approach tends to be practical in the case of unit tests, and perhaps a few integration tests that you may know are related. Otherwise, it becomes too expensive to run a long running suite.

An additional benefit is that if you already know of some tests that should be testing some code, you may find a test that meant to test the logic, but for some reason was always passing.

An “old school” technique for testing summation

Saturday, September 20th, 2008

I wrote some tests a few weeks back where I had to sum up a bunch of values on a collection of objects and assert that the summation happened correctly. A naive way to do this is to build the test objects with all the values equal to 1, sum them, and assert that the total is the same as the number of objects created for the test.

  1. int calculateClaimTotal(List<Claim> claims) {
  2.         int total = 0;
  3.         for (Claim claim : claims) {
  4.                 total += claim.getAmount();
  5.         }
  6.         return total;
  7. }

In this example, you could test calculateClaimTotal by creating 3 claims with amounts = 1, and assert that the total is 3.

This may seem sufficient for a simple summation, but it becomes more flawed when the summation becomes based on business rules. Now, if the values to be summed are all 1, you can’t differentiate which rules were enforced by looking at the resulting number directly.

  1. int calculateClaimTotal(List<Claim> claims) {
  2.         int total = 0;       
  3.         for (Claim claim : claims) {
  4.                 if (claim.isActive()) {
  5.                         total += claim.getAmount();
  6.                 }
  7.         }
  8.         return total;
  9. }

Now, we want to be able to differentiate that the active claims are the ones that get summed. This can become a bloated assertion to make. For instance, you can extend the test objects and count invocations on getAmount(). Then, you can assert that only the objects you expected where used to calculate the total.

A much simpler way of asserting that the objects that you expected were the ones that were used is to use amount values that, when summed, always have a distinct result. This is achieved by using numbers that map to distinct bitwise values:

00001 = 1
00010 = 2
00100 = 4
01000 = 8
10000 = 16

There is no way to add any of these numbers and have them be equal to any other summation of a subset of the numbers. This is because addition of 2 of these numbers is equivalent to an “or” operation on the bits of the numbers:

00001 = 1
00010 = 2
+__________
00011 = 3

This characteristic allows me to identify exactly what claims where used in the summation, because the resulting value could only occur from the values I expect:

Claim 1 is active with value = 1
Claim 2 is inactive with value = 2
Claim 3 is active with value = 4

I can assert that calculateClaimTotal will return 5 here, and that 5 will occur if and only if Claim 1 and Claim 3 are the ones used for the summation. Essentially, a bit location set to 1 instead of 0 will uniquely identify the object that the value came from.

I call this an old school testing technique because these days, there is not a lot of bitwise math that occurs in the course of programming. Back in the day, high performance C programmers would use bitwise operation often, and api’s such as the win32 api used bitwise math as part of api.

Even in today’s fancy world of high level abstraction, sometimes it takes a smooth low level trick like this one to achieve the most succinct code.