package structs import "testing" func TestPerimeter(t *testing.T) { rectangle := Rectangle{10.0, 10.0} got := Perimeter(rectangle) want := 40.0 if got != want { t.Errorf("got %.2f want %.2f", got, want) } } // %.2f is replaced with %g which will print a more precise decimal number in an error message. func TestArea(t *testing.T) { // Helper function checkArea := func(t testing.TB, shape Shape, want float64) { t.Helper() got := shape.Area() if got != want { t.Errorf("got %g want %g", got, want) } } t.Run("area rectangle", func(t *testing.T) { rectangle := Rectangle{12.0, 6.0} checkArea(t, rectangle, 72.0) }) t.Run("area circle", func(t *testing.T) { circle := Circle{10} checkArea(t, circle, 314.1592653589793) }) } // https://go.dev/wiki/TableDrivenTests are useful when you want to build a list of test cases that can be tested in the same manner. // They are a great fit when you wish to test various implementations of an interface, or if the data being passed in to a function has lots of different requirements that need testing. func TestAreaTable(t *testing.T) { // "anonymous struct" areaTests := []struct { name string shape Shape want float64 }{ // example showing named arguments. Arguably it is more readable. {name: "Rectangle", shape: Rectangle{Width: 12, Height: 6}, want: 72.0}, {"Circle", Circle{10}, 314.1592653589793}, {"Triangle", Triangle{12, 6}, 36.0}, } // for _, tt := range areaTests { // got := tt.shape.Area() // if got != tt.want { // // %#v format string will print out our struct with the values in its field // t.Errorf("%#v got %g want %g", tt, got, tt.want) // } //} // Wrap in t.Run for better debug output and test failure identification for _, tt := range areaTests { t.Run(tt.name, func(t *testing.T) { got := tt.shape.Area() if got != tt.want { t.Errorf("%#v got %g want %g", tt, got, tt.want) } }) } }