Tag Archives: Dojo - Page 2

Weekly – CW12

I usually exchange interesting articles, presentations and links with my friends in many different ways. I thought it would be better to use one simple way, so I’m going start a weekly series where I post articles, presentations and links I read during the week and find interesting. So here is the collection for calendar week 12, 2011:

  • Google was always famous for innovation. Patrick Copeland presented the eXtreme innovation approach – used by Google -, in his Keynote at QCon 2010. Pretotyping seems to be a good way for implementing only those ideas that really matter. It also helps not to spend time and money on ideas that people will hardly ever or never going to use.
  • My average e-mail inflow was approximately 90 e-mails per day and I read about 5 of them. I was happy to read an article about how to write e-mails effectively. If everyone who wrote to me, had read this article and had written mails as the author had suggests, I might have had the chance to read all of them.
  • Last but not least, here comes a great post about handling waste properly in lean systems. As usual, waste elimination is not black or white. A good lean/Kanban team (or team leader) should be able to recognize the nature of the waste, and eliminate what is really unnecessary.
VN:F [1.9.17_1161]
Rating: 0.0/10 (0 votes cast)

Testing the Stack Implementation

I’ve created my own version of the exercise used during my first agile job interview in order to compare it to the result of the pair programming session of the job interview. The exercise was quite simple: implement a stack, and store the values in an array. The implementation is pretty straightforward, the code is available on github. One can ask: why an array, why not using the collection framework? The answer is simple: just for fun, and just for the exercise :-)

In order to store the necessary amount of values, the internal array needs to be enlarged from time to time. There is nothing wrong with this so far. But in order to avoid unnecessary memory loss, that internal array needs to be shrunk as well. The first version of my Stack implementation lacked this functionality. The user stories of the functionality request can be:

  • As a developer, I don’t want to reserve more memory for my stack implementation than necessary
  • As a customer, I don’t want to lose values after shrinking the internal container

The second user story is very straightforward, so let’s focus on the first one. User stories and previous test cases are available, so far so good, but how to test the user story? An even better question: how to write a test case first? I consider my Stack implementation as an end product, and as such, I believe that it should follow the encapsulation object oriented programming principle, and it shouldn’t be difficult to use. An obvious choice would be a reflection-based solution, but since I’m not a great fan of reflection, I started to test the code from different angles.

For better understanding, here comes the code being tested:

    private void shrinkContainerCapacity() {
        int[] extentedContainer = new int[container.length - 10];
        System.arraycopy(container, 0, extentedContainer, 0, container.length - 10);
        container = extentedContainer;
    }

The first user story suggests memory handling, so first let’s try out this angle. Memory usage can be checked with the following methods:

Using those methods I wrote this test case sketch:

    @Test
    public void shouldUseLessMemoryAfterShrinkingInternalContainer() {
 
        for (int attempts = 0; attempts < 15; attempts++) {
            for (int i = 0; i < 10000; i++) {
                stack.push(i);
            }
 
            long availableMemoryBefore = getAvailableMemory();
            for (int i = 0; i < 10000; i++) {
                stack.pop();
            }
 
            long availableMemoryAfter = getAvailableMemory();
            assertTrue(availableMemoryBefore < availableMemoryAfter);
        }
    }
 
    private long getAvailableMemory() {
        System.gc();
        System.runFinalization();
        System.gc();
        System.runFinalization();
        long totalMemory = Runtime.getRuntime().totalMemory();
        long freeMemory = Runtime.getRuntime().freeMemory();
        return totalMemory - freeMemory;
    }

I’ve executed the test case several times and it never turned red. I was curious why, because it supposed to be work, isn’t it?

The javaDoc of System.gc() and System.runFinalization() states that: “…the Java Virtual Machine has made a best effort…“. Additionally Java Virtual Machine implementations may differ on operation system level: “…The aim is binary compatibility. Each particular host operating system needs its own implementation of the JVM and runtime. These JVMs interpret the bytecode semantically the same way, but the actual implementation may be different.” (source: Wikipedia).

