【发布时间】:2011-08-18 09:32:05
【问题描述】:
在 MiniTest 中是否有 RSpec 的 before(:suite) 和 after(:suite) 的替代品?
我怀疑自定义测试运行程序是有序的,但是我无法想象这不是一个常见的要求,所以可能有人已经实现了。:-)
【问题讨论】:
标签: ruby test-suite minitest
在 MiniTest 中是否有 RSpec 的 before(:suite) 和 after(:suite) 的替代品?
我怀疑自定义测试运行程序是有序的,但是我无法想象这不是一个常见的要求,所以可能有人已经实现了。:-)
【问题讨论】:
标签: ruby test-suite minitest
有setup() 和teardown() 方法可用。该文档还列出了可用的 before() 和 after()。
编辑:您是否希望在每次测试之前或整个套件完成之前或之后运行某些东西?
【讨论】:
setup/teardown 和 before/after 在每个测试之后运行。我需要在 all 测试之前和之后运行一些东西。
如 Caley 的回答和 cmets 中所述,MiniTest::Unit 包含函数 after_tests。没有before_tests 或等效项,但您的minitest_helper.rb 文件中的任何代码都应在测试套件之前运行,这样才能执行此类功能。
警告:在 Ruby 中还是比较新的,在 Minitest 中非常新,所以如果我错了,请纠正我! :-)
【讨论】:
load 你的 test_helper/mintest_helper。如果你使用require,那么它只会加载一次,因此只会运行一次
要使其与当前版本的 Minitest (5.0.6) 一起使用,您需要 require 'minitest' 并使用 Minitest.after_run { ... }。
warn "MiniTest::Unit.after_tests is now Minitest.after_run. ..."
https://github.com/seattlerb/minitest/blob/master/lib/minitest.rb https://github.com/seattlerb/minitest/blob/master/lib/minitest/unit.rb
【讨论】:
要在每个测试之前运行代码,请使用before。您在实例的上下文中操作,可能是由describe 隐式生成的类,因此在每个测试中都可以访问before 中设置的实例变量(例如在it 块内)。
要在所有测试之前运行代码,只需将测试包装在一个类、MiniTest::Spec 的子类或其他任何东西中;现在,在测试本身之前,您可以创建类或模块、设置类变量、调用类方法等,所有这些都将在所有测试中可用。
例子:
require "minitest/autorun"
class MySpec < MiniTest::Spec
class MyClass
end
def self.prepare
puts "once"
@@prepared = "prepared"
@@count = 0
end
prepare
before do
puts "before each test"
@local_count = (@@count += 1)
end
describe "whatever" do
it "first" do
p MyClass
p @@prepared
p @local_count
end
it "second" do
p MyClass
p @@prepared
p @local_count
end
end
end
这是输出,以及我在大括号中的 cmets,解释了输出的每一行证明了什么:
once [this code, a class method, runs once before all tests]
Run options: --seed 29618 [now the tests are about to run]
# Running tests:
before each test [the before block runs before each test]
MySpec::MyClass [the class we created earlier is visible in each test]
"prepared" [the class variable we set earlier is visible in each test]
1 [the instance variable from the before block is visible in each test]
before each test [the before block runs before each test]
MySpec::MyClass [the class we created earlier is visible in each test]
"prepared" [the class variable we set earlier is visible in each test]
2 [the instance variable from the before block is visible each test]
(请注意,我的意思不是说这个输出意味着对测试运行顺序的任何保证。)
另一种方法是使用现有的before,但将代码包装为只在类变量标志中运行一次。示例:
class MySpec < MiniTest::Spec
@@flag = nil
before do
unless @@flag
# do stuff here that is to be done only once
@@flag = true
end
# do stuff here that is to be done every time
end
# ... tests go here
end
【讨论】:
prepare 成语的人,就像我一样,在Rails 中设置一些数据库记录。如果您在test/fixtures 目录中甚至有一个空白文件,那么您通过prepare 放入数据库的任何内容都将被夹具设置擦除。因为变量本身仍然存在,所以会出现奇怪的情况。
一种简单的方法是编写一个受保护的类方法,然后在begin 中调用它。
Minitest::Spec 示例:
describe "my stuff" do
def self.run_setup_code
if @before_flag.nil?
puts "Running the setup code"
@before_flag = true
end
end
before do
self.class.run_setup_code
end
it "will only run the setup code once" do
assert_equal 1, 1
end
it "really only ran it once" do
assert_equal 1,1
end
end
...得到
Run options: --seed 11380
# Running:
Running the setup code
..
Finished in 0.001334s, 1499.2504 runs/s, 1499.2504 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
【讨论】:
您可以将代码放在类之外。
这就是我做横幅的原因。
require 'selenium-webdriver'
require 'minitest/test'
require 'minitest/autorun'
class InstanceTest < Minitest::Test
def setup
url = ARGV.first
@url = self.validate_instance(url)
@driver = Selenium::WebDriver.for :firefox
end
【讨论】:
minitest 的好处在于它的灵活性。我一直在使用带有 +before_suite+ 回调的自定义 MiniTest Runner。这个例子中的东西 - Ruby Minitest: Suite- or Class- level setup?
然后告诉 minitest 使用自定义 runner
MiniTest::Unit.runner = MiniTestSuite::Unit.new
【讨论】:
您还可以通过像这样更新您的 test_helper.rb(或 spec_helper.rb)来添加测试后回调
# test_helper.rb
class MyTest < Minitest::Unit
after_tests do
# ... after test code
end
end
【讨论】: