Skip to content

Commit

Permalink
adding else, subtest syntax and first class functions oh my
Browse files Browse the repository at this point in the history
  • Loading branch information
quii committed Mar 7, 2018
1 parent d87e1fa commit 3bf3041
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 27 deletions.
4 changes: 0 additions & 4 deletions for/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ func Repeat(character string) (repeated string) {

`+=` adds a value to another. It works other types like integers.

## Next iteration

todo: Think of a way to include `continue` in exercise.

## Benchmarking

Writing benchmarks in Go is another first-class feature of the language and it is very similar to writing tests.
Expand Down
10 changes: 0 additions & 10 deletions for/v4/repeat.go

This file was deleted.

12 changes: 0 additions & 12 deletions for/v4/repeat_test.go

This file was deleted.

79 changes: 79 additions & 0 deletions hello-world/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,85 @@ Constants should improve performance of your application as it saves you creatin

To be clear, the performance boost is incredibly negligible for this example! But it's worth thinking about creating constants to capture the meaning of values and sometimes to aid performance.

## Hello, world... again

The next requirement is when our function is called with am emprt string it defaults to printing "Hello, world", rather than "Hello, "

Start by writing a new failing test

```go
func TestHello(t *testing.T) {

t.Run("saying hello to people", func(t *testing.T) {
message := Hello("Chris")
expected := "Hello, Chris"

if message != expected {
t.Errorf("expected '%s' but got '%s'", expected, message)
}
})

t.Run("say hello world when an empty string is supplied", func(t *testing.T) {
message := Hello("")
expected := "Hello, World"

if message != expected {
t.Errorf("expected '%s' but got '%s'", expected, message)
}
})

}
```

Here we are introducing another tool in our testing arsenal, subtests. Sometimes it is useful to group tests around a "thing" and then have subtests describing different scenarios.

A benefit of this approach is you can set up shared code that can be used in the other tests.

You can see some repetition here in our assertion as to whether the message we got is the same as the message we expect.

Refactoring is not _just_ for the production code! We can and should refactor our tests.

```go
func TestHello(t *testing.T) {

assertCorrectMessage := func(expected, actual string) {
if expected != actual {
t.Errorf("expected '%s' but got '%s'", expected, actual)
}
}

t.Run("saying hello to people", func(t *testing.T) {
message := Hello("Chris")
expected := "Hello, Chris"
assertCorrectMessage(expected, message)
})

t.Run("say hello world when an empty string is supplied", func(t *testing.T) {
message := Hello("")
expected := "Hello, World"
assertCorrectMessage(expected, message)
})

}
```

What have we done here? In Go functions are _first class_, which means we can assign them as variables. We have refactored our assertion code into a function, which we can then re-use across our subtests.

This reduces duplication and improves readability of our tests.

Now that we have a well-written failing test, let's fix the code, using the `else` keyword.

```go
const helloPrefix = "Hello, "

func Hello(name string) string {
if name == "" {
name = "World"
}
return helloPrefix + name
}
```

### Discipline

On the face of it, the cycle of writing a test, failing the compiler, making the code pass and then refactoring may seem tedious but sticking to the feedback loop is important.
Expand Down
16 changes: 16 additions & 0 deletions hello-world/v5/hello.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import "fmt"

const helloPrefix = "Hello, "

func Hello(name string) string {
if name == "" {
name = "World"
}
return helloPrefix + name
}

func main() {
fmt.Println(Hello("world"))
}
25 changes: 25 additions & 0 deletions hello-world/v5/hello_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import "testing"

func TestHello(t *testing.T) {

assertCorrectMessage := func(expected, actual string) {
if expected != actual {
t.Errorf("expected '%s' but got '%s'", expected, actual)
}
}

t.Run("saying hello to people", func(t *testing.T) {
message := Hello("Chris")
expected := "Hello, Chris"
assertCorrectMessage(expected, message)
})

t.Run("say hello world when an empty string is supplied", func(t *testing.T) {
message := Hello("")
expected := "Hello, World"
assertCorrectMessage(expected, message)
})

}
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Taking my experience of learning with a group and my own personal way I am going
### Table of contents

0. todo: Install Go, set up environment for productivity.
1. [Hello, world](/hello-world) - Declaring variables, constants, if statements, write your first go program and write your first test.
1. [Hello, world](/hello-world) - Declaring variables, constants, if/else statements, write your first go program and write your first test. Sub-test syntax and first class functions.
2. [Integers](/integers) - Further Explore function declaration syntax and learn new ways to improve the documentation of your code.
3. [Iteration](/for) - Learn about `for` and benchmarking.

Expand Down

0 comments on commit 3bf3041

Please sign in to comment.