We are now ready to begin writing our first lines of actual production code. To assist us we have our acceptance tests that we need to pass, and the CRC-cards from last time. More importantly perhaps, we have access to those who can tell us what the acceptance tests really mean if we get confused, and we have access to the rest of the team that can help us recall and refine what came out of the CRC-session.
We start by looking at the acceptance test. The first thing that it does is to establish a connection between two subscribers. This looks like a good place to start.
Remembering the quick design session, we begin with the Subscriber class. Our first test ends up looking something like this:
class TestSubscriber < Test::Unit::TestCase
include FlexMock::TestCase
def setup
#...
end
def test_start_waiting_for_calls
factory = flexmock('CallReceiverFactory')
receiver = flexmock('CallReceiver')
factory.should_receive(:create_receiver).with(@address, @port).and_return(receiver).once
receiver.should_receive(:start).with(@subscriber).once
@subscriber.start_receiving_calls(factory)
end
end
This test maps roughly to the first steps in the scenario we discussed last time. The Subscriber class is expected to create a CallReceiver and tell it to start listening to calls.
The code above is not by far the first version of this test. We started by just testing that we could tell the Subscriber to start receiving calls. Then we wanted to test that a CallReceiver would be created. That led us to add a CallReceiverFactory, which enabled us to control how CallReceivers are created from outside the Subscriber class. We needed this to be able to make sure that we are able to have the Subscriber class interact with our mocks in a test environment.
We then moved on to test that the CallReceiver was told to start receiving calls by the Subscriber. We actually missed that the CallReceiver will need to know who to notify when a call is received. That we didn’t discover until we started on the CallReceiver class later. We then had to go back and update this test and the corresponding production code.
We also had some notes from the CRC-session that told us that we need some information about IP-addresses and ports. That information eventually ended up in this test as well. We pass that information to the CallReceiver by way of the CallReceiverFactory so that we know from where the CallReceiver should be listening to calls.
We continue with the rest of the classes, focusing on implementing what is needed to get a connection established. If we notice new things that would make sense to add to the code, but isn’t really related to getting a connection up and running, we make a note of that and move on.
When we take a crack at the code for the acceptance tests, we notice that we need to pass an address and a port to the Subscriber’s constructor in order for it to know where it should listen for incoming calls. This forces us to add that data to the acceptance test as well. We do discuss this with the customer first of course.
Acceptance Tests
The acceptance test for the current version creates two Subscriber objects that listen at two different ports on localhost. This feels like a good compromise. We don’t test the application in its entirety right now, but we do use real communication and we have an easy way of asserting that both clients behave properly. This may be revised later though.
The acceptance tests were revised a bit when we started developing. Some information was added that we discovered was needed by the code in order for it to know what to do, and some information was deemed unnecessary. The current version looks like this:

What the Application Does So Far
- A Subscriber can listen for incoming calls.
- A Subscriber can make a call to a predetermined address.
- Subscribers can exchange information about the identity of the calling parties.
We have strived to keep this as simple as possible. For instance, for now all we do is exchange user information by each subscriber sending their name as a string over a TCP socket. This is all we need at the moment. No XML, SOAP, ASN.1, or other is needed yet. We are focusing on getting a connection up and running. We do know that we will (most probably) revise this later so we do our best to not have any duplication in the code. If we want to change from TCP sockets to another scheme, we shouldn’t need to do many changes. If we want to change to a more elaborate identification scheme, we should be able to get away with doing those changes at one place.
Notes
The tests so far make heavy use of mocks. Nearly everything is about testing that class A calls method M on class B with this and that argument. This may be due to the nature of this application – we’re just passing text between two endpoints, but I’m beginning to feel that there must be a different way.
I like the way mocks help me develop from the top down. If a class that I’m working on needs the help of another class, I don’t have to stop and begin implementing that class before continuing with the first. I just create the interface I need, create a mock from that, and continue with the first class. When I later move on to the “discovered” class, I already have a pretty good defined interface to implement.
The fact that this is done in Ruby seems to get me into trouble from time to time. There is no interface where I can put all of my assumptions when I mock a class that I haven’t developed yet. This means that I have to keep notes about what classes needs what methods with what arguments. When I start to implement a class that has only been mocked earlier I quite often notice that I need to make small changes to the interface that I drafted while mocking. With the interface construct, any such changes would be explicit. Tests relying on that interface would automatically start complain if I messed up there assumptions. In Ruby, I don’t get that help from the language and at times things got a little messy.
Using quick design sessions rather than working on design documents requires that there is a short time between the session and implementation. As it has been a while since I last worked on this, just looking at the CRC-cards wasn’t really enough to start implementing. Luckily, I could read the last blog entry and got a pretty good idea of what I was up to last time.