Go ---- godog的使用

简介: Go ---- godog的使用

介绍

godog和go test做的是一样的事,都是测试代码的。只是换了一种形式。

godog是Golang的官方Cucumber BDD框架,它将规范和测试文档合并为一个有凝聚力的整体,使用Gherkin格式的场景,格式为Given,When,Then。

使用

目的:我们要测试一个吃东西的功能是否已经实现。

使用go get 安装

go get github.com/cucumber/godog/cmd/godog@v0.12.0

或是是安装二进制文件使用go install

go install github.com/cucumber/godog/cmd/godog@latest

创建一个feature文件夹,并在该文件夹中创建godogs.feature文件,内容如下

Feature: eat godogs
  In order to be happy
  As a hungry gopher
  I need to be able to eat godogs
  Scenario: Eat 5 out of 12
    Given there are 12 godogs
    When I eat 5
    Then there should be 7 remaining

然后在控制台使用godog run

会出现如下内容

Feature: eat godogs
  In order to be happy
  As a hungry gopher
  I need to be able to eat godogs
  Scenario: Eat 5 out of 12          # features/godogs.feature:6
    Given there are 12 godogs
    When I eat 5
    Then there should be 7 remaining
1 scenarios (1 undefined)
3 steps (3 undefined)
220.129µs
You can implement step definitions for undefined steps with these snippets:
func iEat(arg1 int) error {
        return godog.ErrPending
}
func thereAreGodogs(arg1 int) error {
        return godog.ErrPending
}
func thereShouldBeRemaining(arg1 int) error {
        return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
        ctx.Step(`^I eat (\d+)$`, iEat)
        ctx.Step(`^there are (\d+) godogs$`, thereAreGodogs)
        ctx.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

新建一个godogs_test.go文件。

将上面的函数复制到godogs_test.go中。

package main
import "github.com/cucumber/godog"
func iEat(arg1 int) error {
        return godog.ErrPending
}
func thereAreGodogs(arg1 int) error {
        return godog.ErrPending
}
func thereShouldBeRemaining(arg1 int) error {
        return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
        ctx.Step(`^I eat (\d+)$`, iEat)
        ctx.Step(`^there are (\d+) godogs$`, thereAreGodogs)
        ctx.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

再次运行godog run

这次我们可以看到

Feature: eat godogs
  In order to be happy
  As a hungry gopher
  I need to be able to eat godogs
  Scenario: Eat 5 out of 12          # features/godogs.feature:6
    Given there are 12 godogs        # godogs_test.go:10 -> thereAreGodogs
      TODO: write pending definition
    When I eat 5                     # godogs_test.go:6 -> iEat
    Then there should be 7 remaining # godogs_test.go:14 -> thereShouldBeRemaining
1 scenarios (1 pending)
3 steps (1 pending, 2 skipped)
282.123µs

但函数有错误返回时将不会通过,所以我们应该修改函数的返回,或者是函数没有错误,不给返回值。如

func iEat(arg1 int) {
  // Eat arg1.
}

下面完善行为流程。将下面的代码复制到godogs_test.go 文件中。

package godogs
import (
  "context"
  "errors"
  "fmt"
  "testing"
  "github.com/cucumber/godog"
)
// godogsCtxKey 是用来在context.Context中存储可用godogs的键。
type godogsCtxKey struct{}
// 错误在三个步骤定义中返回 nil,方案将成功通过。
func thereAreGodogs(ctx context.Context, available int) (context.Context, error) {
  return context.WithValue(ctx, godogsCtxKey{}, available), nil
}
func iEat(ctx context.Context, num int) (context.Context, error) {
  // 使用断言
  available, ok := ctx.Value(godogsCtxKey{}).(int)
  if !ok {
    return ctx, errors.New("there are no godogs available")
  }
  if available < num {
    return ctx, fmt.Errorf("you cannot eat %d godogs, there are %d available", num, available)
  }
  available -= num
  return context.WithValue(ctx, godogsCtxKey{}, available), nil
}
func thereShouldBeRemaining(ctx context.Context, remaining int) error {
  available, ok := ctx.Value(godogsCtxKey{}).(int)
  if !ok {
    return errors.New("there are no godogs available")
  }
  if available != remaining {
    return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, available)
  }
  return nil
}
func TestFeatures(t *testing.T) {
  // 配置测试套件
  suite := godog.TestSuite{
    ScenarioInitializer: InitializeScenario,
    Options: &godog.Options{
      // 格式名称
      Format:   "pretty",
      // 所有特征文件路径
      Paths:    []string{"features"},
      // 运行子测试的测试实列
      TestingT: t,
    },
  }
  if suite.Run() != 0 {
    t.Fatal("non-zero status returned, failed to run feature tests")
  }
}
func InitializeScenario(sc *godog.ScenarioContext) {
  sc.Step(`^there are (\d+) godogs$`, thereAreGodogs)
  sc.Step(`^I eat (\d+)$`, iEat)
  sc.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
}

再次执行godog run命令,发现全部通过,则功能已经实现,若是最后出现没有通过的情况,则是逻辑出错,请仔细检查更正后继续测试。

BDD 行为驱动开发

什么是BDD?

BDD是软件团队的一种工作方式。类似于软件开发的瀑布模型,都是用于开发软件的一种模式。

有以下几个特点:

  • 鼓励跨角色协作,以建立对要解决的问题的共同理解
  • 在快速、小的迭代中工作,以增加反馈和价值流动
  • 生成系统文档,根据系统行为自动检查

发展史

瀑布开发模式

以前使用的开发模型大多都是瀑布开发模式,但是由于瀑布模型的先开发后测试的特性,导致代码交予测试后会有一大段时间代码开发人员处于空闲期,没活干,这大大的拖慢了软件开发的进度。

test-first programing

因为在开发中可能不会按照瀑布开发模型走,而是一边写代码一边测试,开发的同时不断的对代码进行完善。这样的做法叫test-first programing

测试驱动开发

如果在测试开发的过程中发现功能没办法使用现在可用的技术实现,也将大大的降低效率,任何代码不能开发到一半的时候才发现当前的设计方案行不通。所以在设计之前,技术上要做好测试,验证这样的设计在技术上是行得通的,然后在具体着手开发。这样的做法叫 test-driven development (TDD)

行为驱动开发

在开发过程中突然发现原本的功能几乎无用,或是别的功能或许更加重要,然后再这样的代码上做出针对性的调整。这样的做法叫:behavior-driven development (BDD)

行为驱动开发就是由测试驱动开发发展来的。它遵循持续迭代,小步快跑原则。

Step

Step是指GivenWhenThenAndBut这种,虽然程序在处理的时候,并不会对这些关键字做区分,但在写feature文件的时候,我们需要做明确区分,方便我们合理的描述流程。

结合文章开头的例子,可能觉得例子太过于简单了。但实际上这个gherkin语法支持的功能也是很丰富的。包括它的scenario outlinebackground等。

主要的关键字,点击查看详细信息:

几个常用的简单介绍

  • Feature:描述我们需要测试的功能
  • Scenario: 描述测试场景
  • Given: 描述初始上下文
  • When: 描述一个事件(强烈建议每个方案只有一个步骤)
  • Then: 描述预期结果(应基于可观察的输出)

参考信息:

GitHub - cucumber/godog: Cucumber for golang

How to use godog | 渐行渐远 (neojos.com)



相关文章
|
人工智能 搜索推荐 数据管理
探索软件测试中的自动化测试框架选择与优化策略
本文深入探讨了在现代软件开发流程中,如何根据项目特性、团队技能和长期维护需求,精准选择合适的自动化测试框架。
550 11
|
开发工具 git
Git使用不当导致代码丢失的N种场景
背景git作为目前使用最广泛的分布式版本控制软件,集团内基本上所有开发同学都使用它来做代码管理。一个最典型的使用场景,是一个git仓库存在一个master主干分支,多个需求基于master拉自己的开发分支,然后在发布日时,新建一个release分支,然后原先并行的几个开发分支merge到release分支上,最后基于该分支发布上线,上线后release再merge到master主干上,一次发布完成
3755 1
Git使用不当导致代码丢失的N种场景
|
JSON Kubernetes 数据格式
K8S client-go Patch example
我在本文中主要会介绍使用client-go的Patch方式,主要包括strategic merge patch和json-patch
|
消息中间件 算法 数据库
如果解决MQ消息堆积问题
如果解决MQ消息堆积问题
|
数据采集 Prometheus 运维
基于LoongCollector构建全新可观测Pipeline
LoongCollector是阿里云推出的下一代可观测数据管道,旨在融合多种采集技术,构建统一的可观测数据代理。它具备高性能、可靠性和灵活性,支持日志、指标和追踪等多类型数据采集。通过模块化设计和SPL处理引擎,LoongCollector实现了高效的数据处理与传输,并大幅简化了配置管理。此外,集成eBPF技术,提供无侵入、高性能的应用性能监控,适用于复杂异构环境。未来,LoongCollector将继续优化性能、探索AI赋能的智能化采集。
671 102
|
Java 测试技术 持续交付
自动化测试实践:从单元测试到集成测试
【6月更文挑战第28天】-单元测试:聚焦代码最小单元,确保每个函数或模块按预期工作。使用测试框架(如JUnit, unittest),编写覆盖所有功能和边界的测试用例,持续集成确保每次变更后自动测试。 - 集成测试:关注模块间交互,检查协同工作。选择集成策略,编写集成测试用例,模拟真实环境执行测试,整合到CI/CD流程以持续验证软件稳定性。 自动化测试提升软件质量,降低成本,加速开发周期,是现代软件开发不可或缺的部分。
|
Devops 测试技术 持续交付
软件测试中的自动化与持续集成:最佳实践与挑战
在快速迭代的软件开发周期中,自动化测试和持续集成(CI)已成为提高软件质量和加速产品上市的关键策略。本文探讨了自动化测试和CI的实施如何帮助开发团队提前发现缺陷、缩短反馈循环,并确保代码质量。我们将深入分析自动化测试的策略选择、工具应用以及面临的挑战,同时提供一些克服这些挑战的最佳实践。
668 27
|
存储 负载均衡 监控
何为微服务、网关、服务发现/注册?
随着互联网业务复杂性慢慢提高,单机服务的架构慢慢出现了生产效率问题 微服务架构带来的有优点也有缺点,使用前需要调研清楚 微服务架构的网关设计、服务注册/发现、配置管理都是关键点
何为微服务、网关、服务发现/注册?
|
安全 Go 调度
Go语言中的并发编程:掌握goroutines和channels
在现代软件开发中,并发编程已经成为不可或缺的一部分。Go语言以其简洁的语法和强大的并发特性,成为了开发者的首选之一。本文将深入探讨Go语言中的两个核心概念——goroutines和channels,并通过实际代码示例展示如何使用它们来实现高效的并发处理。无论你是初学者还是有经验的开发者,通过本文的学习,你将能够更好地理解和应用Go语言的并发机制,提升你的编程技能。
|
Go
一行代码处理字符串,Go语言链式调用技术深度指南
一行代码处理字符串,Go语言链式调用技术深度指南
692 0