测试不会自动运行

时间:2014-12-05 20:55:57

标签: ruby minitest guard

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

文件夹结构如下所示:

.
├── exercism
└── ruby
    ├── bob
    │   ├── bob.rb
    │   ├── bob_test.rb
    ├── etl
    │   ├── etl.rb
    │   ├── etl_test.rb
...
    └── binary_search_tree
        ├── bst.rb
        ├── binary_search_tree.rb
        └── README.md

由于文件夹结构异常,我在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

通过此设置,我希望在对.rb文件进行任何编辑后运行所有测试。

我在调试模式下运行。

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

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

20:43:26 - DEBUG - Interactor was stopped or killed    
20:43:26 - DEBUG - Hook :run_on_additions_begin executed for Guard::Minitest
20:43:26 - DEBUG - Hook :run_on_additions_end executed for Guard::Minitest
20:43:26 - DEBUG - Start interactor

我在防护配置中尝试了很多变化,例如:

watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
  Dir.glob("ruby/#{m[1]}/*_test.rb").first  
end

(我希望这只能从修改文件的文件夹中运行测试。)

似乎没什么用。我必须去看守的交互式控制台并按 ENTER 来运行测试。

我做错了什么?


修改

在阅读下面的Cezary's answer后,我尝试了更多其他内容,包括在其他环境中尝试此操作。

事实证明这不是警卫的错,但可能是我正在使用的环境。

我最初在Codio框中运行了所有内容。 我将项目移动到其他两台机器,一台Win8和一台Ubuntu 14.04,它使用这个Guardfile都可以正常工作:

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的输出如下:

在Codio框上(不起作用):

<!-- language: lang-none -->

08:55:09 - DEBUG - Interactor was stopped or killed
  Should test ruby/anagram/anagram_test.rb
08:55:09 - DEBUG - Hook :run_on_additions_begin executed for Guard::Minitest
08:55:09 - DEBUG - Hook :run_on_additions_end executed for Guard::Minitest
08:55:09 - DEBUG - Start interactor
[1] guard(main)>

在Win / Ubuntu上(它工作正常):

<!-- language: lang-none -->

11:02:10 - DEBUG - Interactor was stopped or killed
  Should test ruby/anagram/anagram_test.rb
11:02:10 - DEBUG - Hook :run_on_modifications_begin executed for Guard::Minitest
11:02:10 - INFO - Running: ruby/anagram/anagram_test.rb
Run options: --seed 52507

# Running tests:

..........

Finished tests in 0.001249s, 8006.0205 tests/s, 8006.0205 assertions/s.

10 tests, 10 assertions, 0 failures, 0 errors, 0 skips

11:02:10 - DEBUG - Hook :run_on_modifications_end executed for Guard::Minitest
11:02:10 - DEBUG - Start interactor
[1] guard(main)>

我不知道为什么在Codio上我得到run_on_additions而在另外两个我得到run_on_modifications。 无论如何,我猜这是一个Codio问题。我尝试使用和不使用手动保存,它也是一样的。

2 个答案:

答案 0 :(得分:5)

嗨,我是其中一个&#34;责备&#34;对于Guard,基于此,我写了一个演练:https://github.com/guard/guard/wiki/Understanding-Guard

我强烈建议您仔细阅读(反馈意见)。

