Loading...
Loading...
Compare original and translation side by side
Ensures high code quality and reliability. Tests are self-documenting, reducing cognitive load for reviewers and maintainers.
Uniform structure across tests ensures predictable, familiar code that team members can navigate efficiently.
Table-driven and data-driven approaches minimize boilerplate code when adding new test cases, making it simple to expand coverage.
Scoped traces and detailed assertion messages pinpoint failures quickly during continuous integration and local testing.
确保高代码质量和可靠性。测试具备自文档性,降低评审人员和维护人员的认知负担。
测试采用统一结构,代码可预测且易于理解,团队成员能高效浏览。
表格驱动和数据驱动方法在添加新测试用例时最大限度减少样板代码,便于扩展测试覆盖率。
范围化的跟踪信息和详细的断言消息能在持续集成和本地测试中快速定位故障。
Defines the input parameters or conditions for the test.
Captures the actual output or result produced by the code under test.
Specifies the expected output or result that the test is verifying against.
定义测试的输入参数或条件。
捕获被测代码产生的实际输出或结果。
指定测试要验证的预期输出或结果。
Each row in the table represents a distinct test case with its own set of inputs and expected outputs.
The test framework iterates over each row, executing the same test logic with different data.
表格中的每一行代表一个独立的测试用例,包含自身的输入和预期输出。
测试框架遍历每一行,使用不同数据执行相同的测试逻辑。
Test data can be stored in external files (e.g., JSON, CSV) and loaded at runtime.
The same test logic can be reused with different datasets, enhancing maintainability and coverage.
测试数据可存储在外部文件(如JSON、CSV)中,并在运行时加载。
同一测试逻辑可与不同数据集复用,提升可维护性和测试覆盖率。
Set up the necessary preconditions and inputs for the test.
Execute the function or method being tested.
Verify that the actual output matches the expected output.
设置测试所需的前置条件和输入。
执行被测函数或方法。
验证实际输出是否与预期输出匹配。
Initialize common objects or state needed for multiple tests.
Clean up resources or reset state after each test.
初始化多个测试所需的通用对象或状态。
在每个测试完成后清理资源或重置状态。
pkg/internal/pkg/<package>/<file>.gopkg/<package>/<file>_test.gopkg/internal/pkg/<package>/<file>.gopkg/<package>/<file>_test.go| Command | Description |
|---|---|
| Execute tests with race detection and JUnit report |
| Generate coverage reports (HTML and XML) |
| 命令 | 描述 |
|---|---|
| 启用竞争检测并生成JUnit报告的测试执行命令 |
| 生成覆盖率报告(HTML和XML格式) |
Use the standard Gopackage.testing
Includeandtestingfor comparisons.github.com/google/go-cmp/cmp
Useto run tests in parallel.t.Parallel()
Consolidate test cases for a single function into onefunction using table-driven testing.TestXxx(t *testing.T)
Usefor value comparisons andcmp.Equalfor error checking.errors.Is
使用Go标准包。testing
导入和testing用于值比较。github.com/google/go-cmp/cmp
使用实现测试并行运行。t.Parallel()
使用表格驱动测试,将单个函数的所有测试用例整合到一个函数中。TestXxx(t *testing.T)
使用进行值比较,使用cmp.Equal进行错误检查。errors.Is
// SPDX-License-Identifier: Apache-2.0
package <package>
import (
"errors"
"testing"
"github.com/google/go-cmp/cmp"
)// SPDX-License-Identifier: Apache-2.0
package <package>
import (
"errors"
"testing"
"github.com/google/go-cmp/cmp"
)func Test<FunctionName>(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
/* input fields */
}
type want struct {
/* expected output fields */
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "case-description-1",
in: in{
/* input values */
},
want: want{
/* expected output */
err: nil,
},
},
{
name: "case-description-2",
in: in{
/* input values */
},
want: want{
/* expected output */
err: nil, // or specific error
},
},
// add more cases as needed
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// additional setup as needed
// Act
got, err := <Function>(tt.in.<input>)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
if !cmp.Equal(got, tt.want.<value>) {
t.Errorf("<Function>(%+v) = %v, want %v", tt.in, got, tt.want.<value>)
}
})
}
}func Test<FunctionName>(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
/* input fields */
}
type want struct {
/* expected output fields */
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "case-description-1",
in: in{
/* input values */
},
want: want{
/* expected output */
err: nil,
},
},
{
name: "case-description-2",
in: in{
/* input values */
},
want: want{
/* expected output */
err: nil, // or specific error
},
},
// add more cases as needed
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// additional setup as needed
// Act
got, err := <Function>(tt.in.<input>)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
if !cmp.Equal(got, tt.want.<value>) {
t.Errorf("<Function>(%+v) = %v, want %v", tt.in, got, tt.want.<value>)
}
})
}
}// testFixture holds common test state and provides setup/teardown.
type testFixture struct {
t *testing.T
// Add common fields for test state
object *<Type>
}
// newTestFixture creates and initializes a test fixture.
func newTestFixture(t *testing.T) *testFixture {
t.Helper()
// Setup
return &testFixture{
t: t,
object: New<Type>(),
}
}
// teardown cleans up resources after test completion.
func (f *testFixture) teardown() {
f.t.Helper()
// Teardown
if f.object != nil {
f.object.Close()
}
}
func Test<FunctionName>WithFixture(t *testing.T) {
t.Parallel()
// Arrange
f := newTestFixture(t)
defer f.teardown()
input := <input_value>
// Act
got, err := f.object.<Function>(input)
// Assert
if err != nil {
t.Errorf("<Function>() unexpected error: %v", err)
}
if !cmp.Equal(got, <expected>) {
t.Errorf("<Function>() = %v, want %v", got, <expected>)
}
}// testFixture holds common test state and provides setup/teardown.
type testFixture struct {
t *testing.T
// Add common fields for test state
object *<Type>
}
// newTestFixture creates and initializes a test fixture.
func newTestFixture(t *testing.T) *testFixture {
t.Helper()
// Setup
return &testFixture{
t: t,
object: New<Type>(),
}
}
// teardown cleans up resources after test completion.
func (f *testFixture) teardown() {
f.t.Helper()
// Teardown
if f.object != nil {
f.object.Close()
}
}
func Test<FunctionName>WithFixture(t *testing.T) {
t.Parallel()
// Arrange
f := newTestFixture(t)
defer f.teardown()
input := <input_value>
// Act
got, err := f.object.<Function>(input)
// Assert
if err != nil {
t.Errorf("<Function>() unexpected error: %v", err)
}
if !cmp.Equal(got, <expected>) {
t.Errorf("<Function>() = %v, want %v", got, <expected>)
}
}func Test<FunctionName>Error(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
/* invalid input fields */
}
type want struct {
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "nil-input-returns-error",
in: in{
/* nil or invalid input */
},
want: want{
err: resource.Err<ErrorName>,
},
},
{
name: "invalid-value-returns-error",
in: in{
/* invalid value */
},
want: want{
err: resource.Err<ErrorName>,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// setup if needed
// Act
_, err := <Function>(tt.in.<input>)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
})
}
}func Test<FunctionName>Error(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
/* invalid input fields */
}
type want struct {
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "nil-input-returns-error",
in: in{
/* nil or invalid input */
},
want: want{
err: resource.Err<ErrorName>,
},
},
{
name: "invalid-value-returns-error",
in: in{
/* invalid value */
},
want: want{
err: resource.Err<ErrorName>,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// setup if needed
// Act
_, err := <Function>(tt.in.<input>)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
})
}
}func Test<FunctionName>BoundaryValues(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
input <input_type>
}
type want struct {
value <output_type>
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "minimum-value",
in: in{input: <MIN_VALUE>},
want: want{value: /* expected */, err: nil},
},
{
name: "maximum-value",
in: in{input: <MAX_VALUE>},
want: want{value: /* expected */, err: nil},
},
{
name: "zero-value",
in: in{input: 0},
want: want{value: /* expected */, err: nil},
},
{
name: "negative-value",
in: in{input: -1},
want: want{value: /* expected */, err: nil},
},
{
name: "overflow-value",
in: in{input: math.MaxFloat64},
want: want{value: 0, err: resource.ErrOverflow},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// setup if needed
// Act
got, err := <Function>(tt.in.input)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
if !cmp.Equal(got, tt.want.value) {
t.Errorf("<Function>(%v) = %v, want %v", tt.in.input, got, tt.want.value)
}
})
}
}func Test<FunctionName>BoundaryValues(t *testing.T) {
t.Parallel()
// In-Got-Want
type in struct {
input <input_type>
}
type want struct {
value <output_type>
err error
}
// Table-Driven Testing
tests := []struct {
name string
in in
want want
}{
{
name: "minimum-value",
in: in{input: <MIN_VALUE>},
want: want{value: /* expected */, err: nil},
},
{
name: "maximum-value",
in: in{input: <MAX_VALUE>},
want: want{value: /* expected */, err: nil},
},
{
name: "zero-value",
in: in{input: 0},
want: want{value: /* expected */, err: nil},
},
{
name: "negative-value",
in: in{input: -1},
want: want{value: /* expected */, err: nil},
},
{
name: "overflow-value",
in: in{input: math.MaxFloat64},
want: want{value: 0, err: resource.ErrOverflow},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Arrange
// setup if needed
// Act
got, err := <Function>(tt.in.input)
// Assert
if !errors.Is(err, tt.want.err) {
t.Errorf("<Function>() error = %v, want err %v", err, tt.want.err)
}
if !cmp.Equal(got, tt.want.value) {
t.Errorf("<Function>(%v) = %v, want %v", tt.in.input, got, tt.want.value)
}
})
}
}import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
)
// testCase represents a single test case loaded from JSON.
type testCase struct {
Name string `json:"name"`
In struct {
Input <input_type> `json:"input"`
} `json:"in"`
Want struct {
Expected <output_type> `json:"expected"`
} `json:"want"`
}
// testData represents the JSON test data structure.
type testData struct {
Tests []testCase `json:"tests"`
}
func Test<FunctionName>DataDriven(t *testing.T) {
t.Parallel()
// Load test data from JSON file
testdataPath := filepath.Join("testdata", "<function>_test.json")
data, err := os.ReadFile(testdataPath)
if err != nil {
t.Fatalf("failed to read test data: %v", err)
}
var td testData
if err := json.Unmarshal(data, &td); err != nil {
t.Fatalf("failed to parse test data: %v", err)
}
for _, tc := range td.Tests {
t.Run(tc.Name, func(t *testing.T) {
// Arrange
input := tc.In.Input
expected := tc.Want.Expected
// Act
got, err := <Function>(input)
// Assert
if err != nil {
t.Errorf("<Function>() unexpected error: %v", err)
}
if !cmp.Equal(got, expected) {
t.Errorf("<Function>(%v) = %v, want %v", input, got, expected)
}
})
}
}tests/data/<function>_test.jsonJSON file containing test cases.
{
"tests": [
{
"name": "case-description-1",
"in": {
"input": <value>
},
"want": {
"expected": <value>
}
},
{
"name": "case-description-2",
"in": {
"input": <value>
},
"want": {
"expected": <value>
}
}
]
}import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
)
// testCase represents a single test case loaded from JSON.
type testCase struct {
Name string `json:"name"`
In struct {
Input <input_type> `json:"input"`
} `json:"in"`
Want struct {
Expected <output_type> `json:"expected"`
} `json:"want"`
}
// testData represents the JSON test data structure.
type testData struct {
Tests []testCase `json:"tests"`
}
func Test<FunctionName>DataDriven(t *testing.T) {
t.Parallel()
// Load test data from JSON file
testdataPath := filepath.Join("testdata", "<function>_test.json")
data, err := os.ReadFile(testdataPath)
if err != nil {
t.Fatalf("failed to read test data: %v", err)
}
var td testData
if err := json.Unmarshal(data, &td); err != nil {
t.Fatalf("failed to parse test data: %v", err)
}
for _, tc := range td.Tests {
t.Run(tc.Name, func(t *testing.T) {
// Arrange
input := tc.In.Input
expected := tc.Want.Expected
// Act
got, err := <Function>(input)
// Assert
if err != nil {
t.Errorf("<Function>() unexpected error: %v", err)
}
if !cmp.Equal(got, expected) {
t.Errorf("<Function>(%v) = %v, want %v", input, got, expected)
}
})
}
}tests/data/<function>_test.json包含测试用例的JSON文件。
{
"tests": [
{
"name": "case-description-1",
"in": {
"input": <value>
},
"want": {
"expected": <value>
}
},
{
"name": "case-description-2",
"in": {
"input": <value>
},
"want": {
"expected": <value>
}
}
]
}