Testing checks that code behaves as expected now and after later changes. It also exposes whether code is easy to use, isolate, and adapt, so testability matters alongside finding bugs. Even broad coverage cannot prove a program is bug-free. section 1.1.3 section 2.0
In Go, tests live in *_test.go files as functions named TestX that receive *testing.T. Run them with go test. Use t.Fatalf when a failure makes the rest of that test invalid; use t.Errorf when later checks can still reveal useful failures. A fatal failure stops only its own test function, not other tests. section 2.3 section 2.3.1
Test a URL parser
Call Parse with a URL, stop if parsing returns an error, then compare the returned URL with the expected Scheme, Host, and Path. Test String separately by constructing a URL and checking that it reassembles the original URL string. Failure messages should report both got and want values. section 2.3.1
A test case is a named scenario containing input and expected output. Table-driven tests keep cases in a slice of structs and run shared logic for each row. This reduces duplicated test code, makes new cases cheap to add, and lets a bug become a permanent regression case. section 2.4 section 2.4.1
Listing 2.7 A table-driven test case (url/url_test.go)
var parseTests = []struct { #1
name string #1
uri string #1
want *URL #1
}{
{ #2
name: "full", #2
uri: "https://github.com/inancgumus", #2
want: &URL{ #2
Scheme: "https", #2
Host: "github.com", #2
Path: "inancgumus", #2
}, #2
}, #2
{ #3
name: "without_path", #3
uri: "https://github.com", #3
want: &URL{ #3
Scheme: "https", #3
Host: "github.com", #3
Path: "", #3
}, #3
}, #3
/* many more test cases can be easily added */ #3
} #3
Inspect a compact test-case table: each row pairs a descriptive name and URL input with the expected parsed URL. section 2.4.1
A plain table loop has a trade-off: Fatalf in one case skips all remaining cases, and individual rows cannot be selected with the run flag. Subtests give each case its own *testing.T, so a fatal failure stays local and cases can be addressed independently. section 2.4.4 section 2.5.3
Choose the test level to fit the risk. CLI tests verify user-visible behavior, while unit tests isolate components such as a flag parser for edge cases. Dependencies can be substituted to make units testable; handler tests can invoke an HTTP handler with a request and ResponseRecorder, then inspect status and body. section 5.0 section 5.5 section 8.7.2




















































