Advanced go-testdeep technique

Of course we can test struct fields one by one, but with go-testdeep and the [td package], the whole struct can be compared with one Cmp call.

We can choose to ignore the non-guessable fields set by CreateRecord():

import (
  "testing"
  "time"

  "github.com/maxatome/go-testdeep/td"
)

func TestCreateRecord(t *testing.T) {
  record, err := CreateRecord("Bob", 23)

  if td.CmpNoError(t, err) {
    td.Cmp(t, record,
      td.Struct(
        &Record{
          Name: "Bob",
          Age:  23,
        },
        nil),
      "Newly created record")
  }
}

Test in in playground: https://play.golang.org/p/-HdKRKY7Kbk

The Struct operator, used here, ignores zero fields in its model parameter.

But it is better to check all fields:

import (
  "testing"
  "time"

  "github.com/maxatome/go-testdeep/td"
)

func TestCreateRecord(t *testing.T) {
  before := time.Now().Truncate(time.Second)
  record, err := CreateRecord("Bob", 23)

  if td.CmpNoError(t, err) {
    td.Cmp(t, record,
      td.Struct(
        &Record{
          Name: "Bob",
          Age:  23,
        },
        td.StructFields{
          "Id":        td.NotZero(),
          "CreatedAt": td.Between(before, time.Now()),
        }),
      "Newly created record")
  }
}

Test it in playground: https://play.golang.org/p/PGyi0d3ZXMa

See the use of the Struct operator. It is needed here to overcome the go static typing system and so use other go-testdeep operators for some fields, here NotZero for Id and Between for CreatedAt.

Not only structs can be compared. A lot of operators can be found to cover most (all?) needed tests. See the operators list.

Say CreateRecord() does not set correctly CreatedAt field, then:

go test -run=TestCreateRecord

outputs for last td.Cmp call:

error output

If CreateRecord() had not set correctly Id field, output would have been:

error output

If CreateRecord() had set Name field to “Alice” value instead of expected “Bob”, output would have been:

error output