You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bats无法识别被测函数导出的数组变量的解决方法

解决Bats中无法识别全局数组的问题

Bats是一款优秀的bash脚本测试工具,但在示例、说明等诸多方面的文档严重不足1。很多开发者在测试输出为全局数组的函数时,会遇到Bats无法识别该数组的问题——普通变量可以通过stdout导出内容,但数组处理起来更麻烦。

问题复现

以下是包含函数定义(_load_filetoarray)和测试的文件:

#!bats/bin/bats

load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'

_load_filetoarray() {
  # 假设数组数据来自外部文件
  declare -a CREATEDARRAY
  CREATEDARRAY=("aaa" "bbb" "ccc")
  export CREATEDARRAY
}

@test "stackoverflow plain" {
  # 运行待测试函数
  run _load_filetoarray

  # 验证数组加载的元素数量
  assert [ "${#CREATEDARRAY[@]}" -eq 3 ]
}

在Bats v1.10.0中运行该文件,会得到如下失败结果:

stackoverflow.bats
 ✗ stackoverflow plain
   (from function `assert' in file test_helper/bats-assert/src/assert.bash, line 40,
    in test file stackoverflow.bats, line 18)
     `assert [ "${#CREATEDARRAY[@]}" -eq 3 ]' failed
   
   -- assertion failed --
   expression : [ 0 -eq 3 ]
   --
   

1 test, 1 failure

单独运行bash脚本时数组能正常加载,但Bats无法识别,核心原因是:Bats的run命令会在子shell中执行目标函数,子shell内的环境变量(包括数组)无法传递回父shell,所以测试代码中访问到的CREATEDARRAY是空数组。

解决方案

方案1:直接调用函数(不使用run)

如果不需要捕获函数的输出、退出状态等信息,直接在当前shell中调用函数即可,这样函数创建的全局数组能被测试代码直接访问:

@test "stackoverflow plain" {
  # 直接调用函数,跳过run命令
  _load_filetoarray

  # 验证数组长度
  assert [ "${#CREATEDARRAY[@]}" -eq 3 ]
  # 也可以验证具体元素
  assert_equal "${CREATEDARRAY[0]}" "aaa"
}

方案2:将数组输出到stdout,在测试中解析

如果必须使用run(比如需要检查函数的退出状态、捕获错误输出),可以修改函数,将数组元素输出到标准输出,然后利用Bats提供的$lines变量(存储命令输出的每一行)来验证:

首先修改函数:

_load_filetoarray() {
  declare -a CREATEDARRAY
  CREATEDARRAY=("aaa" "bbb" "ccc")
  # 将数组元素按换行分隔输出到stdout
  printf "%s\n" "${CREATEDARRAY[@]}"
}

然后修改测试代码:

@test "stackoverflow with run" {
  run _load_filetoarray

  # 验证函数执行成功
  assert_success
  # 验证输出的行数等于数组元素个数
  assert_equal "${#lines[@]}" 3
  # 逐个验证数组元素
  assert_equal "${lines[0]}" "aaa"
  assert_equal "${lines[1]}" "bbb"
  assert_equal "${lines[2]}" "ccc"
}

1 关于Bats文档的吐槽:
抱歉,它是个很棒的工具,但文档让我回想起计算机行业的“旧日时光”,知识被资深人士垄断。我花了数年才发现Bats支持直接测试函数,还是通过别人的测试文件才得知。我曾摸索出一个需要run bash -c '...'搭配export -f funcname的测试。另外,$lines和$output孰先孰后?官方readthedocs.io教程中途逻辑混乱,开始引用未提前介绍的文件。

内容的提问来源于stack exchange,提问作者Cliff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:43:17