Ruby 测试不会自动运行

Ruby 测试不会自动运行,ruby,minitest,guard,Ruby,Minitest,Guard,我正在尝试在我的Exercism文件夹中设置Guard,以便自动运行所有测试(使用Guard minitest) 文件夹结构如下所示: 。 ├── 锻炼 └── 红宝石    ├── 上下快速移动    │   ├── 鲍勃.rb    │   ├── bob_test.rb    ├── etl    │   ├── etl.rb    │   ├── etl_test.rb ...    └── 二叉搜索树       ├── 英国标准时间       ├── 二进制搜索树.rb   

我正在尝试在我的Exercism文件夹中设置Guard,以便自动运行所有测试(使用Guard minitest)

文件夹结构如下所示:

。
├── 锻炼
└── 红宝石
   ├── 上下快速移动
   │   ├── 鲍勃.rb
   │   ├── bob_test.rb
   ├── etl
   │   ├── etl.rb
   │   ├── etl_test.rb
...
   └── 二叉搜索树
       ├── 英国标准时间
       ├── 二进制搜索树.rb
       └── 自述文件
由于不寻常的文件夹结构,我在Guardfile中进行了以下配置:

# tell Guard to watch all folders under ruby/
all_dirs = Dir.glob('ruby/*')

directories all_dirs

options = {
  test_folders: all_dirs, 
  test_file_patterns: '*_test.rb',
  pride: true
}

guard :minitest, options do   
  watch(%r{^ruby/([^/]+)/([^/]+).rb$})
end
all_dirs = Dir.glob('ruby/*')

directories all_dirs

clearing :on

options = {
  test_folders: all_dirs, 
  test_file_patterns: '*_test.rb',
  pride: true
}

guard :minitest, options do
  watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
    file = Dir.glob("ruby/#{m[1]}/*_test.rb").first
    puts "  Should test #{file}"
    file
  end
end
使用此设置,我希望在对.rb文件进行任何编辑后都能运行我的所有测试

我在调试模式下运行guard

所有测试都在启动时运行,如预期的那样

但是,当我编辑.rb文件时,测试不会再次运行,尽管Guard会输出以下内容:

20:43:26-调试-已停止或终止交互程序
20:43:26-调试-挂钩:为Guard::Minitest运行\u
20:43:26-调试-钩子:在为Guard::Minitest执行的添加端上运行
20:43:26-调试-启动交互程序
我尝试了多种防护配置,例如:

watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
  Dir.glob("ruby/#{m[1]}/*_test.rb").first  
end
(我希望它只能从修改文件的文件夹中运行测试。)

似乎什么都不管用。我必须进入guard的交互控制台,按ENTER键才能运行测试

我做错了什么


编辑 在阅读下面的内容后,我尝试了更多的东西,包括在其他环境中尝试

结果证明这不是guard的错,但可能是我使用的环境

我最初把所有东西都放在一个盒子里。 我将该项目转移到另外两台机器上,一台Win8和一台Ubuntu 14.04,使用这个Guardfile,它在这两台机器上都能正常工作:

# tell Guard to watch all folders under ruby/
all_dirs = Dir.glob('ruby/*')

directories all_dirs

options = {
  test_folders: all_dirs, 
  test_file_patterns: '*_test.rb',
  pride: true
}

guard :minitest, options do   
  watch(%r{^ruby/([^/]+)/([^/]+).rb$})
end
all_dirs = Dir.glob('ruby/*')

directories all_dirs

clearing :on

options = {
  test_folders: all_dirs, 
  test_file_patterns: '*_test.rb',
  pride: true
}

guard :minitest, options do
  watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
    file = Dir.glob("ruby/#{m[1]}/*_test.rb").first
    puts "  Should test #{file}"
    file
  end
end
guard-d
的输出如下:

在密码箱上(不起作用的地方):


08:55:09-调试-已停止或终止交互程序
应该测试ruby/anagram/anagram_test.rb
08:55:09-调试-挂钩:为Guard::Minitest运行\u
08:55:09-调试-钩子:在为Guard::Minitest执行的\u添加\u结束时运行\u
08:55:09-调试-启动交互程序
[1] 防护罩(主)>
在Win/Ubuntu上(运行良好):


