Go Christmas tree kata

Bjorn Krols

Bjorn Krols

Published on
23 May 2022

In this article, you will learn how to quickly set up a test-driven environment to perform a Christmas tree kata in Go.

The rules of this kata are:

Draw a Christmas tree with ASCII characters, the height of the tree should be specifiable.

Example of a tree with a height of 3:

  X
 XXX
XXXXX
  |

Example of a tree with a height of 5:

    X
   XXX
  XXXXX
 XXXXXXX
XXXXXXXXX
    |

Project setup

Create a new Go module:

go mod init kata

Create the main source file:

touch main.go
package main

func DrawTree() {
    // TODO: add implementation here
}

TDD setup

Install Testify:

go get github.com/stretchr/testify

Create the test file:

touch main_test.go
package main

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

func TestDrawTree(t *testing.T) {
    // TODO: add tests here
    assert.Equal(t, 2, 1+1)
}

To run tests automatically when source files are changed:

watchman-make -p '**/*.go' --make=go -t test

To run tests manually:

go test

Example tests and implementations

Draw a trunk

Test:

func TestDrawTree(t *testing.T) {
    // Draw a trunk
    /*
        |
    */
    // Draw a trunk
    assert.Equal(t, "|", DrawTree())
}

Implementation:

func DrawTree() string {
    tree := "|"
    fmt.Println(tree)
    return tree
}

Height of 1

Test:

// Height of 1
/*
    X
    |
*/
assert.Equal(t, "X\n|", DrawTree(1))

Implementation:

package main

import "fmt"

func DrawTree(height int) string {
    tree := ""
    if height == 1 {
        tree += "X"
        tree += "\n"
    }
    tree += "|"
    fmt.Println(tree)
    return tree
}

Height of 2

Test:

// Height of 2
/*
     X
    XXX
     |
*/
assert.Equal(t, " X\nXXX\n |", DrawTree(2))

Implementation:

func DrawTree(height int) string {
    tree := ""
    if height == 1 {
        tree += "X"
        tree += "\n"
    }
    if height == 2 {
        tree += " "
        tree += "X"
        tree += "\n"
        tree += "XXX"
        tree += "\n"
        tree += " "
    }
    tree += "|"
    fmt.Println(tree)
    return tree
}

Height of 3

At this point, we can start to refactor our implementation.

Test:

// Height of 3
/*
      X
     XXX
    XXXXX
      |
*/
assert.Equal(t, "  X\n XXX\nXXXXX\n  |", DrawTree(3))

Implementation:

package main

import (
    "fmt"
    "strings"
)

func DrawTree(height int) string {
    tree := ""
    if height > 0 {
        for line := 0; line < height; line++ {
            tree += strings.Repeat(" ", height-line-1)
            tree += strings.Repeat("X", 2*line+1)
            tree += "\n"
        }
        tree += strings.Repeat(" ", height-1)
    }
    tree += "|"
    fmt.Println(tree)
    return tree
}

Subscribe to our newsletter

The latest news, articles, and resources, sent to your inbox weekly.

More like this