Web Apps in TDD, Part 4

Multiple buildings!

I bet that you can tell where this is going, I’ve one building, now I want multiple buildings on my page and then finally put the player in the middle.
So, I add two more rectangles to my investigation.html.


            ...
            var map = new Raphael(0,0,600,400);
            map.rect(10,10,50,40);
            map.rect(80,10,30,40);
            map.rect(10,70,100,40);
            ...

Which produces :

Now, for the test that will lead me to implementing this…


    @Test
    public void shouldRenderMultipleBuildings() throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10,10,50,40);
        htmlScreen.addBuilding(80,10,30,40);
        htmlScreen.addBuilding(10,70,100,40);
        User user = new User().lookAt(htmlScreen.render());
        assertThat(user.currentSight(), is("A Rectangle at [10,10], 40px high and 50px wide"));
        assertThat(user.currentSight(), is("A Rectangle at [80,10], 40px high and 30px wide"));
        assertThat(user.currentSight(), is("A Rectangle at [10,70], 40px high and 100px wide"));
    }

The current result is :


Expected: is "A Rectangle at [10,10], 40px high and 50px wide"
     got: "A Rectangle at [10,70], 40px high and 100px wide"

Which is the last building only. This is due to my implementation of the html screen. Which stores the last building and overwrites the previous one. Easy fixed.


    private String renderBuildings() {
        String renderedBuildings = "";
        for (Building building : buildings) {
            renderedBuildings += building.render(vectorGraphics);
        }
        return renderedBuildings;
    }
    
    public Screen addBuilding(int x, int y, int width, int height) {
        buildings.add(new Building(x, y, width, height));
        return this;
    }

function Raphael(x, y, width, height){

    this.rect = function(x, y, width, height) {
        output[invocations++] = "A Rectangle at [" + x + "," + y + "], " +
                    height + "px high and " + width + "px wide";
    }

}

var output = [];

    public String currentSight() {
        return (String) output.get(current++);
    }

Now, for the real-life test


    public static void main(String... args) throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10,10,50,40);
        htmlScreen.addBuilding(80,10,30,40);
        htmlScreen.addBuilding(10,70,100,40);
        new Boss(11111, htmlScreen);
    }

But, the very first HtmlScreenBehavior test is not happy, it did expect a rectangle, now that rectangle needs to be added explicitly.


    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        User user = new User().lookAt(new HtmlScreen().addBuilding(10, 10, 50, 40).render());
        assertThat(user.currentSight(), is("A Rectangle at [10,10], 40px high and 50px wide"));
    }

Now it passes. All tests are green.

I’m so glad it’s time to refactor, because my tests are looking very bad. For instance, have a look at the test just after the one I just modified :


    @Test
    public void shouldRenderTheBuildingWithTheRightPositionAndDimensions() {
        User user = new User().lookAt(
        		new HtmlScreen().addBuilding(50, 30, 80, 40).render());
        assertThat(user.currentSight(),
        		is("A Rectangle at [50,30], 40px high and 80px wide"));
    }

Yes, they are the same, the only difference is in the values. This is pretty much the only instance were I do consider erasing a test without a change in features : when it says exactly the same thing as another test.

So, adieu! I delete the second one, as I like the first one’s name better.

What else? Well, I’m growing bored of typing all of these “A Rectangle…”.


    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        User user = new User().lookAt(new HtmlScreen().addBuilding(10, 10, 50, 40).render());
        assertThat(user.currentSight(), is(aRectangle(10, 10, 50, 40)));
    }

    @Test
    public void shouldRenderMultipleBuildings() throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10, 10, 50, 40);
        htmlScreen.addBuilding(80, 10, 30, 40);
        htmlScreen.addBuilding(10, 70, 100, 40);
        User user = new User().lookAt(htmlScreen.render());
        assertThat(user.currentSight(), is(aRectangle(10, 10, 50, 40)));
        assertThat(user.currentSight(), is(aRectangle(80, 10, 30, 40)));
        assertThat(user.currentSight(), is(aRectangle(10, 70, 100, 40)));
    }

    private String aRectangle(int x, int y, int width, int height) {
        return "A Rectangle at [" + x + "," + y + "], " + 
        			height + "px high and " + width + "px wide";
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s