Adding these statements up makes me nervous. The whole situation – using memory measurements for testing – starts looking black for me, so I did some measurements using the test code from above with different Java Virtual Machine implementations on different operating systems:

  • Running with eclipse 1.6 jre on Ubuntu Linux
  • Running with oracle’s 1.6 jre on Ubuntu Linux
  • Running with jrockit 1.6 jre on Ubuntu Linux
  • Running with oracle’s 1.6 jre on Windows XP

I’m interested how the assertTrue(availableMemoryBefore < availableMemoryAfter) will turn out in the different scenarios, so I’m measuring the availableMemoryBefore and availableMemoryAfter values, and calculate the SIGN of their difference: if the availableMemoryAfter is greater than availableMemoryBefore the SIGN will return 1, which is equal to a true test case and a green bar. In other words, after shrinking the array, the Stack uses less memory. Mission accomplished sort of say.

Before evaluating the results I have to note two things.  I’ve executed the test cases several times and I didn’t find any difference in their outputs, that’s the reason why I have only one measurement sheet for each case. Additionally I sometimes have the feeling that there is a slight difference when I’m running a java application/test case from eclipse and from command line using oracle’s jre, therefore I did the measurements with both of them separately. The detailed measurement values are available in this spreadsheet. Now the result:

Now my red bar is understandable. I’m using eclipse under Ubuntu Linux (and oracle’s jre), and according to the diagram above, there is less available memory after the first execution of the shrinking (again, I executed this particular measurement more than twenty times, and I always got the same result). If I had used jrockit, the problem above never would have turned out (the orange bars are always at 1, meaning that there is more available memory after shrinking in every case).

I would have stopped with the measurements here, unless my friend had asked me this: “Why did you have to call the System.gc() and System.runFinalization() twice?” It is a very good question. The more I call the System.gc() the more feasible is that the Java Virtual Machine will do garbage collection, which means that my application will use less memory, at least on paper.

Unfortunately experience shows otherwise. Have a look again at the javaDoc of System.gc(). In layman’s terms the System.gc() call is just a request to the Java Virtual Machine, and there is no guarantee that it will consider the call at all. According to my measurements below, the Java Virtual Machine considered it, but I had participated in a project several years ago, in which we had memory issues and no matter how often we called the System.gc() nothing really happened. The Java Virtual Machine felt that the time for garbage collection had not come yet, so it ignored our request.

So SIGN (before – after) looks this, when I’m calling the System.gc() and System.runFinalization() only once:

 

In this case I would still see a red bar with my setup, in several cases (7, 9, 11, 13 and 15) the SIGN is 0, meaning that the amount of available memory is the same before and after the shrinking. After having a close look there isn’t any option, which would make my bar green. I feel like I’m getting somewhere: checking memory usage as validation is not that promising as it was before I started measuring it. Let’s see the result without any System.gc() and System.runFinalization() calls in order to finish my measurements and provide more data for evaluation:

 

The result is not deterministic at all. Now I’m 100% sure that checking the memory is a dead end for me. I cannot garantee that my shouldUseLessMemoryAfterShrinkingInternalContainer() test case will produce the same output every time. Someone can use a different kind of machine for test case execution – for example Solaris, on which I didn’t do any measurement at all -, or can change my getAvailableMemory() helper method and execute less or more System.gc() calls. Unfortunately I need a different approach.

The next thing worth having a look at is injecting the array copy functionality. Unfortunately, the System.arraycopy() method is static, so I have to wrap it up, and inject the wrapper class into my Stack. The Stack is considered an end product, I cannot let the user take care of the dependency injection by herself, so I need a factory to do that:

public class StackFactory {
	public Stack create() {
		return new Stack(new ArrayCopyWrapper());
	}
}
// ...
public class ArrayCopyWrapper {
    public void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
        System.arraycopy(src, srcPos, dest, destPos, length);
    }
}

First let’s see the effect of this modification on the test code:

    @Test
    public void shouldShrinkInternalCapacity() {
        FakeArrayCopyWrapper arrayCopyWrapper = new FakeArrayCopyWrapper();
        stack = new Stack(arrayCopyWrapper);
 
        arrayCopyWrapper.setExpectations(0, 0, 10);
        for (int i = 0; i &lt; 20; i++) {
             stack.push(i);
        } 
 
        // Had to cut the for() loop in half
        // In order to be able to set two expectations
        arrayCopyWrapper.setExpectations(0, 0, 20);
        stack.push(20);
 
        // The same reason here
        arrayCopyWrapper.setExpectations(20, 10, 1);
        stack.pop();
 
        arrayCopyWrapper.setExpectations(20, 10, 15);
        for (int i = 20; i &gt;= 5; i--) {
           stack.pop();
        }
    }

I didn’t want to spend too much time on setting up and using mock libraries. I had the strange feeling that I didn’t have to put too much effort into this angle. A simple fake object will be just fine:

public class FakeArrayCopyWrapper extends ArrayCopyWrapper {
    private int srcPos;
    private int destPos;
    private int length;
 
    public void setExpectations(int srcPos, int destPos, int length) {
        this.srcPos = srcPos;
        this.destPos = destPos;
        this.length = length;
    }
 
    public void arraycopy(int srcPos, Object dest, int destPos, int length) {
        assertEquals(this.srcPos, srcPos);
        assertEquals(this.destPos, destPos);
        assertEquals(this.length, length);
    }
}

Although I wrote the shouldShrinkInternalCapacity() and FakeArrayCopyWrapper class, I don’t like them too much. The test case is complicated and the Fake is strange.

Additionally, when someone wants to instantiate my Stack she must do this:

Stack stack = new StackFactory().create()

But, this version seems to be more user friendly:

Stack stack = new Stack()

The first version is good for internal classes, but personally I don’t want my users to do complicated things like using wrapper factories for creating an object, when there is an easier way.

However there is one more thing. The ArrayCopyWrapper wraps only the System.arraycopy() call. If I executed a code coverage measurement using the shouldShrinkInternalCapacity() test case, the measurement would indicate that the shrinkContainerCapacity() method is 100% covered with shouldShrinkInternalCapacity() test case. This is not true. The current version of shouldShrinkInternalCapacity() does not test the command below, because it focuses only on the arraycopy:

    private void shrinkContainerCapacity() {
        //...
        //...
        container = extentedContainer;
    }

One can argue that the line above is indirectly tested by the other test cases.  This is true, but I would like to have focused test cases and correct coverage data.

This solution is not user friendly and I had to do things in testing which I don’t really like. This approach is another dead end for me, at least.

The last thing I can think of is checking the size of the internal container. I have the following options:

  • make it protected
  • create a protected method for getting its size
  • use reflection

The first two options harm encapsulation, which I have no intention to do, so another dead end.

I had no other option but to do the testing with reflection. I don’t like the current state of the test cases, but I have no other ideas. So I’m going to leave this post open, feel free to submit other ideas on how this feature can be tested. The code is available on github, and any suggestions and comments are welcome.

VN:F [1.9.17_1161]
Rating: 0.0/10 (0 votes cast)

jMock versus Mockito

I’ve been using jMock for more than a year now, but recently I came across mockito. In this post, I’ll show the difference between jMock and mockito – without judging which one is better – using the basic features I’ve been using the most often from jMock. I admit that there are more features than presented in this post, but for starters, I find these enough.

The versions under comparison:

The Test Object

For this demonstration, I’m using a very fictional, but simple code example which fits the purpose of comparison.

The skeleton of the main class which is going to be tested:

public class PosTerminal {
 
	private static final String SHOP_ACCOUNT_NUMBER = "00000000-00000000";
	private final ReceiptPrinter receiptPrinter;
	private final BankConnection bankConnection;
 
