A release can look ready while leaving QA to rediscover familiar bugs. Testing moves some of that work earlier: define what the software should do, check it automatically, and use failures to guide the next small change. A test case pairs an input or condition with an expected result; together, cases record business expectations as well as catch regressions. section 3.0 section 1.3.2
Start by sketching use cases with a teammate. Then choose a system under test with a clear boundary and check its inputs and outputs rather than its internal steps. A translation API, for example, can be split into a translation service, an HTTP handler, and a server. Smaller boundaries make failures easier to locate. section 3.1 section 3.8
For a translation service, useful cases include:
- Given “hello” and English, return “hello”; given German or Finnish, return “hallo” or “hei.” section 3.3
- Given an unsupported language or a word with no translation, return an empty string. section 3.3
- Given capitalization or extra spaces in the input, return the same translation as for normalized input. section 3.3
Write a case, run it, and let a failure identify the behavior to implement. Once it passes, keep the test while refactoring: it protects the requirement even if the implementation changes. Before changing an expectation to make a test pass, consider whether the business requirement has changed. Test negative paths and edge cases, not only successful requests. section 3.3
Listing 3.5 translator_test.go
package translate_test
import (
"testing"
"github.com/holmes89/hello-api/translation"
)
func TestTranslate(t *testing.T) {
res := translation.Translate("hello", "english") #1
if res != "hello" {
t.Errorf(`expected "hello" but recieved "%s"`, res)
}
res = translation.Translate("hello", "german") #2
if res != "hallo" {
t.Errorf(`expected "hallo" but recieved "%s"`, res)
}
res = translation.Translate("hello", "finnish") #3
if res != "hei" {
t.Errorf(`expected "hei" but received "%s"`, res)
}
res = translation.Translate("hello", "dutch") #4
if res != "" {
t.Errorf(`expected "" but received "%s"`, res)
}
}
A Go test checks several language inputs and reports the expected and actual translation when a case fails. section 3.3
Run fast unit tests as a quality gate before the build. The example CI job runs `go test ./...`, and the build waits for that job. Coverage reports can point to untested branches, but a high percentage cannot prove that behavior matches customer expectations; use coverage to guide additions and refactoring, not as a substitute for meaningful cases. section 3.6 section 3.7
Grow the checks with the product. Unit tests establish a foundation; isolated tests can use injected dependencies, stubs, and mocks, while integration tests check larger services. Acceptance cases ask whether a customer-facing rule holds—for example, whether an insufficient balance produces an error. Broader end-to-end checks assess the whole system but cost more to run and maintain, so begin with core behavior and expand where bugs reveal risk. section 6.0 section 1.3.8 section 1.3.10 section 11.4.2




















































