Testing in Rust: built-in tests for developers used to Go's standard package
Map Go's standard-library testing habits onto Rust's #[test], assertions, and nearby test modules.
by the end of this lesson you can
- →Uses #[test] and assertion macros
- →Keeps multiple cases easy to scan
- →Stays close to Rust's built-in testing style
Overview
Go developers already know a standard-library-first testing culture. Rust feels similar in spirit, but the structure is different: test modules, assertion macros, and stronger integration with the language's type system.
In Go, you often
write tests in _test.go files with explicit case loops and standard-library helpers.
In Rust, the common pattern is
to use #[test], assertion macros, and inline or nearby test modules that stay close to the code they verify.
why this difference matters
This lesson should feel reassuring. Rust testing is explicit in much the same way Go testing is, but the syntax and organization are different.
Go
func TestSquare(t *testing.T) {
if square(4) != 16 {
t.Fatal("bad result")
}
}Rust
#[test]
fn square_returns_16() {
assert_eq!(square(4), 16);
}Deeper comparison
Go version
func TestSlugify(t *testing.T) {
cases := []struct {
in string
want string
}{{"Hello World", "hello-world"}}
for _, tc := range cases {
if got := slugify(tc.in); got != tc.want {
t.Fatalf("got %q, want %q", got, tc.want)
}
}
}Rust version
#[test]
fn slugify_cases() {
let cases = [("Hello World", "hello-world")];
for (input, expected) in cases {
assert_eq!(slugify(input), expected);
}
}Reflect
What feels familiar to a Go developer in Rust testing, and what changes in the way tests are organized?
what a strong answer notices
A strong answer mentions standard-tooling familiarity, explicit cases, and closer integration with modules and macros.
Rewrite
Rewrite this Go table-style test into an idiomatic Rust test.
Rewrite this Go
func TestDouble(t *testing.T) {
cases := []struct{ in, want int }{{2, 4}, {3, 6}}
for _, tc := range cases {
if got := double(tc.in); got != tc.want {
t.Fatalf("got %d, want %d", got, tc.want)
}
}
}what good looks like
- Uses #[test] and assertion macros
- Keeps multiple cases easy to scan
- Stays close to Rust's built-in testing style
Practice
Design a Rust test module for request validation with both valid and invalid cases.
success criteria
- Groups related tests clearly
- Uses assertions that make the intended contract obvious
- Keeps setup explicit rather than overly abstract
Common mistakes
- Expecting _test.go file layout instead of learning Rust's test-module conventions.
- Recreating Go helpers before understanding Rust's simpler built-in patterns.
- Treating macros as magic instead of ordinary testing tools.
takeaways
- ●This lesson should feel reassuring. Rust testing is explicit in much the same way Go testing is, but the syntax and organization are different.
- ●A strong answer mentions standard-tooling familiarity, explicit cases, and closer integration with modules and macros.
- ●Groups related tests clearly