11:02:10-调试-已停止或终止交互程序
应该测试ruby/anagram/anagram_test.rb
11:02:10-调试-钩子:为Guard::Minitest运行\u
11:02:10-INFO-Running:ruby/anagram/anagram_test.rb
运行选项:--seed 52507
#运行测试:
..........
在0.001249s、8006.0205测试/秒、8006.0205断言/秒中完成测试。
10次测试,10次断言,0次失败,0次错误,0次跳过
11:02:10-DEBUG-Hook:run_on_modifications_end为Guard::Minitest执行
11:02:10-调试-启动交互程序
[1] 防护罩(主)>
我不知道为什么在Codio上我得到了
run\u on\u additions
,在另外两个上我得到了
run\u on\u modifications
。 不管怎样,我想这是一个密码问题。我尝试了手动保存和不手动保存,结果都是一样的。

嗨,我是守卫的“负责人”之一,基于此,我写了一篇演练:

我强烈建议您仔细阅读(感谢您的反馈)

下面列出了需要考虑的事项:

  • 结构:如果可以,将测试放在一个单独的顶部文件夹中,最好是示例中的“ruby/test”,文件放在“ruby/lib”中。这更接近常规,然后像
    Guard::Minitest
    这样的东西就可以开箱即用了。(一些编辑器——如Vim和Emacs——允许您在“可选”文件之间切换,它们将自动知道在哪里查找测试或实现文件)

  • Guard递归地监视目录(现在甚至不能关闭)。对于小型项目,您可以通过不指定
    目录
    选项来查看所有内容。但是,如果文件夹中有大量磁盘活动,并且有大型项目,则需要选择目录。例如,在您的情况下,它将是:
    目录ruby
    。所以'Dir.glob('ruby/*')在这里没有多大意义

  • Guard::Minitest选项-如果您使用我描述的结构,这应该不是必需的。如果没有,我认为拥有
    test\u文件夹:%w(ruby)
    就足够了。另外,
    test\u file\u模式
    应该是不必要的,因为您的文件似乎遵循默认/约定(
    bob\u test.rb
    etl\u test.rb
    ),除非您有一些非常奇怪的事情,比如在
    bob.rb
    etl.rb
    文件中有测试套件

  • 您的watch表达式没有块,因此它返回更改的文件。不幸的是,当您更改一个实现文件(如
    bob.rb
    )时,该文件会被传递到
    Guard::Minitest
    ,它会忽略非测试文件(可能使用
    test\u file\u patterns
    选项),因此由于
    bob.rb
    bob\u test.rb
    不匹配,Guard::Minitest将悄悄地执行任何操作

  • 理想情况下,重命名您的
    Guardfile
    ,更新您的gems(
    Guard::Minitest
    基本上),然后运行
    bundle exec Guard init Minitest
    ,使其成为
    Guard::Minitest
    的“当前”推荐模板,并尝试对其进行调整。您将看到默认模板有:

    watch(%r{^lib/(.*/)?([^/]+)\.rb$})  { |m| "test/#{m[1]}test_#{m[2]}.rb" }
    
  • 它显示了如何将更改的实现文件转换为测试文件(这些文件是
    Guard::Minitest
    唯一关心的文件)

    在您的情况下,您可能需要:

    watch(%r{^ruby/(.*/)?([^/]+)\.rb$}) { |m| "ruby/#{m[1]}/#{m[2]}_test.rb" }
    
    我会说regexen非常糟糕——我正计划实现glob模式支持——但这需要一段时间(我正在进行大量关键的bug修复)

  • 如果这没有帮助-一定要浏览上面的Wiki文档,因为Guard/Listen可能会有20-50个问题-而且大多数问题完全不在Guard/Listen的控制范围内。(我希望我能改变这一点,让它变得简单。)
    # frozen_string_literal: true
    
    group :red_green_refactor, halt_on_fail: true do
      guard :minitest,
            all_on_start: false,
            test_folders: ["."] do
        # Re-test test files when they're edited.
        watch(%r{\A.+_test\.rb\z}) { |m| "./#{m[1]}" }
        # Run the test file of the (non-test) file that was edited.
        watch(%r{\A(.+)(?<!_test)\.rb\z}) { |m| "./#{m[1]}_test.rb" }
      end
    
      guard :rubocop,
            all_on_start: false,
            cli: ["--display-cop-names"] do
        # Only run Rubocop over implementation files only
        # as test files are not written by me.
        watch(%r{\A(.+)(?<!_test)\.rb\z})
        watch(%r{(?:.+/)?\.rubocop\.yml\z}) { |m| File.dirname(m[0]) }
      end
    end