0

我正在编写一个简单的命令行 gem。

执行实际工作的库是使用 rspec 开发的,并且到目前为止有效。

我正在尝试使用 Aruba/Cucumber 测试命令行部分,但我遇到了一些奇怪的行为。

只是为了测试这个,我有一个二进制文件puts ARGV,我有测试文件tmp/aruba

当我运行时,我会bundle exec gem_name tmp/aruba/*.*看到 shell 扩展文件名的列表。

现在我的功能文件有:

Given files to work on       # I set up files in tmp/aruba in this step
When I run `gem_name *.*`    # standard step
Then the output should contain "Wibble"

最后一步显然会失败,但它向我展示了预期与实际输出之间的差异。而不是看到一个shell扩展文件名列表,我得到的只是"*.*"

因此,我只能拥有一个可以按预期工作的应用程序,但我无法通过测试。我可以使用“ . ”并从那里生成文件列表,但是我正在编写额外的生产代码只是为了让应用程序在测试中工作——我认为这不是正确的方法。而这一切都是因为外壳扩展没有发生。

如果您查看我的个人资料,您会发现 Ruby 不是我的主要包,请随时指出我可能错过的任何资源,但这只是我遗漏了什么,或者有人知道的预期行为如何解决?

4

1 回答 1

2

在对Aruba 源代码进行了一些挖掘之后,我发现该When I run步骤最终出现在如下代码块中:

def run!(&block)
  @process = ChildProcess.build(*shellwords(@cmd))
  ...
  begin
    @process.start
    ...

进一步挖掘到这里ChildProcess结束:

def launch_process
  ...
  begin
    exec(*@args)
    ...

这就是问题所在。exec当参数列表被拆分为多个数组元素时,不进行 shell 扩展:

如果给 exec 一个参数,则该参数将被视为在执行之前受外壳扩展影响的行。如果给定了多个参数,则第二个和后续参数作为参数传递给 command 而没有 shell 扩展。

但是玩shellwords了一下我们发现:

Shellwords.shellwords('gem_name *.*')
=> ["gem_name", "*.*"]                   # No good
Shellwords.shellwords('"gem_name *.*"')
=> ["gem_name *.*"]                      # Aha!

因此,解决方案可能很简单:

When I run `"gem_name *.*"`

如果这不起作用,那么你很不走运。我建议您手动扩展文件名,因为您在这里并没有真正测试 shell 扩展 - 我们知道这是有效的:您正在测试多个参数。

因此,您应该改为:

When I run `gem_name your_file1 your_file2 your_file3`
于 2012-12-29T05:06:39.523 回答