开发过程测试 | 豆包MarsCode AI 刷题

52 阅读3分钟

软件测试

软件测试主要分为三种类型:回归测试、集成测试和单元测试。

回归测试

回归测试的重点在于确保系统在经过更新或修改后,原有的功能仍然能够正常运行。简单来说,就是你改了一些代码,需要保证这些改动没有影响到其他已经测试通过的功能。比如,你更新了用户管理模块的某部分逻辑,回归测试可以帮助验证登录和注册功能是否仍然正常。

集成测试

集成测试主要关注不同模块或服务之间的交互,保证各个单独测试过的模块组合在一起时能够正确协作,解决的是模块之间数据传递和依赖的问题。比如,如果你的系统有用户管理、支付系统和订单处理三个模块,集成测试会确保用户下单、支付成功后订单状态能够正确更新。

单元测试

单元测试是软件测试中最基础也是最重要的一部分。它主要是在开发阶段对单独的函数或模块进行功能验证,确保每个单元在不同的输入条件下都能正确运行。单元测试的好处在于能够快速定位和修复问题,减少代码修改带来的风险。

单元测试规范

  • 文件命名:单元测试文件通常以 -test.go 结尾,例如 user_test.go
  • TestMain 函数:在 Go 语言中,使用 TestMain 函数可以实现测试前的初始化和测试后的清理工作。这个函数的参数是 m *testing.M,可以用它来装载数据、初始化环境,测试完成后释放资源,确保测试环境的干净。
func TestMain(m *testing.M) {
    // 初始化工作
    setup()

    // 运行所有测试
    code := m.Run()

    // 清理工作
    teardown()

    // 退出
    os.Exit(code)
}

**

单元测试的目标

  • 幂等性:多次运行同一个测试用例,结果应该始终一致。这确保了测试的可靠性和可重复性。
  • 稳定性:单元测试应该能够在任何时候独立运行,不受其他测试用例或外部环境的影响。这提高了测试的灵活性和独立性。

单元测试的覆盖率

  • 一般覆盖率:50-60% 的代码覆盖率是一个合理的目标。
  • 较高覆盖率:80% 以上的代码覆盖率可以提供更高的信心,确保大部分代码都经过了测试。
  • 测试分支:测试用例应该覆盖所有可能的分支,确保每个逻辑路径都被验证。
  • 测试单元粒度:每个测试用例应该只验证一个函数或方法的功能,而且这个函数或方法的职责应该单一。

Mock 测试

Mock 测试主要用于在测试中模拟外部依赖或函数的行为。这样可以隔离被测试代码,防止外部因素干扰测试结果。常用的 Mock 测试包有 Monkey。

  • 打桩(Patch) :用一个模拟函数(A)替换实际函数(B)。这样可以控制函数 B 的行为,确保测试的可预测性。
  • 取消打桩(Unpatch) :在测试完成后恢复原函数 B 的行为。
import "github.com/bouk/monkey"

func TestSomeFunction(t *testing.T) {
    // 打桩
    patch := monkey.Patch(originalFunc, mockFunc)
    defer patch.Unpatch()

    // 运行测试
    someFunction()
    // 验证结果
    assert....(t)
}

**

基准测试

基准测试用于评估程序的运行性能和资源消耗情况。性能问题通常需要通过基准测试来发现和优化。

  • Benchmark 开头:基准测试函数以 Benchmark 开头。
  • 入参:基准测试函数的参数是 b *testing.B
  • 并行执行:通过 RunParallel() 方法支持并行测试。
  • 执行次数:可以通过 b.N 参数指定测试的执行次数。
import "testing"

func BenchmarkSomeFunction(b *testing.B) {
    // 并行测试
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            someFunction()
        }
    })

    // 单线程测试
    for i := 0; i < b.N; i++ {
        someFunction()
    }
}