Table tests run the same check across a short list of input and expected values.

table test A table test stores cases as data, then loops through each case with one shared check.

Table Tests

caseCount
table_tests.go
Replay: real traced execution (multi-file project)
package main

import "fmt"

func double(value int) int {
	return value * 2
}

func main() {
	var caseCount = 3
	cases := []struct {
		input    int
		expected int
	}{
		{1, 2},
		{2, 4},
		{3, 6},
		{4, 8},
	}

	passed := 0
	selected := cases[:caseCount]
	for _, testCase := range selected {
		actual := double(testCase.input)
		if actual == testCase.expected {
			passed++
		}
	}

	allPassed := passed == len(selected)
	fmt.Println("cases=", len(selected))
	fmt.Println("passed=", passed)
	fmt.Println("allPassed=", allPassed)
}
package main

import "fmt"

func double(value int) int {
	return value * 2
}

func main() {
	var caseCount = 2
	cases := []struct {
		input    int
		expected int
	}{
		{1, 2},
		{2, 4},
		{3, 6},
		{4, 8},
	}

	passed := 0
	selected := cases[:caseCount]
	for _, testCase := range selected {
		actual := double(testCase.input)
		if actual == testCase.expected {
			passed++
		}
	}

	allPassed := passed == len(selected)
	fmt.Println("cases=", len(selected))
	fmt.Println("passed=", passed)
	fmt.Println("allPassed=", allPassed)
}
package main

import "fmt"

func double(value int) int {
	return value * 2
}

