【Golang星辰图】构建健壮应用的秘籍:探索Go语言中最强大的测试工具库

精进单元测试:探秘Go语言中流行的测试框架和工具

前言

提高软件质量和稳定性是每个开发人员的目标之一。而单元测试是保证代码质量的重要手段之一,可以帮助我们检查代码是否按预期工作,并提早发现潜在的bug。Go语言提供了丰富的测试框架和工具,本文将为你介绍Go语言中几个流行的测试框架和工具,帮助你更好地编写单元测试。

欢迎订阅专栏:Golang星辰图

文章目录

  • 精进单元测试:探秘Go语言中流行的测试框架和工具
    • 前言
    • 1. testing库
      • 1.1 基本概述
      • 1.2 测试函数
        • 1.2.1 命名规则
        • 1.2.2 函数签名
      • 1.3 子测试和子测试函数
      • 1.4 示例和基准测试
      • 1.5 测试覆盖率分析
      • 1.6 并发测试
      • 1.7 表格驱动测试
      • 1.8 Mock测试
    • 2. testify库
      • 2.1 基本概述
      • 2.2 测试函数
        • 2.2.1 命名规则
        • 2.2.2 函数签名
      • 2.3 子测试和子测试函数
      • 2.4 示例和基准测试
      • 2.5 测试覆盖率分析
      • 2.6 并发测试
      • 2.7 表格驱动测试
      • 2.8 Mock测试
    • 3. ginkgo库
      • 3.1 基本概述
      • 3.2 测试函数
        • 3.2.1 命名规则
        • 3.2.2 函数签名
      • 3.3 子测试和子测试函数
      • 3.4 示例和基准测试
      • 3.5 测试覆盖率分析
      • 3.6 并发测试
      • 3.7 表格驱动测试
      • 3.8 Mock测试
    • 4. gocheck库
      • 4.1 基本概述
      • 4.2 测试函数
        • 4.2.1 命名规则
        • 4.2.2 函数签名
      • 4.3 子测试和子测试函数
      • 4.4 Suite和SuiteSetUp
      • 4.5 跳过测试
      • 4.6 测试覆盖率
    • 5. gomega库
      • 5.1 基本概述
      • 5.2 安装
      • 5.3 使用
      • 5.4 匹配器
      • 5.5 自定义匹配器
    • 6. goconvey库
      • 6.1 基本概述
      • 6.2 安装
      • 6.3 使用
      • 6.4 辅助函数
      • 6.5 配置
    • 总结

1. testing库

testing 是 Go 语言标准库中的测试框架,提供了基本的测试功能,包括测试函数、子测试和子测试函数、示例和基准测试、测试覆盖率分析、并发测试、表格驱动测试和 Mock 测试等。

1.1 基本概述

testing 库是 Go 语言标准库中的测试框架,用于对 Go 代码进行自动化测试。testing 库提供了一系列的测试函数,用于测试代码的正确性和性能。测试函数通常以 Test 开头,接受一个 *testing.T 类型的参数,用于报告测试结果和错误信息。

以下是一个简单的测试函数示例:

