Adding structs and interfaces
parent
eeef9622df
commit
3686956a02
@ -0,0 +1,7 @@
|
||||
# Testing Structs
|
||||
|
||||
You can run individual tests like:
|
||||
|
||||
```
|
||||
go test -run TestArea/Rectangle
|
||||
```
|
@ -0,0 +1,3 @@
|
||||
module structs
|
||||
|
||||
go 1.21.0
|
@ -0,0 +1,49 @@
|
||||
package structs
|
||||
|
||||
import "math"
|
||||
|
||||
// In Go interface resolution is implicit. So Rectangle and Cirle have
|
||||
// receiver functions that satisfy the Shape interface.
|
||||
type Shape interface {
|
||||
Area() float64
|
||||
}
|
||||
|
||||
type Rectangle struct {
|
||||
Width float64
|
||||
Height float64
|
||||
}
|
||||
|
||||
type Circle struct {
|
||||
Radius float64
|
||||
}
|
||||
|
||||
type Triangle struct {
|
||||
Base float64
|
||||
Height float64
|
||||
}
|
||||
|
||||
// There are examples of functions (not methods)
|
||||
// Perimeter calculates the perimeter of a rectangle
|
||||
func Perimeter(rectangle Rectangle) float64 {
|
||||
return 2 * (rectangle.Width + rectangle.Height)
|
||||
}
|
||||
|
||||
// Area calculates the area of a rectangle
|
||||
func Area(rectangle Rectangle) float64 {
|
||||
return rectangle.Width * rectangle.Height
|
||||
}
|
||||
|
||||
// A method is a function with a receiver. A method declaration binds an identifier,
|
||||
// the method name, to a method, and associates the method with the receiver's base type.
|
||||
func (r Rectangle) Area() float64 {
|
||||
return r.Height * r.Width
|
||||
}
|
||||
|
||||
func (c Circle) Area() float64 {
|
||||
return math.Pow(c.Radius, 2) * math.Pi
|
||||
}
|
||||
|
||||
func (t Triangle) Area() float64 {
|
||||
// return (t.Base * t.Height) / 2
|
||||
return (t.Base * t.Height) * 0.5
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue