A table of test cases looped through `t.Run` gives every case its own name in the output, makes adding new cases trivial, and lets you run individual cases with `-run TestX/case_name`.
`@ParameterizedTest` runs the same test with multiple inputs. Use `@CsvSource`, `@MethodSource`, or `@EnumSource` for data. Eliminates copy-paste in test classes.
JUnit 5 is the modern standard. `@Test` marks a method as a test; `Assertions.*` provides the assertion API. `@BeforeEach` runs setup before every test.
Tests live alongside the code they test. `cargo test` runs every `#[test]` function. Use `#[cfg(test)] mod tests` so the test code is compiled out of release builds.
When you extract a verification routine into a helper, call `t.Helper()` so failure messages point to the CALLER line — not the helper line. One line, much better diagnostics.
JUnit 5 + Kotlin: `@ParameterizedTest` runs the same test body with multiple input rows. `@CsvSource` for inline data, `@MethodSource` for complex args.
`BenchmarkXxx(b *testing.B)` functions are run by `go test -bench`. `b.N` is the loop count the framework auto-tunes; report results in ns/op, allocs/op.
`runTest { }` from kotlinx-coroutines-test gives you a virtual time scheduler — `delay(1000)` finishes instantly while preserving ordering. No more flaky 1-second test sleeps.
Tests live in `*_test.go` files alongside the code. Functions named `TestXxx(t *testing.T)` are picked up by `go test`. Use `t.Errorf` for soft fails (continues running), `t.Fatalf` for hard fails.