	public PosTerminal(BankConnection bankConnection,
                           ReceiptPrinter receiptPrinter) {
		this.bankConnection = bankConnection;
		this.receiptPrinter = receiptPrinter;
	}
 
	public boolean buyWithCard(int amountOfMoney, String cardNumber) {
	}
}

The skeleton of the first injected class:

public class BankConnection {
 
	public Account getAccountByCardNumber(String cardNumber) {
		return null;
	}
 
	public Account getAccountByAccountNumber(String accountNumber) {
		return null;
	}
}

The skeleton of the second injected class:

public class ReceiptPrinter {
	public void print(String string) {
	}
}

And the interface for accounts:

public interface Account {
        boolean withdraw(int amountOfMoney, String destinationAccountNumber);
        boolean enter(int amountOfMoney, String sourceAccountNumber);
        void rollback();
        void commit();
}

Creating Mocks

jMock

import org.jmock.Mockery;
import org.junit.Test;
 
public class PosTerminalTest {
    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        Mockery context = new Mockery();
 
        BankConnection bankConnection = context.mock(BankConnection.class);
        ReceiptPrinter receiptPrinter = context.mock(ReceiptPrinter.class);
        // the test case continues...
    }
}

mockito

import static org.mockito.Mockito.mock;
import org.junit.Test;
 
public class PosTerminalTest {
    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        BankConnection bankConnection = mock(BankConnection.class);
        ReceiptPrinter receiptPrinter = mock(ReceiptPrinter.class);
        // the test case continues...
   }
}

There is no significant difference here. jMock uses a context for handling mocks, while mockito solves it with statically imported methods.

Mocking Classes

If you compile and execute the examples above, the following exception is raised when the jMock test case is executed:

java.lang.IllegalArgumentException: com.zsoltfabok.dojo.mocks.BankConnection is not an interface

jMock is designed to mock interfaces, not classes. It forces the developer to use interfaces, which is a good programming practice, but sometimes it is an overhead. Imagine that you are working on a legacy code. There is no way to extract interfaces for every single class just to satisfy a mocking framework. Fortunately, you can set jMock so that it can mock classes:

        // the same as before ...
        Mockery context = new Mockery() {{
            setImposteriser(ClassImposteriser.INSTANCE);
        }};
        // the same as before ...

There is no need for such setting in the mockito based test case.

Two Of The Same Kind of Mocks

During testing the PosTerminal class, we need to fetch two Accounts from the BankConnection. One for the card owner (customer) and one for the shop. They will be mocks, too:

jMock

        // the same as before ...
        Account customerAccount = context.mock(Account.class);
        Account shopAccount = context.mock(Account.class);
        // the same as before ...

mockito

        // the same as before ...
        Account customerAccount = mock(Account.class);
        Account shopAccount = mock(Account.class);
        // the same as before ...

No difference here at first sight. After executing the jMock test case, the following exception is raised:

java.lang.IllegalArgumentException: a mock with name account already exists

Internally, jMock uses name references for handling mocks, and if no name is specified, the name will be the type of the mock. In the example above, we have two Accounts with the same name. The problem can be solved easily:

        // the same as before ...
        Account customerAccount = context.mock(Account.class, "customer account");
        Account shopAccount = context.mock(Account.class, "shop account");
        // the same as before ...

Annotation

Based on the mockito and jMock documentation it is possible to setup mocks with annotations, which is excellent, because with this approach, I can make the test case much simpler.

jMock

Although the current stable jMock documentation describes the @Mock annotation, I was unable to find it in the framework.

mockito

import org.mockito.Mock;
// Other import statements ...
 
@RunWith(MockitoJUnitRunner.class)
public class PosTerminalTest {
    @Mock
    private BankConnection bankConnection;
    @Mock
    private ReceiptPrinter receiptPrinter;
    @Mock
    private Account customerAccount;
    @Mock
    private Account shopAccount;
 