func main() {
	var caseCount = 4
	cases := []struct {
		input    int
		expected int
	}{
		{1, 2},
		{2, 4},
		{3, 6},
		{4, 8},
	}

	passed := 0
	selected := cases[:caseCount]
	for _, testCase := range selected {
		actual := double(testCase.input)
		if actual == testCase.expected {
			passed++
		}
	}

	allPassed := passed == len(selected)
	fmt.Println("cases=", len(selected))
	fmt.Println("passed=", passed)
	fmt.Println("allPassed=", allPassed)
}
  1. caseCount ← 3, cases ← []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}

    9func main() {10  var caseCount→ 3 = 3 //@caseCount=2, 411  cases→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}} := []struct {12    input    int13    expected int14  }{15    {1, 2},16    {2, 4},17    {3, 6},18    {4, 8},19  }2021  passed→ 0 := 022  selected→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}} := cases[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}[:caseCount3]23  for _, testCase := range selected {
  2. for _, testCase := range selected

    pass 1 of 3
    22selected := cases[:caseCount]23for _, testCasestruct { input int; expected int }{input:1, expected:2} := range selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}} {24  actual := double(testCase.input1)25  if actual == testCase.expected {
    All 3 passes — pass 1 is the card above
    passtestCasetestCase.input
    1struct { input int; expected int }{input:1, expected:2}1
    2struct { input int; expected int }{input:2, expected:4}2
    3struct { input int; expected int }{input:3, expected:6}3
  3. func double(value int) int

    pass 1 of 3
    5func double(value1 int) int {6  return value1 * 27}
    All 3 passes — pass 1 is the card above
    passvalue
    11
    22
    33
  4. actual ← 2

    23for _, testCase := range selected {24  actual→ 2 := double(testCase.input1)25  if actual == testCase.expected {
  5. passed ← 1

    pass 1 of 3
    24actual := double(testCase.input)25if actual2 == testCase.expected2 {26  passed→ 1++27}
    All 3 passes — pass 1 is the card above
    passactualtestCase.expectedpassed
    1220 1
    2441 2
    3662 3
  6. actual ← 4

    23for _, testCase := range selected {24  actual→ 4 := double(testCase.input2)25  if actual == testCase.expected {
  7. actual ← 6

    23for _, testCase := range selected {24  actual→ 6 := double(testCase.input3)25  if actual == testCase.expected {
  8. allPassed ← true

    30  allPassed→ true := passed3 == len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}})31  fmt.Println("cases=", len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}}))32  fmt.Println("passed=", passed3)33  fmt.Println("allPassed=", allPassedtrue)34}
    outputcases= 3
    passed= 3
    allPassed= true
  1. caseCount ← 2, cases ← []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}

    9func main() {10  var caseCount→ 2 = 211  cases→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}} := []struct {12    input    int13    expected int14  }{15    {1, 2},16    {2, 4},17    {3, 6},18    {4, 8},19  }2021  passed→ 0 := 022  selected→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}} := cases[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}[:caseCount2]23  for _, testCase := range selected {
  2. for _, testCase := range selected

    pass 1 of 2
    22selected := cases[:caseCount]23for _, testCasestruct { input int; expected int }{input:1, expected:2} := range selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}} {24  actual := double(testCase.input1)25  if actual == testCase.expected {
  3. func double(value int) int

    pass 1 of 2
    5func double(value1 int) int {6  return value1 * 27}
  4. actual ← 2

    23for _, testCase := range selected {24  actual→ 2 := double(testCase.input1)25  if actual == testCase.expected {
  5. passed ← 1

    pass 1 of 2
    24actual := double(testCase.input)25if actual2 == testCase.expected2 {26  passed→ 1++27}
  6. for _, testCase := range selected

    pass 2 of 2
    22selected := cases[:caseCount]23for _, testCasestruct { input int; expected int }{input:2, expected:4} := range selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}} {24  actual := double(testCase.input2)25  if actual == testCase.expected {
  7. func double(value int) int

    pass 2 of 2
    5func double(value2 int) int {6  return value2 * 27}
  8. actual ← 4

    23for _, testCase := range selected {24  actual→ 4 := double(testCase.input2)25  if actual == testCase.expected {
  9. passed ← 2

    pass 2 of 2
    24actual := double(testCase.input)25if actual4 == testCase.expected4 {26  passed→ 2++27}
  10. allPassed ← true

    30  allPassed→ true := passed2 == len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}})31  fmt.Println("cases=", len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}}))32  fmt.Println("passed=", passed2)33  fmt.Println("allPassed=", allPassedtrue)34}
    outputcases= 2
    passed= 2
    allPassed= true
  1. caseCount ← 4, cases ← []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}

    9func main() {10  var caseCount→ 4 = 411  cases→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}} := []struct {12    input    int13    expected int14  }{15    {1, 2},16    {2, 4},17    {3, 6},18    {4, 8},19  }2021  passed→ 0 := 022  selected→ []struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}} := cases[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}[:caseCount4]23  for _, testCase := range selected {
  2. for _, testCase := range selected

    pass 1 of 4
    22selected := cases[:caseCount]23for _, testCasestruct { input int; expected int }{input:1, expected:2} := range selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}} {24  actual := double(testCase.input1)25  if actual == testCase.expected {
    All 4 passes — pass 1 is the card above
    passtestCasetestCase.input
    1struct { input int; expected int }{input:1, expected:2}1
    2struct { input int; expected int }{input:2, expected:4}2
    3struct { input int; expected int }{input:3, expected:6}3
    4struct { input int; expected int }{input:4, expected:8}4
  3. func double(value int) int

    pass 1 of 4
    5func double(value1 int) int {6  return value1 * 27}
    All 4 passes — pass 1 is the card above
    passvalue
    11
    22
    33
    44
  4. actual ← 2

    23for _, testCase := range selected {24  actual→ 2 := double(testCase.input1)25  if actual == testCase.expected {
  5. passed ← 1

    pass 1 of 4
    24actual := double(testCase.input)25if actual2 == testCase.expected2 {26  passed→ 1++27}
    All 4 passes — pass 1 is the card above
    passactualtestCase.expectedpassed
    1220 1
    2441 2
    3662 3
    4883 4
  6. actual ← 4

    23for _, testCase := range selected {24  actual→ 4 := double(testCase.input2)25  if actual == testCase.expected {
  7. actual ← 6

    23for _, testCase := range selected {24  actual→ 6 := double(testCase.input3)25  if actual == testCase.expected {
  8. actual ← 8

    23for _, testCase := range selected {24  actual→ 8 := double(testCase.input4)25  if actual == testCase.expected {
  9. allPassed ← true

    30  allPassed→ true := passed4 == len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}})31  fmt.Println("cases=", len(selected[]struct { input int; expected int }{struct { input int; expected int }{input:1, expected:2}, struct { input int; expected int }{input:2, expected:4}, struct { input int; expected int }{input:3, expected:6}, struct { input int; expected int }{input:4, expected:8}}))32  fmt.Println("passed=", passed4)33  fmt.Println("allPassed=", allPassedtrue)34}
    outputcases= 4
    passed= 4
    allPassed= true

Loop Through Cases

  1. Each row stores one input and one expected result.
  2. The loop runs the same check for every selected row.
  3. actual comes from calling double.
  4. Matching rows increase passed.
  5. allPassed compares passed rows with selected rows. | Case row | Check | | --- | --- | | {1, 2} | double(1) == 2 | | {2, 4} | double(2) == 4 | | {3, 6} | double(3) == 6 |

Exercise: table_tests.go

Add table rows for a double helper and count how many selected cases pass