Standard library
Writing Tests
Node.js's node:test + node:assert compared to Go's testing, Rust's #[test], Swift Testing, and Java's JUnit for table-driven tests.
- Minimum versions
- Node.js ≥ 18.1Go ≥ 1.7Rust ≥ 1.58Swift ≥ 6.0Java ≥ 17
- Verified on
- Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1
Node.js code is an ES module: save it as .mjs or set "type": "module" in package.json.
Node.js and Go both have a built-in test runner, no external package required; Rust does too, with #[test]/cargo test. Node.js's nested t.test() is roughly equivalent to Go's t.Run() for table-driven tests — running the same test case against multiple sets of input. Rust's plain std #[test] has no named subtests like Go/Node — the example below just loops over cases inside one test function. Swift Testing (the newer framework replacing XCTest, bundled with the toolchain since Swift 6.0 rather than a separate package) supports this directly through @Test(arguments:). Java has no standard test runner in the JDK, so the example uses the most common library, JUnit, with @ParameterizedTest + @CsvSource.
Table-driven tests
import { test } from 'node:test'
import assert from 'node:assert/strict'
test('sum', async t => {
const tt = [
{ a: 1, b: 1, ret: 2 },
{ a: 2, b: 3, ret: 5 },
{ a: 5, b: 5, ret: 10 },
]
for (const { a, b, ret } of tt) {
await t.test(`${a} + ${b}`, () => {
assert.equal(sum(a, b), ret)
})
}
})
function sum(a, b) {
return a + b
}package example
import (
"fmt"
"testing"
)
func TestSum(t *testing.T) {
for _, tt := range []struct {
a int
b int
ret int
}{
{1, 1, 2},
{2, 3, 5},
{5, 5, 10},
} {
t.Run(fmt.Sprintf("(%v + %v)", tt.a, tt.b), func(t *testing.T) {
ret := sum(tt.a, tt.b)
if ret != tt.ret {
t.Errorf("want %v, got %v", tt.ret, ret)
}
})
}
}
func sum(a, b int) int {
return a + b
}pub fn sum(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::sum;
#[test]
fn test_sum() {
let cases = [(1, 1, 2), (2, 3, 5), (5, 5, 10)];
for (a, b, want) in cases {
let got = sum(a, b);
assert_eq!(got, want, "sum({a}, {b})"); // the message adds context when the assertion fails
}
}
}// Sources/example/Sum.swift
public func sum(_ a: Int, _ b: Int) -> Int {
a + b
}
// Tests/exampleTests/SumTests.swift
import Testing
@testable import example
@Test("sum", arguments: [(1, 1, 2), (2, 3, 5), (5, 5, 10)])
func testSum(_ testCase: (a: Int, b: Int, want: Int)) {
#expect(sum(testCase.a, testCase.b) == testCase.want)
}import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
// Maven: org.junit.jupiter:junit-jupiter:6.1.3
class SumTest {
@ParameterizedTest(name = "{0} + {1}")
@CsvSource({"1,1,2", "2,3,5", "5,5,10"})
void sum(int a, int b, int want) {
assertEquals(want, Sum.sum(a, b));
}
}
class Sum {
static int sum(int a, int b) {
return a + b;
}
}$ node --test examples/example_test.js
▶ sum
✔ 1 + 1 (0.29ms)
✔ 2 + 3 (0.05ms)
✔ 5 + 5 (0.05ms)
✔ sum (0.87ms)
# trimmed: tests/suites/pass/fail/duration summary lines; durations vary between runs$ go test -v examples/example_test.go
=== RUN TestSum
=== RUN TestSum/(1_+_1)
=== RUN TestSum/(2_+_3)
=== RUN TestSum/(5_+_5)
--- PASS: TestSum (0.00s)
--- PASS: TestSum/(1_+_1) (0.00s)
--- PASS: TestSum/(2_+_3) (0.00s)
--- PASS: TestSum/(5_+_5) (0.00s)
PASS
ok command-line-arguments 0.459s$ cargo test -q
running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s$ swift test
◇ Test "sum" started.
◇ Test case passing 1 argument testCase → (1, 1, 2) to "sum" started.
◇ Test case passing 1 argument testCase → (5, 5, 10) to "sum" started.
◇ Test case passing 1 argument testCase → (2, 3, 5) to "sum" started.
✔ Test "sum" with 3 test cases passed after 0.001 seconds.
✔ Test run with 1 test in 0 suites passed after 0.001 seconds.$ java -jar junit-platform-console-standalone-6.1.3.jar execute -cp out --scan-class-path --details=tree
# trimmed the "Thanks for using JUnit!" banner, the JUnit Platform Suite/JUnit Vintage branches
# (empty, no test runs through them), and the containers/tests found/started/failed summary lines
├─ JUnit Jupiter ✔
│ └─ SumTest ✔
│ └─ sum(int, int, int) ✔
│ ├─ "1" + "1" ✔
│ ├─ "2" + "3" ✔
│ └─ "5" + "5" ✔Reference: github.com/miguelmota/golang-for-nodejs-developers#testing