    @Test
    public void shouldPrintSuccessfulWithdrawal() {
    }
}

Note that in order to make it work, you need a @RunWith annotation.

Call Verification and Return Value Handling

This is the good part; how our class communicates with the injected classes. The verification is quite simple: check whether or not a method of the mock is called. The other thing is how our class can handle the return value of a method of a mock.

jMock

    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        PosTerminal posTerminal = new PosTerminal(bankConnection, receiptPrinter);
 
        context.checking(new Expectations() {{
            oneOf(bankConnection).getAccountByCardNumber("1000-0000-0001-0003");
            will(returnValue(customerAccount));
 
            // Other oneOf() will() statements ...
 
            oneOf(receiptPrinter).print("Successful withdrawal");
        }});
 
        posTerminal.buyWithCard(100, "1000-0000-0001-0003");
    }

mockito

    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        PosTerminal posTerminal = new PosTerminal(bankConnection, receiptPrinter);
 
        when(bankConnection.getAccountByCardNumber("1000-0000-0001-0003"))
            .thenReturn(customerAccount);
        // Other when(...).thenReturn(...) calls ...
 
        posTerminal.buyWithCard(100, "1000-0000-0001-0003");
 
        verify(receiptPrinter).print("Successful withdrawal");
    }

The order in which the methods are called is important. In case of jMock, the Expectations shall come before the method call, and in case of mockito the verify() always afterwards. There is no significant difference between jMock and mockito in this case, besides readability. The verify() method call clearly states that the we are just checking if a method is called. This clear difference makes the code more readable for me. Another readability thing is that for me, the inner class Expectations is less readable. If the mocks are not fields, then, because of the inner class, I have to make the mocks final.

Argument Matchers

Sometimes one or more arguments are not relevant when a method of a mock object is called.

jMock

        context.checking(new Expectations() {{
            // Other oneOf() will() statements ...
 
            oneOf(customerAccount).withdraw(with(any(Integer.class)),
                    with(any(String.class)));
            will(returnValue(true));
 
            oneOf(shopAccount).enter(with(100), with(any(String.class)));
            will(returnValue(true));
 
           // Other oneOf() will() statements ...
        }});

mockito

import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
// Other parts of the code ...
    @Test
    public void shouldPrintSuccessfulWithdrawal() {
       // Other when(...).thenReturn(...) calls ...
 
        when(customerAccount.withdraw(anyInt(), anyString())).thenReturn(true);
        when(shopAccount.enter(eq(100), anyString())).thenReturn(true);
 
        // Other when(...).thenReturn(...)  and verify(...) calls ...
    }

The are no differences here, but I find the mockito version more readable. One additional thing is that neither of the frameworks support mixing the matchers with exact matches, for example:

jMock

Mind the missing with() call:

        context.checking(new Expectations() {{
            // Other oneOf() will() statements ...
 
            oneOf(shopAccount).enter(100, with(any(String.class)));
            will(returnValue(true));
 
           // Other oneOf() will() statements ...
        }});

The following exception will be raised during execution:

java.lang.IllegalArgumentException: not all parameters were given explicit matchers: either all parameters must be specified by matchers or all must be specified by values, you cannot mix matchers and values

mockito

Mind the missing eq() call:

       // Other when(...).thenReturn(...) calls ...
 
        when(shopAccount.enter(100, anyString())).thenReturn(true);
 
        // Other when(...).thenReturn(...)  and verify(...) calls ...

The following exception will be raised during execution:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), “raw String”);
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq(“String by matcher”));
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers!2 matchers expected, 1 recorded.This exception may occur if matchers are combined with raw values:    //incorrect:    someMethod(anyObject(), “raw String”);When using matchers, all arguments have to be provided by matchers.For example:    //correct:    someMethod(anyObject(), eq(“String by matcher”));

The output of mockito provides a bit more information.

Number of Invocations

Sometimes the number of invocations of a certain method is important. The approaches of jMock and mockito are quite the same, except that the number of invocations is used with the verify() method in mockito.

jMock

        context.checking(new Expectations() {{
           // Other oneOf() will() statements ...
 
            exactly(1).of(receiptPrinter).print(with(any(String.class)));
        }});

or

        context.checking(new Expectations() {{
           // Other oneOf() will() statements ...
 
            atLeast(1).of(receiptPrinter).print(with(any(String.class)));
        }});

or

        context.checking(new Expectations() {{
           // Other oneOf() will() statements ...
 
            never(receiptPrinter).print(with(any(String.class)));
        }});

mockito

       // Other when(...).thenReturn(...) calls ...
 
        verify(receiptPrinter, times(1)).print(anyString());
 
        // Other verify() calls ...

or

       // Other when(...).thenReturn(...) calls ...
 
        verify(receiptPrinter, atLeast(1)).print(anyString());
 
        // Other verify() calls ...

or

       // Other when(...).thenReturn(...) calls ...
 
        verify(receiptPrinter, never()).print(anyString());
 
        // Other verify() calls ...

There are plenty of other possibilities. jMock has allowing() and ignoring() options, which are not available in mockito. On the other hand, mockito has an only() method which makes the code more readable. In jMock, if an unexpected method call is made, a RuntimeException is thrown. In mockito this feature is not available. There is an issue for it with number 162.

Consecutive Calls

jMock

        context.checking(new Expectations() {{
            // Other oneOf() will() statements ...
 
            oneOf(shopAccount).enter(with(100), with(any(String.class)));
            will(onConsecutiveCalls(returnValue(true), returnValue(false),
                 returnValue(false)));
        }});

mockito

        // Other when(...).thenReturn(...) calls ...
        when(shopAccount.enter(eq(100), anyString())).thenReturn(true, false, false);

No difference, but I find mockito more readable.

Verify Call Order

jMock

    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        PosTerminal posTerminal = new PosTerminal(bankConnection, receiptPrinter);
 
        final Sequence sequence = context.sequence("account order");
        context.checking(new Expectations() {{
            // Other oneOf() will() statements ...
 
            oneOf(customerAccount).withdraw(with(any(Integer.class)),
                    with(any(String.class)));
            will(returnValue(true));
            inSequence(sequence);
 
            atLeast(1).of(shopAccount).enter(with(100), with(any(String.class)));
            will(returnValue(true));
            inSequence(sequence);
        }});
 
        posTerminal.buyWithCard(100, "1000-0000-0001-0003");
    }

mockito

    @Test
    public void shouldPrintSuccessfulWithdrawal() {
        PosTerminal posTerminal = new PosTerminal(bankConnection, receiptPrinter);
 
        posTerminal.buyWithCard(100, "1000-0000-0001-0003");
 
        InOrder inOrder = Mockito.inOrder(customerAccount, shopAccount);
        inOrder.verify(customerAccount).withdraw(anyInt(), anyString());
        inOrder.verify(shopAccount).enter(anyInt(), anyString());
 
        verify(receiptPrinter).print(anyString());
    }

One significant difference here: in case of mockito the involved mocks need to be injected when creating the InOrder (Sequence equivalent) object.

Exception Handling

jMock

        context.checking(new Expectations() {{
            oneOf(bankConnection).getAccountByCardNumber("1000-0000-0001-0003");
            will(throwException(new RuntimeException()));
         }});

mockito

        when(bankConnection.getAccountByCardNumber("1000-0000-0001-0003"))
        	.thenThrow(new RuntimeException());

No difference, other than readability.

Setup

In order to make the examples compile and run I had to add the following external libraries.

jMock

  • jmock-2.5.1.jar
  • jmock-junit4-2.5.1.jar
  • hamcrest-core-1.1.jar
  • hamcrest-library-1.1.jar
  • jmock-legacy-2.5.1.jar
  • cglib-2.1_3-src.jar
  • cglib-nodep-2.1_3.jar
  • objenesis-1.0.jar

mockito

  • mockito-all-1.8.5.jar

Some of the jMock libraries were added after I tried to run my test cases and it took me quite some time to find out the right build path. With mockito, I just had to add one simple jar file.

Conclusion

jMock and mockito are both very well documented with examples and good practical hints. However, based on the examples above I find the test cases more readable with mockito. In my next project I’m definitely going to work with mockito. One good advice: if you make the same decision, do not mix jMock and mockito in your test code. It will make your code unreadable, and additionally it might not even work: it would be hard to execute a mockito mock related code in a jMock TestRunner (mind the @RunWith annotations).

VN:F [1.9.17_1161]
Rating: 10.0/10 (4 votes cast)

Using Kata for Improvements

I used to keep coding dojos for my colleagues, and it was sometimes very hard to find the right topic. I recently rediscovered the code kata – I did it earlier, but stopped after a short period -, and got an idea. I’m going to use it for discovering areas where our teams can improve. The setup is very easy: I propose a certain kata to the others with a time constraint. While they are working – the participation is voluntary -, I’m hanging around and looking for certain clues. These clues and the discussions after the session will help me find the areas where we need to exercise more.

After they get used to the code kata style and are able to finish the exercise within the time frame, we go forward with some constraints. In the far future, they will be able to pick their own code kata and constraint, but first there are things which have to be re-learnt and practised more. Here are some of the usual problems:

  • Too much time spent in red
  • Too much thinking before actually doing something
  • Not following the ideas from the clean code book
  • Too large steps

My plan is to come out with good practices in order to show a way to improve these areas, but for now, let’s have a final look at the code kata setup:

  1. Present a coding exercise for the participants
  2. Give them a time frame and keep them informed about the elapsed time
  3. Walk around and watch out for things the guys are doing right and wrong
  4. When the time has elapsed, shortly discuss the experience, share ideas with each other (sharing is very important here)
  5. If there is time left, redo the session from the start

We are going to keep these sessions twice a week before the daily stand-up meetings. Usually this time of day is less productive, because not everybody is in the office, people are warming up, having their starting tea or coffee – the list goes on. It is also a good time for doing improvements, but I’ll talk about that in a different post.

One can ask why this style is different from others, and how it is going to help. I see it this way: if programmers have to perform a simple but challenging task under time pressure, they are focusing on it very much. They won’t bother that you are watching what they are doing, or that you are asking them short but focused questions. On the other hand, during pair programming, they may show a picture of themselves as they want to look like, or simply become shy. Time will tell how this is going to work. I’ll keep you posted.

VN:F [1.9.17_1161]
Rating: 0.0/10 (0 votes cast)

One Step Back In Testing

There are several advantages and disadvantages of Test Driven Development. In this post, I have no intention of repeating any of these, instead, I’d like to show a way to use TDD effectively while changing legacy code.

The Problem

Have a look at this legacy code:

package com.zsoltfabok.dojo.legacy.stepback;
public class Comparator {
    public boolean same(String string) {
        char[] data = string.toCharArray();
        char[] first = null;
        char[] second = null;
        boolean value = false;
 
        for (int i = 0; i &lt; data.length; i++)
        if (data[i] == ' ') {
            first = new char[i];
            second = new char[data.length - i - 1];
            System.arraycopy(data, 0, first, 0, i);
            System.arraycopy(data, i + 1, second, 0, data.length - i - 1);
            if (first.length == second.length)
                for (int j = 0; j &lt; first.length; j++)
                    if (first[j] == second[j])
                        value = true;
                    else {
                        value = false;
                        break;
                    }
            else
                return false;
            break;
        }
        return value;
    }
}

This code does not do much; it accepts two words separated with a space, and returns true/false depending on whether the words are equal or not. This works quite well, but imagine that we are asked to enhance it, so that the comparison is not case sensitive any more. As a first step, have some test cases in order to preserve the original behaviour:

public class ComparatorTest {
 
    private Comparator comparator = new Comparator();
 
    @Test
    public void shouldReturnTrueForTheSameWords() {
        assertTrue(comparator.same("word word"));
    }
 
    @Test
    public void shouldReturnFalseForDifferentWords() {
        assertFalse(comparator.same("ward word"));
    }
}

There can be more, but for now, they are enough (check the screencast and the source repository for the whole test suite). TDD and the green bar, among other things, make you/me confident that the upcoming changes won’t affect the already implemented behaviour. This is the most important thing in it for me. Now back to the legacy code. Have the test case, which will drive the change:

    @Test
    public void shouldReturnTrueForTheSameButDifferentlyCasedWords() {
        assertTrue(comparator.same("wORd word"));
    }

After having this test case on board, which turns the bar red, the following will happen:

  • introducing the change (implementation of the non case sensitive comparison)
  • massive refactoring (nobody doubts it I assume)

Such a huge work may take “hours” even for that small piece of code above (I admit that in this case it won’t take hours). Obviously, you cannot commit it, cannot ship it to the customer, you cannot show it to others besides your pair, etc. until the change is not done.

Ideas for Solving the Problem

The TDD mantra says red-green-refactorred-green-refactor,… but is does not say anything about the time spent in each phase, a factor that I consider very important. For example, staying too long in green and refactor means less or no progress, staying too long in red means losing control over the code, causing quality and feature degradation. In order to avoid these cases I’ll take two ideas:

The small steps help to make progress in green, and the limited time in red helps to stay on the right track. If you realize after some minutes that you are doing changing and refactoring in one step, you may do your last step back, and perform only one of them. I prefer doing the refactoring first, because the green code is shippable, shareable, and nevertheless I feel more secure, because the test cases prevent me from introducing bugs in the existing functionality. So a third item to the list:

  • take a step back: do the refactoring first and the change afterwards

One can argue that only the change has value to the customer so that shall be done first and refactoring afterwards. In my point of view, this statement highly depends on the definition of value. If the customer got the code, the value wouldn’t only mean the functionality but quality as well. However, I admit that there are cases when the change comes first and refactoring afterwards.

Ignoring Test Cases

One way of stepping back is to ignore the new test case. Do not delete it, just @Ignore it:

    @Ignore("Introduces new functionality, but I must refactor first")
    @Test
    public void shouldReturnTrueForTheSameButDifferentlyCasedWords() {
        assertTrue(comparator.same("wORd word"));
    }

An ignored test case is similar to a TODO note, but a bit more effective. You know that the test case is there, because Eclipse shows the number of ignored test cases. Now everything is green again, you spent less time in red, but need a smaller step. Do the refactoring now. The first test cases make sure that nothing is going to be broken, and with wise refactoring, the introduction of the change will be fast and easy.

When the refactoring is done, remove the @Ignore tag, and introduce the change. You can apply this technique as many times as you want.

Don’t get me wrong, there is nothing wrong with such test cases, on the contrary: they are very good test cases. They not only drive the implementation, but also point out that the code base needs refactoring.

Write Test Cases With Temporarily Wrong Assertion

The example above introduces something new, but sometimes an already existing functionality has to be fixed. Imagine that the customer complains that the method does not work if the input contains trailing spaces. Now, the test case looks like this:

    @Test
    public void shouldReturnTrueInCaseOfSameWordsButWithTrailingSpaces() {
        assertTrue(comparator.same("word word "));
    }

Another way of stepping back is to change the assertion here like this:

    @Test
    public void shouldReturnTrueInCaseOfSameWordsButWithTrailingSpaces() {
        assertFalse(comparator.same("word word "));
    }

This test case provides more safety, because this is how the legacy code works, isn’t it? As soon as the refactoring is done, do not forget to change back to the original test case.

Example

In the following screencast I demonstrate how to use these techniques while working with the example legacy code.

The source code of the example is available on github.

VN:F [1.9.17_1161]
Rating: 0.0/10 (0 votes cast)