package mainimport ("testing"
)func TestAdd(t *testing.T) {got := Add(2, 3)want := 5if got != want {t.Errorf("got %d, want %d", got, want)}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们测试了 Add 函数的正确性。测试函数 TestAdd 接受一个 *testing.T 类型的参数,用于报告测试结果。我们通过 gotwant 两个变量来比较期望值和实际值,如果两者不相等,则调用 t.Errorf 函数报告错误信息。

1.2 测试函数

1.2.1 命名规则

测试函数必须以 Test 开头,接受一个 *testing.T 类型的参数,并且不能有任何返回值。测试函数必须放在要测试的包的 _test.go 文件中,否则不会被测试框架识别。

1.2.2 函数签名

测试函数的函数签名如下:

func TestName(t *testing.T)

其中,Name 是测试函数的名称,通常为要测试的函数或方法的名称。t 是一个指向 testing.T 类型的指针,用于报告测试结果和错误信息。

1.3 子测试和子测试函数

子测试和子测试函数是 testing 库中的高级测试功能,用于对测试用例进行分组和子分组,以更好地组织和管理测试代码。子测试函数可以嵌套在其他子测试函数中,形成一个树状结构。子测试和子测试函数可以共享测试数据和测试逻辑,提高测试代码的复用性和可维护性。

以下是一个子测试函数示例:

package mainimport ("testing""testing/quick"
)func TestAdd(t *testing.T) {t.Run("normal case", func(t *testing.T) {got := Add(2, 3)want := 5if got != want {t.Errorf("got %d, want %d", got, want)}})t.Run("edge case", func(t *testing.T) {got := Add(0, 0)want := 0if got != want {t.Errorf("got %d, want %d", got, want)}})t.Run("property testing", func(t *testing.T) {f := func(x, y int) bool {return Add(x, y) == x+y}if err := quick.Check(f, nil); err != nil {t.Error(err)}})
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 t.Run 函数定义了三个子测试函数,分别测试了 Add 函数的正常情况、边界情况和属性测试。每个子测试函数都接受一个 *testing.T 类型的参数,用于报���测试结果和错误信息。子测试函数可以嵌套在其他子测试函数中,形成一个树状结构。

1.4 示例和基准测试

示例和基准测试是 testing 库中的高级测试功能,用于展示函数的使用方法和测试函数的性能。示例函数以 Example 开头,接受一个 *testing.T 类型的参数,用于展示函数的使用方法。基准测试函数以 Benchmark 开头,接受一个 *testing.B 类型的参数,用于测试函数的性能。

以下是一个示例函数示例:

package mainimport ("fmt""testing"
)func ExampleAdd() {got := Add(2, 3)fmt.Println(got)// Output: 5
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 ExampleAdd 函数展示了 Add 函数的使用方法。示例函数以 Example 开头,接受一个 *testing.T 类型的参数,用于展示函数的使用方法。示例函数的输出会被测试框架捕获并打印到控制台上。

以下是一个基准测试函数示例:

package mainimport ("testing"
)func BenchmarkAdd(b *testing.B) {for i := 0; i < b.N; i++ {Add(2, 3)}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 BenchmarkAdd 函数测试了 Add 函数的性能。基准测试函数以 Benchmark 开头,接受一个 *testing.B 类型的参数,用于测试函数的性能。基准测试函数会运行多次,以获取平均性能数据。

1.5 测试覆盖率分析

测试覆盖率分析是测试过程中非常重要的环节,用于评估测试用例的质量和测试代码的完整性。testing 库提供了 go test -cover 命令来进行测试覆盖率分析,该命令会输出被测试代码的覆盖率数据。

以下是一个测试覆盖率分析示例:

package mainimport ("testing"
)func TestAdd(t *testing.T) {got := Add(2, 3)want := 5if got != want {t.Errorf("got %d, want %d", got, want)}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 go test -cover 命令进行测试覆盖率分析。测试覆盖率分析结果如下:

$ go test -cover
PASS
coverage: 100.0% of statements
ok      github.com/username/project  0.002s

从结果可以看出,被测试代码的覆盖率为 100%,说明测试用例的质量较好,测试代码的完整性较高。

1.6 并发测试

并发测试是 testing 库中的高级测试功能,用于测试并发代码的正确性和性能。testing 库提供了 t.Parallel() 函数来启用并发测试,该函数会告诉测试框架可以并发运行测试用例。

以下是一个并发测试示例:

package mainimport ("sync""testing"
)func TestCounter(t *testing.T) {t.Parallel()counter := NewCounter()var wg sync.WaitGroupwg.Add(2)go func() {defer wg.Done()counter.Inc()}()go func() {defer wg.Done()counter.Inc()}()wg.Wait()got := counter.Value()want := 2if got != want {t.Errorf("got %d, want %d", got, want)}
}type Counter struct {value intmutex sync.Mutex
}func NewCounter() *Counter {return &Counter{}
}func (c *Counter) Inc() {c.mutex.Lock()defer c.mutex.Unlock()c.value++
}func (c *Counter) Value() int {c.mutex.Lock()defer c.mutex.Unlock()return c.value
}

在这个示例中,我们使用了 t.Parallel() 函数启用了并发测试。我们测试了一个并发计数器的正确性,该计数器使用了 sync.Mutex 来保证线程安全。在测试函数中,我们使用了 sync.WaitGroup 来等待所有 Goroutine 运行完毕。

1.7 表格驱动测试

表格驱动测试是 testing 库中的高级测试功能,用于对多组测试用例进行批量测试。表格驱动测试可以大大简化测试代码,提高测试代码的复用性和可维护性。

以下是一个表格驱动测试示例:

package mainimport ("testing"
)func TestAdd(t *testing.T) {cases := []struct {x, y, want int}{{2, 3, 5},{0, 0, 0},{-1, 1, 0},}for _, c := range cases {got := Add(c.x, c.y)if got != c.want {t.Errorf("got %d, want %d", got, c.want)}}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了表格驱动测试对 Add 函数进行了批量测试。我们定义了一个包含多组测试用例的结构体数组,每个测试用例都包含了 xywant 三个字段。在测试函数中,我们遍历了所有的测试用例,并对每个测试用例进行了测试。

1.8 Mock测试

Mock 测试是 testing 库中的高级测试功能,用于模拟依赖组件的行为,以隔离被测试代码。Mock 测试可以大大提高测试代码的可靠性和可维护性。

以下是一个 Mock 测试示例:

package mainimport ("testing""github.com/stretchr/testify/mock"
)type UserService interface {GetUser(id int) (*User, error)
}type User struct {ID   intName string
}type UserController struct {UserService UserService
}func (c *UserController) GetUser(id int) (*User, error) {return c.UserService.GetUser(id)
}type MockUserService struct {mock.Mock
}func (m *MockUserService) GetUser(id int) (*User, error) {args := m.Called(id)return args.Get(0).(*User), args.Error(1)
}func TestUserController_GetUser(t *testing.T) {userService := new(MockUserService)userService.On("GetUser", 1).Return(&User{ID: 1, Name: "Tom"}, nil)controller := &UserController{UserService: userService}user, err := controller.GetUser(1)if err != nil {t.Fatal(err)}if user.Name != "Tom" {t.Errorf("got %s, want Tom", user.Name)}userService.AssertExpectations(t)
}

在这个示例中,我们使用了 Mock 测试对 UserController 进行了测试。我们定义了一个 UserService 接口,用于模拟用户服务的行为。我们还定义了一个 MockUserService 结构体,用于实现 UserService 接口,并使用 testify/mock 库来模拟 UserService 的行为。在测试函数中,我们使用了 MockUserService 来模拟用户服务的行为,并对 UserController 进行了测试。

2. testify库

testify 是 Go 语言中最常用的测试库之一,提供了丰富的断言函数、模拟对象和测试套件等测试功能。testify 库的设计目标是提供一套简单易用、功能强大、可扩展性好的测试工具,以帮助开发者更高效地进行单元测试和集成测试。

2.1 基本概述

testify 库是一个第三方的 Go 测试库,用于对 Go 代码进行自动化测试。testify 库提供了一系列的测试工具,包括断言函数、模拟对象和测试套件等,用于帮助开发者更高效地进行单元测试和集成测试。

2.2 测试函数

2.2.1 命名规则

testify 库中的测试函数命名规则与 testing 库中的测试函数命名规则类似,必须以 Test 开头,接受一个 *testing.T 类型的参数,并且不能有任何返回值。测试函数必须放在要测试的包的 _test.go 文件中,否则不会被测试框架识别。

2.2.2 函数签名

testify 库中的测试函数的函数签名如下:

func TestName(t *testing.T)

其中,Name 是测试函数的名称,通常为要测试的函数或方法的名称。t 是一个指向 testing.T 类型的指针,用于报告测试结果和错误信息。

2.3 子测试和子测试函数

testify 库中的子测试和子测试函数与 testing 库中的子测试和子测试函数类似,用于对测试用例进行分组和子分组,以更好地组织和管理测试代码。子测试函数可以嵌套在其他子测试函数中,形成一个树状结构。子测试和子测试函数可以共享测试数据和测试逻辑,提高测试代码的复用性和可维护性。

以下是一个子测试函数示例:

package mainimport ("testing""github.com/stretchr/testify/suite"
)type MyTestSuite struct {suite.Suite
}func (s *MyTestSuite) TestAdd() {s.Run("normal case", func() {got := Add(2, 3)want := 5s.Equal(got, want)})s.Run("edge case", func() {got := Add(0, 0)want := 0s.Equal(got, want)})
}func TestMyTestSuite(t *testing.T) {suite.Run(t, new(MyTestSuite))
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 suite.Suite 类型来定义一个测试套件,并在测试套件中定义了一个 TestAdd 测试函数。在 TestAdd 测试函数中,我们使用了 s.Run 函数定义了两个子测试函数,分别测试了 Add 函数的正常情况和边界情况。每个子测试函数都接受一个闭包函数,用于测试具体的测试用例。在子测试函数中,我们使用了 s.Equal 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。最后,我们使用了 suite.Run 函数来运行测试套件。

2.4 示例和基准测试

testify 库中的示例和基准测试与 testing 库中的示例和基准测试类似,用于展示函数的使用方法和测试函数的性能。示例函数以 Example 开头,接受一个 *testing.T 类型的参数,用于展示函数的使用方法。基准测试函数以 Benchmark 开头,接受一个 *testing.B 类型的参数,用于测试函数的性能。

以下是一个示例函数示例:

package mainimport ("testing""github.com/stretchr/testify/assert"
)func ExampleAdd() {got := Add(2, 3)assert.Equal(t, got, 5)// Output:// 5
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 assert.Equal 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。示例函数的输出会被测试框架捕获并打印到控制台上。

以下是一个基准测试函数示例:

package mainimport ("testing""github.com/stretchr/testify/require"
)func BenchmarkAdd(b *testing.B) {for i := 0; i < b.N; i++ {require.Equal(t, Add(2, 3), 5)}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 require.Equal 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。基准测试函数会运行多次,以获取平均性能数据。

2.5 测试覆盖率分析

testify 库中的测试覆盖率分析与 testing 库中的测试覆盖率分析类似,用于评估测试用例的质量和测试代码的完整性。testify 库提供了 go test -cover 命令来进行测试覆盖率分析,该命令会输出被测试代码的覆盖率数据。

以下是一个测试覆盖率分析示例:

package mainimport ("testing""github.com/stretchr/testify/assert"
)func TestAdd(t *testing.T) {got := Add(2, 3)assert.Equal(t, got, 5)
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 assert.Equal 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。我们使用了 go test -cover 命令进行测试覆盖率分析。测试覆盖率分析结果如下:

$ go test -cover
PASS
coverage: 100.0% of statements
ok      github.com/username/project  0.002s

从结果可以看出,被测试代码的覆盖率为 100%,说明测试用例的质量较好,测试代码的完整性较高。

2.6 并发测试

testify 库中的并发测试与 testing 库中的并发测试类似,用于测试并发代码的正确性和性能。testify 库提供了 t.Parallel() 函数来启用并发测试,该函数会告诉测试框架可以并发运行测试用例。

以下是一个并发测试示例:

package mainimport ("sync""testing""github.com/stretchr/testify/assert"
)func TestCounter(t *testing.T) {t.Parallel()counter := NewCounter()var wg sync.WaitGroupwg.Add(2)go func() {defer wg.Done()counter.Inc()}()go func() {defer wg.Done()counter.Inc()}()wg.Wait()got := counter.Value()want := 2assert.Equal(t, got, want)
}type Counter struct {value intmutex sync.Mutex
}func NewCounter() *Counter {return &Counter{}
}func (c *Counter) Inc() {c.mutex.Lock()defer c.mutex.Unlock()c.value++
}func (c *Counter) Value() int {c.mutex.Lock()defer c.mutex.Unlock()return c.value
}

在这个示例中,我们使用了 t.Parallel() 函数启用了并发测试。我们测试了一个并发计数器的正确性,该计数器使用了 sync.Mutex 来保证线程安全。在测试函数中,我们使用了 sync.WaitGroup 来等待所有 Goroutine 运行完毕。

2.7 表格驱动测试

testify 库中的表格驱动测试与 testing 库中的表格驱动测试类似,用于对多组测试用例进行批量测试。表格驱动测试可以大大简化测试代码,提高测试代码的复用性和可维护性。

以下是一个表格驱动测试示例:

package mainimport ("testing""github.com/stretchr/testify/assert"
)func TestAdd(t *testing.T) {cases := []struct {x, y, want int}{{2, 3, 5},{0, 0, 0},{-1, 1, 0},}for _, c := range cases {got := Add(c.x, c.y)assert.Equal(t, got, c.want)}
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了表格驱动测试对 Add 函数进行了批量测试。我们定义了一个包含多组测试用例的结构体数组,每个测试用例都包含了 xywant 三个字段。在测试函数中,我们遍历了所有的测试用例,并对每个测试用例进行了测试。

2.8 Mock测试

testify 库中的 Mock 测试与 testing 库中的 Mock 测试类似,用于模拟依赖组件的行为,以隔离被测试代码。testify 库提供了一个名为 mock 的子包,用于创建和管理模拟对象。

以下是一个 Mock 测试示例:

package mainimport ("testing""github.com/stretchr/testify/assert""github.com/stretchr/testify/mock"
)type UserService interface {GetUser(id int) (*User, error)
}type User struct {ID   intName string
}type UserController struct {UserService UserService
}func (c *UserController) GetUser(id int) (*User, error) {return c.UserService.GetUser(id)
}type MockUserService struct {mock.Mock
}func (m *MockUserService) GetUser(id int) (*User, error) {args := m.Called(id)return args.Get(0).(*User), args.Error(1)
}func TestUserController_GetUser(t *testing.T) {userService := new(MockUserService)userService.On("GetUser", 1).Return(&User{ID: 1, Name: "Tom"}, nil)controller := &UserController{UserService: userService}user, err := controller.GetUser(1)assert.NoError(t, err)assert.Equal(t, user.Name, "Tom")userService.AssertExpectations(t)
}

在这个示例中,我们使用了 mock 子包来创建和管理模拟对象。我们定义了一个 UserService 接口,用于模拟用户服务的行为。我们还定义了一个 MockUserService 结构体,用于实现 UserService 接口,并使用 mock 子包来模拟 UserService 的行为。在测试函数中,我们使用了 MockUserService 来模拟用户服务的行为,并对 UserController 进行了测试。

3. ginkgo库

ginkgo 是一个用于 Go 语言的行为驱动开发(BDD)测试框架,提供了一套简单易用、功能强大、可扩展性好的测试工具,用于帮助开发者更高效地进行单元测试和集成测试。ginkgo 库的设计目标是提供一套更加自然、直观、易于理解的测试语言,以帮助开发者更好地表达测试用例的意图和期望。

3.1 基本概述

ginkgo 库是一个第三方的 Go 测试库,用于对 Go 代码进行自动化测试。ginkgo 库提供了一系列的测试工具,包括描述(Describe)、上下文(Context)、它(It)、指定(Specify)等,用于帮助开发者更好地组织和管理测试代码。

3.2 测试函数

3.2.1 命名规则

ginkgo 库中的测试函数命名规则与 testing 库中的测试函数命名规则类似,必须以 Test 开头,接受一个 *testing.T 类型的参数,并且不能有任何返回值。测试函数必须放在要测试的包的 _test.go 文件中,否则不会被测试框架识别。

3.2.2 函数签名

ginkgo 库中的测试函数的函数签名如下:

func TestName(t *testing.T)

其中,Name 是测试函数的名称,通常为要测试的函数或方法的名称。t 是一个指向 testing.T 类型的指针,用于报告测试结果和错误信息。

3.3 子测试和子测试函数

ginkgo 库中的子测试和子测试函数与 testing 库中的子测试和子测试函数类似,用于对测试用例进行分组和子分组,以更好地组织和管理测试代码。子测试函数可以嵌套在其他子测试函数中,形成一个树状结构。子测试和子测试函数可以共享测试数据和测试逻辑,提高测试代码的复用性和可维护性。

以下是一个子测试函数示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Add", func() {Context("normal case", func() {It("should return 5", func() {got := Add(2, 3)want := 5Expect(got).To(Equal(want))})})Context("edge case", func() {It("should return 0", func() {got := Add(0, 0)want := 0Expect(got).To(Equal(want))})})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 Describe 函数来定义一个测试套件,并在测试套件中定义了两个子测试函数,分别测试了 Add 函数的正常情况和边界情况。每个子测试函数都接受一个闭包函数,用于测试具体的测试用例。在子测试函数中,我们使用了 Expect 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。最后,我们使用了 RunSpecs 函数来运行测试套件。

3.4 示例和基准测试

ginkgo 库中的示例和基准测试与 testing 库中的示例和基准测试类似,用于展示函数的使用方法和测试函数的性能。示例函数以 Example 开头,接受一个 *testing.T 类型的参数,用于展示函数的使用方法。基准测试函数以 Benchmark 开头,接受一个 *testing.B 类型的参数,用于测试函数的性能。

以下是一个示例函数示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Add", func() {It("should return 5", func() {got := Add(2, 3)want := 5Expect(got).To(Equal(want))})Context("example", func() {It("should return 5", func() {got := Add(2, 3)Expect(got).To(Equal(5))// Output:// 5})})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 Expect 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。示例函数的输出会被测试框架捕获并打印到控制台上。

以下是一个基准测试函数示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Add", func() {It("should return 5", func() {got := Add(2, 3)want := 5Expect(got).To(Equal(want))})Context("benchmark", func() {It("should benchmark Add function", func() {for i := 0; i < b.N; i++ {Add(2, 3)}})})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 Expect 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。基准测试函数会运行多次,以获取平均性能数据。

3.5 测试覆盖率分析

ginkgo 库中的测试覆盖率分析与 testing 库中的测试覆盖率分析类似,用于评估测试用例的质量和测试代码的完整性。ginkgo 库提供了 go test -cover 命令来进行测试覆盖率分析,该命令会输出被测试代码的覆盖率数据。

以下是一个测试覆盖率分析示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Add", func() {It("should return 5", func() {got := Add(2, 3)want := 5Expect(got).To(Equal(want))})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 Expect 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。我们使用了 go test -cover 命令进行测试覆盖率分析。测试覆盖率分析结果如下:

$ go test -cover
PASS
coverage: 100.0% of statements
ok      github.com/username/project  0.002s

从结果可以看出,被测试代码的覆盖率为 100%,说明测试用例的质量较好,测试代码的完整性较高。

3.6 并发测试

ginkgo 库中的并发测试与 testing 库中的并发测试类似,用于测试并发代码的正确性和性能。ginkgo 库提供了 JustBeforeEachAfterEachParallel 等函数来支持并发测试。

以下是一个并发测试示例:

package mainimport ("sync""testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var counter *Counter
var wg *sync.WaitGroupvar _ = Describe("Counter", func() {BeforeEach(func() {counter = NewCounter()wg = &sync.WaitGroup{}})AfterEach(func() {wg.Wait()})It("should increment counter", func() {wg.Add(1)go func() {counter.Inc()wg.Done()}()eventually(func() int {return counter.Value()}, "1 second").Should(Equal(1))})It("should increment counter concurrently", func() {wg.Add(2)go func() {counter.Inc()wg.Done()}()go func() {counter.Inc()wg.Done()}()eventually(func() int {return counter.Value()}, "1 second").Should(Equal(2))}, 2)
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}type Counter struct {value intmutex sync.Mutex
}func NewCounter() *Counter {return &Counter{}
}func (c *Counter) Inc() {c.mutex.Lock()defer c.mutex.Unlock()c.value++
}func (c *Counter) Value() int {c.mutex.Lock()defer c.mutex.Unlock()return c.value
}

在这个示例中,我们使用了 BeforeEach 函数来初始化计数器和等待组,使用了 AfterEach 函数来等待所有 Goroutine 运行完毕。在第一个测试用例中,我们使用了 eventually 函数来等待计数器的值为 1。在第二个测试用例中,我们使用了 Parallel 函数来启用并发测试,并使用了 eventually 函数来等待计数器的值为 2。

3.7 表格驱动测试

ginkgo 库中的表格驱动测试与 testing 库中的表格驱动测试类似,用于对多组测试用例进行批量测试。表格驱动测试可以大大简化测试代码,提高测试代码的复用性和可维护性。

以下是一个表格驱动测试示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Add", func() {It("should return correct result", func() {cases := []struct {x, y, want int}{{2, 3, 5},{0, 0, 0},{-1, 1, 0},}for _, c := range cases {got := Add(c.x, c.y)Expect(got).To(Equal(c.want))}})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了表格驱动测试对 Add 函数进行了批量测试。我们定义了一个包含多组测试用例的结构体数组,每个测试用例都包含了 xywant 三个字段。在测试函数中,我们遍历了所有的测试用例,并对每个测试用例进行了测试。

3.8 Mock测试

ginkgo 库中的 Mock 测试与 testing 库中的 Mock 测试类似,用于模拟依赖组件的行为,以隔离被测试代码。ginkgo 库提供了一个名为 gock 的子包,用于创建和管理模拟对象。

以下是一个 Mock 测试示例:

package mainimport ("testing". "github.com/onsi/ginkgo". "github.com/onsi/gomega""github.com/stretchr/testify/mock""gopkg.in/h2non/gock.v1"
)type UserService interface {GetUser(id int) (*User, error)
}type User struct {ID   intName string
}type UserController struct {UserService UserService
}func (c *UserController) GetUser(id int) (*User, error) {return c.UserService.GetUser(id)
}type MockUserService struct {mock.Mock
}func (m *MockUserService) GetUser(id int) (*User, error) {args := m.Called(id)return args.Get(0).(*User), args.Error(1)
}var _ = Describe("UserController", func() {var userService *MockUserServicevar controller *UserControllerBeforeEach(func() {userService = &MockUserService{}controller = &UserController{UserService: userService}})AfterEach(func() {gock.OffAll()})It("should return user", func() {user := &User{ID: 1, Name: "Tom"}userService.On("GetUser", 1).Return(user, nil)got, err := controller.GetUser(1)Expect(err).To(BeNil())Expect(got).To(Equal(user))})It("should return error", func() {userService.On("GetUser", 1).Return(nil, errors.New("user not found"))got, err := controller.GetUser(1)Expect(err).To(HaveOccurred())Expect(got).To(BeNil())})
})func TestMyTestSuite(t *testing.T) {RegisterFailHandler(Fail)RunSpecs(t, "My Test Suite")
}

在这个示例中,我们使用了 gock 子包来创建和管理模拟对象。我们定义了一个 UserService 接口,用于模拟用户服务的行为。我们还定义了一个 MockUserService 结构体,用于实现 UserService 接口,并使用 mock 子包来模拟 UserService 的行为。在测试函数中,我们使用了 MockUserService 来模拟用户服务的行为,并对 UserController 进行了测试。

4. gocheck库

gocheck 是一个用于 Go 语言的测试库,提供了丰富的断言函数和测试套件等测试功能。gocheck 库的设计目标是提供一套简单易用、功能强大、可扩展性好的测试工具,以帮助开发者更高效地进行单元测试和集成测试。

4.1 基本概述

gocheck 库是一个第三方的 Go 测试库,用于对 Go 代码进行自动化测试。gocheck 库提供了一系列的测试工具,包括断言函数、测试套件等,用于帮助开发者更好地组织和管理测试代码。

4.2 测试函数

4.2.1 命名规则

gocheck 库中的测试函数命名规则与 testing 库中的测试函数命名规则类似,必须以 Test 开头,接受一个 *testing.T 类型的参数,并且不能有任何返回值。测试函数必须放在要测试的包的 _test.go 文件中,否则不会被测试框架识别。

4.2.2 函数签名

gocheck 库中的测试函数的函数签名如下:

func TestName(t *testing.T)

其中,Name 是测试函数的名称,通常为要测试的函数或方法的名称。t 是一个指向 testing.T 类型的指针,用于报告测试结果和错误信息。

4.3 子测试和子测试函数

gocheck 库中的子测试和子测试函数与 testing 库中的子测试和子测试函数类似,用于对测试用例进行分组和子分组,以更好地组织和管理测试代码。子测试函数可以嵌套在其他子测试函数中,形成一个树状结构。子测试和子测试函数可以共享测试数据和测试逻辑,提高测试代码的复用性和可维护性。

以下是一个子测试函数示例:

package mainimport ("testing""github.com/go-check/check"
)type MyTestSuite struct{}var _ = check.Suite(&MyTestSuite{})func (s *MyTestSuite) TestAdd(c *check.C) {c.Run("normal case", func(c *check.C) {got := Add(2, 3)want := 5c.Assert(got, check.Equals, want)})c.Run("edge case", func(c *check.C) {got := Add(0, 0)want := 0c.Assert(got, check.Equals, want)})
}func TestMyTestSuite(t *testing.T) {check.TestingT(t)
}func Add(x, y int) int {return x + y
}

在这个示例中,我们使用了 check.Suite 类型来定义一个测试套件,并在测试套件中定义了一个 TestAdd 测试函数。在 TestAdd 测试函数中,我们使用了 c.Run 函数定义了两个子测试函数,分别测试了 Add 函数的正常情况和边界情况。每个子测试函数都接受一个闭包函数,用于测试具体的测试用例。在子测试函数中,我们使用了 c.Assert 函数来比较实际值和预期值,如果两者不相等,则报告错误信息。最后,我们使用了 check.TestingT 函数来运行测试套件。

4.4 Suite和SuiteSetUp

Gocheck提供了Suite和SuiteSetUp两个概念,用于组织测试代码。Suite是一个测试套件,它包含一组相关的测试用例。SuiteSetUp是一个可选的函数,它在Suite中的所有测试用例运��之前被调用,用于执行一些初始化操作。

以下是一个使用Suite和SuiteSetUp的例子:

package main_testimport ("testing""github.com/go-check/check"
)type Suite struct {db *DB
}var _ = check.Suite(&Suite{})func (s *Suite) SetUpSuite(c *check.C) {s.db = NewDB()
}func (s *Suite) TearDownSuite(c *check.C) {s.db.Close()
}func (s *Suite) TestAdd(c *check.C) {s.db.Add("test")c.Assert(s.db.Count(), check.Equals, 1)
}func (s *Suite) TestRemove(c *check.C) {s.db.Add("test")s.db.Remove("test")c.Assert(s.db.Count(), check.Equals, 0)
}func TestSuite(t *testing.T) {check.TestingT(t)
}

在这个例子中,我们定义了一个名为Suite的结构体,它包含一个DB类型的成员变量。我们使用check.Suite函数将Suite注册为一个测试套件。我们还定义了两个函数SetUpSuiteTearDownSuite,它们分别在Suite中的所有测试用例运行之前和运行之后被调用。在SetUpSuite函数中,我们创建了一个新的DB实例,并将其赋值给Suite的db成员变量。在TearDownSuite函数中,我们关闭了DB实例。

在Suite中,我们定义了两个测试用例TestAddTestRemove,它们分别测试了DB的Add和Remove方法。在每个测试用例中,我们使用了Suite的db成员变量来操作DB。

在测试套件中,我们使用check.TestingT函数来运行测试套件。

4.5 跳过测试

Gocheck提供了一个名为Skip的函数,用于跳过某些测试用例。Skip函数接收一个字符串参数,用于描述跳过测试的原因。

以下是一个使用Skip函数跳过测试用例的例子:

package main_testimport ("testing""github.com/go-check/check"
)type Suite struct{}var _ = check.Suite(&Suite{})func (s *Suite) TestSkip(c *check.C) {c.Skip("Skip this test")
}func TestSuite(t *testing.T) {check.TestingT(t)
}

在这个例子中,我们定义了一个名为TestSkip的测试用例,它调用了c.Skip函数来跳过这个测试用例。在控制台输出中,我们可以看到这个测试用例被跳过了:

$ go test -v
=== RUN   TestSuite
=== SKIP  TestSuite.TestSkip
--- PASS: TestSuite (0.00s)--- SKIP: TestSuite.TestSkip (0.00s)
PASS
ok      command-line-arguments  0.011s

4.6 测试覆盖率

Go语言提供了一个名为go tool cover的工具,用于测量测试覆盖率。测试覆盖率是指被测试代码中被测试用例执行到的代码行数占总代码行数的比例。

以下是一个测试覆盖率的例子:

$ go test -cover
PASS
coverage: 80.0% of statements
ok      command-line-arguments  0.011s

在这个例子中,我们使用了-cover标志来运行测试,并输出了测试覆盖率。在这个例子中,测试覆盖率为80%,表示被测试代码中有80%的代码行数被测试用例执行到了。

如果想要生成一个可视化的测试覆盖率报告,可以使用-coverprofile标志来指定一个输出文件,然后使用go tool cover命令来生成报告:

$ go test -cover -coverprofile=cover.out
$ go tool cover -html=cover.out

在这个例子中,我们使用了-coverprofile标志来指定一个输出文件cover.out,然后使用了go tool cover命令来生成一个HTML格式的测试覆盖率报告。

5. gomega库

Gomega是一个Go语言的测试库,它提供了一组丰富的匹配器,用于简化测试用例的编写和维护。Gomega库是Ginkgo库的部分,但也可以单独使用。

5.1 基本概述

Gomega库提供了一组匹配器,用于简化测试用例的编写和维护。匹配器是一种特殊的函数,它接收一个实际值和一个期望值,然后返回一个布尔值,表示实际值是否满足期望值。

Gomega库还提供了一些辅助函数,用于打印测试用例的结果和错误信息。

5.2 安装

可以使用以下命令来安装Gomega库:

$ go get github.com/onsi/gomega

5.3 使用

以下是一个使用Gomega库的例子:

package main_testimport ("testing""github.com/onsi/gomega""github.com/stretchr/testify/assert"
)func TestGomega(t *testing.T) {g := gomega.NewGomegaWithT(t)// 使用Gomega的匹配器来测试一个整数num := 10g.Expect(num).To(gomega.Equal(10))g.Expect(num).NotTo(gomega.Equal(20))g.Expect(num).To(gomega.BeNumerically(">", 5))g.Expect(num).To(gomega.BeNumerically("<=", 10))// 使用Gomega的匹配器来测试一个字符串str := "hello"g.Expect(str).To(gomega.Equal("hello"))g.Expect(str).NotTo(gomega.Equal("world"))g.Expect(str).To(gomega.ContainSubstring("ell"))g.Expect(str).To(gomega.HaveLen(5))// 使用Gomega的匹配器来测试一个切片slice := []int{1, 2, 3}g.Expect(slice).To(gomega.HaveLen(3))g.Expect(slice).To(gomega.ContainElement(2))g.Expect(slice).NotTo(gomega.ContainElement(4))// 使用Testify的断言来测试一个错误err := someFunctionThatReturnsAnError()assert.NotNil(t, err)g.Expect(err).To(gomega.HaveOccurred())g.Expect(err.Error()).To(gomega.ContainSubstring("some error"))
}func someFunctionThatReturnsAnError() error {return fmt.Errorf("some error")
}

在这个例子中,我们使用了gomega.NewGomegaWithT函数来创建一个新的Gomega实例,并将其绑定到当前的测试用例中。然后,我们使用了Gomega的匹配器来测试一个整数、一个字符串和一个切片。在测试过程中,我们使用了g.Expect函数来检查实际值是否满足期望值。

在最后,我们使用了Testify的断言来测试一个错误,并使用了Gomega的匹配器来检查错误的信息。

在控制台输出中,我们可以看到测试用例的结果和错误信息:

$ go test -v
=== RUN   TestGomega
--- PASS: TestGomega (0.00s)
PASS
ok      command-line-arguments  0.012s

5.4 匹配器

Gomega库提供了许多内置的匹配器,用于测试不同类型的值。以下是一些常用的匹配器:

  • Equal(expected interface{}):检查实际值是否等于期望值。
  • Not(matcher Matcher):检查实际值是否不满足给定的匹配器。
  • BeNumerically(operator string, value interface{}):检查实际值是否满足给定的数值比较运算符和值。
  • ContainSubstring(substring string):检查实际值是否包含给定的子字符串。
  • HaveLen(length int):检查实际值的长度是否等于给定的长度。
  • ContainElement(element interface{}):检查实际值是否包含给定的元素。
  • HaveOccurred():检查实际值是否为一个非nil的错误。
  • HavePrefix(prefix string):检查实际值是否以给定的前缀开头。
  • HaveSuffix(suffix string):检查实际值是否以给定的后缀结尾。

5.5 自定义匹配器

Gomega库允许用户定义自己的匹配器。以下是一个自定义匹配器的例子:

package main_testimport ("testing""github.com/onsi/gomega"
)func TestCustomMatcher(t *testing.T) {g := gomega.NewGomegaWithT(t)// 定义一个自定义匹配器matcher := gomega.WithTransform(func(actual interface{}) interface{} {return actual.(string) + " world"}, gomega.Equal("hello world"))// 使用自定义匹配器来测试一个字符串str := "hello"g.Expect(str).To(matcher)
}

在这个例子中,我们定义了一个名为matcher的自定义匹配器,它使用了gomega.WithTransform函数来转换实际值,然后使用了gomega.Equal函数来检查转换后的值是否等于期望值。在测试过程中,我们使用了g.Expect函数来检查实际值是否满足自定义匹配器。

在控制台输出中,我们可以看到测试用例的结果和错误信息:

$ go test -v
=== RUN   TestCustomMatcher
--- PASS: TestCustomMatcher (0.00s)
PASS
ok      command-line-arguments  0.012s

6. goconvey库

Goconvey是一个Go语言的测试库,它提供了一个 web 界面,用于查看测试用例的结果和错误信息。Goconvey库是Ginkgo库的一部分,但也可以单独使用。

6.1 基本概述

Goconvey库提供了一个 web 界面,用于查看测试用例的结果和错误信息。在 web 界面中,用户可以查看测试用例的执行过程、测试覆盖率、错误信息等。

Goconvey库还提供了一些辅助函数,用于打印测试用例的结果和错误信息。

6.2 安装

可以使用以下命令来安装Goconvey库:

$ go get github.com/smartystreets/goconvey/convey

6.3 使用

以下是一个使用Goconvey库的例子:

package main_testimport ("testing""github.com/smartystreets/goconvey/convey"
)func TestConvey(t *testing.T) {convey.Convey("TestConvey", t, func() {convey.Convey("Given a number", func() {num := 10convey.Convey("When the number is added by 1", func() {num++convey.Convey("Then the number should be 11", func() {convey.So(num, convey.ShouldEqual, 11)})})})})
}

在这个例子中,我们使用了convey.Convey函数来定义一个测试用例,然后使用了convey.So函数来检查实际值是否满足期望值。在测试过程中,我们使用了convey.Convey函数来描述测试用例的执行过程。

在控制台输出中,我们可以看到测试用例的结果和错误信息:

$ go test -v
=== RUN   TestConvey
=== RUN   TestConvey/Given_a_number
=== RUN   TestConvey/Given_a_number/When_the_number_is_added_by_1
=== RUN   TestConvey/Given_a_number/When_the_number_is_added_by_1/Then_the_number_should_be_11
--- PASS: TestConvey (0.00s)--- PASS: TestConvey/Given_a_number (0.00s)--- PASS: TestConvey/Given_a_number/When_the_number_is_added_by_1 (0.00s)--- PASS: TestConvey/Given_a_number/When_the_number_is_added_by_1/Then_the_number_should_be_11 (0.00s)
PASS
ok      command-line-arguments  0.012s

在 web 界面中,我们可以查看更详细的测试用例结果和错误信息:

$ go test -v | go-convey-web

然后,在浏览器中打开http://localhost:8080,即可查看测试用例的结果和错误信息。

6.4 辅助函数

Goconvey库提供了一些辅助函数,用于打印测试用例的结果和错误信息。以下是一些常用的辅助函数:

  • convey.So(actual interface{}, message string, f convey.FailFunc):检查实际值是否满足给定的条件,如果不满足,则调用f函数来打印错误信息。
  • convey.Should(actual interface{}) convey.Shoulder:返回一个convey.Shoulder接口,用于链式调用其他辅助函数。
  • convey.ShouldEqual(expected interface{}):检查实际值是否等于给定的期望值。
  • convey.ShouldNotEqual(unexpected interface{}):检查实际值是否不等于给定的期望值。
  • convey.ShouldBeNil():检查实际值是否为nil。
  • convey.ShouldNotBeNil():检查实际值是否不为nil。
  • convey.ShouldBeTrue(b bool):检查实际值是否为true。
  • convey.ShouldBeFalse(b bool):检查实际值是否为false。
  • convey.ShouldResemble(expected interface{}):检查实际值是否与给定的期望值具有相同的结构和值。
  • convey.ShouldNotResemble(unexpected interface{}):检查实际值是否与给定的期望值具有不同的结构或值。
  • convey.ShouldPanic(f func()):检查调用f函数是否会引发panic。
  • convey.ShouldNotPanic(f func()):检查调用f函数是否不会引发panic。

6.5 配置

Goconvey库提供了一些配置选项,用于自定义测试用例的执行和输出。以下是一些常用的配置选项:

  • convey.Coverage:启用或禁用测试覆盖率的计算。
  • convey.MaxDepth:设置测试用例的最大嵌套深度。
  • convey.Report:设置测试用例的报告模式。
  • convey.Trace:设置测试用例的跟踪模式。
  • convey.WebRoot:设置 web 界面的根目录。
  • convey.WebPort:设置 web 界面的端口号。

可以在测试用例中使用convey.Configure函数来设置这些配置选项。

总结

单元测试是保证代码质量的重要手段,Go语言提供了丰富的测试框架和工具来帮助我们编写高质量的单元测试。本文介绍了几个流行的测试框架和工具,如testing库、testify库、ginkgo库、gocheck库、gomega库和goconvey库。每个工具都有其独特的特性和用法,可以满足不同的测试需求。通过掌握这些工具,开发人员可以更好地编写和执行单元测试,提高软件质量和稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/723294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Polar 到底给不给flag呢

Polar 到底给不给flag呢 开局直接给了源码 $flag flag{f73da0c8e7c774d488a6df0fec2890d9};是假的 变量覆盖&#xff0c;没啥好说的。举两个例子吧。 <?php $a "hello"; echo "$a"; //输出hello $$a"world"; echo "$…

安装mysql this application requires visual studio 2019 x64报错

提示 this application requires visual studio 2019 x64 缺少依赖 安装依赖 选择对应版本 安装 依赖安装地址 成功进入安装界面

Java 中哪些库可以解决线宽问题?

在Java中&#xff0c;线程安全是一个重要的问题&#xff0c;特别是在多线程编程中。线程安全性是指当多个线程访问共享资源时&#xff0c;不会出现不确定的结果或数据损坏的情况。Java提供了多种机制来解决线程安全性问题&#xff0c;其中包括使用线程安全的类库、同步机制、并…

c++|模板初阶

c|模板 模板的引入模板的作用函数模板函数模板的格式swap函数原理函数模板的实例化1.隐式实例化2.显示实例化 函数模板的匹配规则 类模板类模板的实例化谢谢观看 模板的引入 我们在写交换两个整型的swap函数的时候&#xff0c;突然需求变成交换两个双浮点型&#xff0c;我们这…

【C语言】glibc

一、获取源码 apt install glibc-source 在Debian系统中&#xff0c;通过apt install glibc-source命令安装的glibc源码通常会被放置在/usr/src/glibc目录下。安装完成后&#xff0c;可能需要解压缩该源码包。以下是解压缩源码包的步骤&#xff1a; 1. 打开终端。 2. 切换到源…

设计MySQL数据表的几个注意点

最近合作搞项目&#xff0c;发现了很多问题。特别的&#xff0c;数据库层面上的问题更为致命。记录一下&#xff0c;希望后面看到博客的同学们注意。 注意&#xff1a;以下观点只用于一般情况下的单体、微服务&#xff0c;不保证适用所有场景。 一、ID问题 ID名称问题 如下图…

蓝牙系列二:BLE协议各层的形象化理解

对于蓝牙的协议栈模型已经不再陌生&#xff0c;但是看过相关的文档还是有些没法理解协议栈每层的区别以及每层的功能作用。本文还是继续学习韦东山讲解的蓝牙&#xff0c;对于初学者还是有很好的帮助作用&#xff0c;下面是韦东山老师形象化协议栈的框图&#xff1a; 下面还是把…

交叉编译介绍及实战

前言介绍 交叉编译是一种操作系统或者硬件架构上生成在另一种操作系统或者硬件架构上运行的代码的过程。通常情况下&#xff0c;我们会使用cmake来配置和管理跨平台的项目。 交叉编译有三个核心元素&#xff1a; Host&#xff1a;你将在其上运行编译器的机器。Target&#x…

[计算机效率] 软件优化及垃圾清理

1.7 软件优化及垃圾清理 1.7.1 Advanced SystemCare(优化清理) Advanced SystemCare是一款功能强大的系统性能优化软件&#xff0c;可以全方位诊断系统&#xff0c;找到性能瓶颈并进行有针对性的优化&#xff0c;提升系统运行速度和网络速度&#xff0c;还可以清理加速和保护…

ZWT_各向同性线弹性材料本构模型umat的应用

线弹性材料本构模型 对于多数材料而言&#xff0c;在微小变形的假设下&#xff0c;会满足线弹性理论&#xff0c;数学可以表示为&#xff1a; σ i j C i j k l ε k l E 1 ν ( ε i j ν 1 − 2 ν ε k k δ i j ) \begin{align*} \sigma_{ij}&C_{ijkl}\varepsilon…

金融基础——拨备前利润和拨备后利润介绍

一、简介 拨备前利润&#xff08;PreProvision Operating Profit&#xff0c;也就是PPOP&#xff09;和拨备后利润的主要区别在于是否扣除减值准备金、是否遵循保守性原则以及显示的利润数值不同。 拨备前利润。指在计算利润时没有扣除减值准备金的利润&#xff0c;它等于税前…

QT----QTcreater连接Mysql数据库

目录 1、下载驱动&#xff0c;放入文件夹2、编写代码&#xff0c;实现本地访问3、实现网络数据库3.1 更改权限3.2 修改代码 之前写了一个图书管理系统用的是sqlite3&#xff0c;现在想用mysql&#xff0c;部署到网上&#xff0c;实现远程访问。 1、下载驱动&#xff0c;放入文…

[清爽快捷] Ubuntu上多个版本的cuda切换

做到真正的一行代码搞定&#xff0c;只需要修改对应软链接&#xff0c;就可以轻松实现快捷切换cuda 查看已安装的cuda版本有哪些 一般如果我们都是使用默认位置安装cuda的话&#xff0c;那么其安装路径都是/usr/local。如果要查看该目录下已经安装有哪些版本的cuda&#xff0c…

录制屏幕技巧大揭秘,看看哪种适合你?

在当今信息化的时代&#xff0c;录制屏幕已成为学习、工作和娱乐中不可或缺的一部分。无论是制作教学视频、记录游戏过程&#xff0c;还是制作演示文稿&#xff0c;录制屏幕都为我们提供了极大的便利。本文将详细介绍三种录制屏幕方法&#xff0c;帮助读者轻松掌握录制屏幕的技…

适用于 Windows 的7大数据恢复软件解决方案

数据丢失是数字世界中令人不快的一部分&#xff0c;它会在某一时刻影响许多计算机用户。很容易意外删除一些重要文件&#xff0c;这可能会在您努力恢复它们时带来不必要的压力。幸运的是&#xff0c;数据恢复软件可以帮助恢复已删除的文件&#xff0c;即使您没有备份它们。以下…

2.13计算机工作过程

2.三个级别的语言 1)机器语言。又称二进制代码语言&#xff0c;需要编程人员记忆每条指令的二进制编码。机器语言是计算机唯一可以直接识别和执行的语言。 2)汇编语言。汇编语言用英文单词或其缩写代替二进制的指令代码&#xff0c;更容易为人们记忆和理解。使用汇编语言编辑的…

如何向各大媒体网站投稿 海外媒体发稿平台有哪些

在数字化时代&#xff0c;各大媒体网站是企业推广和个人展示的重要平台。通过在媒体网站上发布文章&#xff0c;可以有效地扩大影响力和提升知名度。但是&#xff0c;如何投稿到各大媒体网站呢&#xff1f;以下是一些常用的方法和步骤。 1. 研究目标媒体 在投稿之前&#xff0…

C# 水排序 微信小游戏

来只 水排序谜题启发式搜索方法_水排序解法小程序-CSDN博客 大神的C语言转换成C# 语言&#xff0c;更多的请看原作者&#xff0c;这里直接贴C#代码 using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace ConsoleApp2 {class Pro…

【python】yaml转成json

姊妹篇&#xff1a;【python】json转成成yaml yaml数据&#xff1a; address:city: 北京市postalCode: 100000street: 北京路123号 age: 30 cart: - product:name: 笔记本电脑price: 1199.99quantity: 2 - product:name: 智能手机price: 599.99quantity: 1 children: - age: …

微服务:Feign篇

1.什么是Feign Feign是一种声明式、模板化的HTTP客户端&#xff0c;可用于调用HTTP API实现微服务之间的远程服务调用。它的特点是使用少量的配置定义服务客户端接口&#xff0c;可以实现简单和可重用的RPC调用。 先来看我们以前利用RestTemplate发起远程调用的代码&#xff…