以下是需要考虑的事项清单:

  1. 结构:如果可以的话,将测试放在一个单独的顶级文件夹中,理想情况下是&ruby / test&#39;在您的示例中,以及&#39; ruby​​ / lib&#39;中的文件。这更接近于惯例,然后像Guard::Minitest这样的东西可以开箱即用。 (有些编辑 - 比如Vim和Emacs--允许你在&#34;替代&#34;文件之间切换,他们会自动知道在哪里寻找测试或实施文件。)

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

  3. Guard :: Minitest选项 - 如果您使用我描述的结构,这不是必需的。如果没有,我认为test_folder: %w(ruby)应该足够了。此外,test_file_patterns不一定是必要的,因为您的文件似乎遵循默认/约定(bob_test.rbetl_test.rb) - 除非您有一些非常奇怪的测试套件< em> inside bob.rbetl.rb个文件。

  4. 您的监视表达式没有阻止,因此它返回已更改的文件。不幸的是,当您更改实现文件(如bob.rb)时,该文件将传递给Guard::Minitest,忽略非测试文件(可能使用test_file_patterns选项,因此{{1}赢得了bob.rb,Guard :: Minitest会悄悄地做......什么都没有。

  5. 理想情况下,重命名您的bob_test.rb,更新您的宝石(基本上为Guardfile)并运行Guard::Minitest,以便&#34;当前&#34;建议的模板适用于bundle exec guard init minitest,并尝试对其进行调整。您会看到默认设置为:

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

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

    Guard::Minitest

    我说regexen很糟糕 - 而且我计划实施glob模式支持 - 但这需要一段时间(对我来说很多关键错误修复)。

    1. 如果这没有帮助 - 绝对要通过上面的Wiki文档,因为你可以使用Guard / Listen大约有20-50个问题 - 而且大部分都完全在Guard&s / s之外听取控制权。 (我希望我可以改变它以使其更简单,所以任何建议都会有所帮助)。

    2. 由于错误对我来说是一个优先事项,就像大多数维护者一样 - 我们依赖于GitHub报告的问题。因此,我们通常不会在Stack Overflow中观察内容(我们预计Github会报告棘手的问题)。

    3. 好的,我已经指出了很多错误,你做的事情的时间非常非常好:

      1. 在调试模式下运行watch(%r{^ruby/(.*/)?([^/]+)\.rb$}) { |m| "ruby/#{m[1]}/#{m[2]}_test.rb" } - 您真的很棒

      2. 显示有关更改的输出 - 您也很高兴这样做(因为这表明Guard :: Minitest正在获取更改,但它忽略了它们 - 可能是因为您&# 39;重新传递实现文件而不是测试文件。)

      3. 提交这样一个详细的问题 - 非常有帮助。理想情况下,你不应该经历所有麻烦(或者甚至首先遇到问题),但通过报告这一点,你可以向我们展示Guard在这么多层面上的错误。 (通常,作为开发人员/维护人员,我们会得到内部人员,因此我们立即知道&#34;什么是错误的 - 即使文档或消息或调试输出对其他人没有任何意义 - 所以这样的问题可以帮助我们帮助别人非常

      4. 再次感谢您 - 如果您看到其他人有问题可以解决 - 请这样做。如果您在Guard中看到明显的错误或问题 - 请在Guard中打开一个问题。如果它在另一个插件存储库(如Guard)中,请提及我,以免重要问题被忽略(在GitHub上提到我Guard::Minitest)。

        我希望能让Guard更好 - 目前我正在努力使其变得更简单,更直观,更灵活,更可靠。我可以依靠报道破碎内容的人越多,我就能越快地推进酷炫的东西。

        再次感谢,祝你有个美好的一天!

答案 1 :(得分:0)

当我想要使用Guard进行任何新的Ruby Exercism练习时,我遇到了类似的问题:运行完整的测试套件会起作用,但是当文件发生变化时测试不会自动运行。我为了实现这一目标所做的工作如下:

  1. 创建一个公共Guardfile并将其放在~/exercism/ruby/Guardfile,其中包含以下内容:

    # 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
    
  2. 在练习文件夹中运行Guard时,请始终专门引用此Guardfile,即guard --guardfile ~/exercism/ruby/Guardfile

  3. 这里有一些关于Guardfile配置的具体问题:

    • test_folders选项,guard-minitest将查找测试文件的位置,默认为%w[test spec]。这适用于任何标准的Ruby项目,但不适用于练习,其中测试文件和实现文件位于同一目录中。因此,需要将其更改为["."]以指定。
    • 在Minitest watch方法的块中,返回的字符串需要看起来像路径,否则测试将在文件更改时不运行(没有错误输出或指示某些内容)出错)。例如:

      watch(%r{\A.+_test\.rb\z}) { |m| "#{m[1]}" }无效。它必须是watch(%r{\A.+_test\.rb\z}) { |m| "./#{m[1]}" }