如何让Dir []和Dir.foreach以确定的顺序返回结果?

时间:2013-04-10 20:04:24

标签: ruby testing filesystems

我正在尝试使用Dir[]和/或Dir.foreach来整理目录:

files = Dir["#{options[:dir]}/**/*"].reject { |file| File.directory?(file) }
puts files.map{|filename| filename.join("\n")

def print_tree(dir = ".", nesting = 0)
  Dir.foreach(dir) do |entry|
    next if entry =~ /^\.{1,2}/ # Ignore ".", "..", or hidden files
    puts "| " * nesting + "|-- #{entry}"
    if File.stat(d = "#{dir}#{File::SEPARATOR}#{entry}").directory?
      print_tree(d, nesting + 1)
    end
  end
end

我正试图用Cucumber and Aruba测试一下。这是listing_files.feature中的内容:

When I run `poet ls`
Then the output should contain exactly:
"""
foo/bar/conf1
foo/conf2.disabled

"""

Then the output should contain exactly:
"""
|-- foo
| |-- bar
| | |-- conf1
| |-- conf2.disabled

"""

测试我的本地机器工作(OSX)很好,但我在Travis上失败了:

expected: "foo/bar/conf1\nfoo/conf2.disabled\n"
got: "foo/conf2.disabled\nfoo/bar/conf1\n" (using ==)

显然,返回结果的顺序在所有系统上都不一样。对于1.9.3和2.0,这是documented behavior

  

请注意,区分大小写取决于您的系统(因此忽略File :: FNM_CASEFOLD),   和返回结果的顺序一样。

这使得测试目录列表成为一场噩梦。我可以以某种方式强迫订单吗?或者如果没有,是否有最佳实践来综合测试这样的事情?

2 个答案:

答案 0 :(得分:3)

您可以在返回之前对Dir[]调用的结果进行排序:

def print_tree(dir = ".", nesting = 0)
  Dir.entries(dir).sort.each do |entry|
    # the rest is the same...
  end
end

或者,如果您有两个目录列表数组,请在比较之前对每个目录列表进行排序。

此外,如果您正在使用RSpec,则可以使用=~运算符来预期数组内容而不是订单/内容:

arr1 = Dir['*.whatever']
arr2 = some_method_that_gets_the_dir_listing()
arr2.should =~ arr1

在Test :: Unit中,可以使用assert_same_elements

完成相同的操作

答案 1 :(得分:0)

如果您不关心订单,可以随时使用带有splat的include匹配器来解压缩阵列

[1,2,3,4,5].should include(*[5,2,4,1,3])