我正在尝试在我的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问题。我尝试使用和不使用手动保存,它也是一样的。
答案 0 :(得分:5)
嗨,我是其中一个&#34;责备&#34;对于Guard,基于此,我写了一个演练:https://github.com/guard/guard/wiki/Understanding-Guard
我强烈建议您仔细阅读(反馈意见)。
以下是需要考虑的事项清单:
结构:如果可以的话,将测试放在一个单独的顶级文件夹中,理想情况下是&ruby / test&#39;在您的示例中,以及&#39; ruby / lib&#39;中的文件。这更接近于惯例,然后像Guard::Minitest
这样的东西可以开箱即用。 (有些编辑 - 比如Vim和Emacs--允许你在&#34;替代&#34;文件之间切换,他们会自动知道在哪里寻找测试或实施文件。)
Guard递归监视目录(现在甚至无法关闭)。对于小型项目,您可以通过而不是指定directories
选项来查看所有内容。但是,如果您的文件夹中有大量磁盘活动并且您有大型项目,那么您将要选择目录。例如。在您的情况下,它将是:directories ruby
。所以`Dir.glob(&#39; ruby / *&#39;)在这里没有多大意义。
Guard :: Minitest选项 - 如果您使用我描述的结构,这不是必需的。如果没有,我认为test_folder: %w(ruby)
应该足够了。此外,test_file_patterns
不一定是必要的,因为您的文件似乎遵循默认/约定(bob_test.rb
和etl_test.rb
) - 除非您有一些非常奇怪的测试套件< em> inside bob.rb
和etl.rb
个文件。
您的监视表达式没有阻止,因此它返回已更改的文件。不幸的是,当您更改实现文件(如bob.rb
)时,该文件将传递给Guard::Minitest
,忽略非测试文件(可能使用test_file_patterns
选项,因此{{1}赢得了bob.rb
,Guard :: Minitest会悄悄地做......什么都没有。
理想情况下,重命名您的bob_test.rb
,更新您的宝石(基本上为Guardfile
)并运行Guard::Minitest
,以便&#34;当前&#34;建议的模板适用于bundle exec guard init minitest
,并尝试对其进行调整。您会看到默认设置为:
Guard::Minitest
显示了如何将已更改的实现文件转换为测试文件(这是watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
唯一关心的文件)。
在您的情况下,您可能需要:
Guard::Minitest
我说regexen很糟糕 - 而且我计划实施glob模式支持 - 但这需要一段时间(对我来说很多关键错误修复)。
如果这没有帮助 - 绝对要通过上面的Wiki文档,因为你可以使用Guard / Listen大约有20-50个问题 - 而且大部分都完全在Guard&s / s之外听取控制权。 (我希望我可以改变它以使其更简单,所以任何建议都会有所帮助)。
由于错误对我来说是一个优先事项,就像大多数维护者一样 - 我们依赖于GitHub报告的问题。因此,我们通常不会在Stack Overflow中观察内容(我们预计Github会报告棘手的问题)。
好的,我已经指出了很多错误,你做的事情的时间非常非常好:
在调试模式下运行watch(%r{^ruby/(.*/)?([^/]+)\.rb$}) { |m| "ruby/#{m[1]}/#{m[2]}_test.rb" }
- 您真的很棒
显示有关更改的输出 - 您也很高兴这样做(因为这表明Guard :: Minitest正在获取更改,但它忽略了它们 - 可能是因为您&# 39;重新传递实现文件而不是测试文件。)
提交这样一个详细的问题 - 非常有帮助。理想情况下,你不应该经历所有麻烦(或者甚至首先遇到问题),但通过报告这一点,你可以向我们展示Guard在这么多层面上的错误。 (通常,作为开发人员/维护人员,我们会得到内部人员,因此我们立即知道&#34;什么是错误的 - 即使文档或消息或调试输出对其他人没有任何意义 - 所以这样的问题可以帮助我们帮助别人非常。
再次感谢您 - 如果您看到其他人有问题可以解决 - 请这样做。如果您在Guard中看到明显的错误或问题 - 请在Guard中打开一个问题。如果它在另一个插件存储库(如Guard
)中,请提及我,以免重要问题被忽略(在GitHub上提到我Guard::Minitest
)。
我希望能让Guard更好 - 目前我正在努力使其变得更简单,更直观,更灵活,更可靠。我可以依靠报道破碎内容的人越多,我就能越快地推进酷炫的东西。
再次感谢,祝你有个美好的一天!
答案 1 :(得分:0)
当我想要使用Guard进行任何新的Ruby Exercism练习时,我遇到了类似的问题:运行完整的测试套件会起作用,但是当文件发生变化时测试不会自动运行。我为了实现这一目标所做的工作如下:
创建一个公共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
在练习文件夹中运行Guard时,请始终专门引用此Guardfile
,即guard --guardfile ~/exercism/ruby/Guardfile
。
这里有一些关于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]}" }
。