使用 Ruby MiniTest 之前/之后的套件

Posted

技术标签:

【中文标题】使用 Ruby MiniTest 之前/之后的套件【英文标题】:Before/After Suite when using Ruby MiniTest 【发布时间】:2011-08-18 09:32:05 【问题描述】:

在 MiniTest 中是否有 RSpec 的 before(:suite)after(:suite) 的替代品?

我怀疑自定义测试运行程序是有序的,但是我无法想象这不是一个常见的要求,所以可能有人已经实现了。:-)

【问题讨论】:

【参考方案1】:

setup()teardown() 方法可用。该文档还列出了可用的 before()after()

编辑:您是否希望在每次测试之前或整个套件完成之前或之后运行某些东西?

【讨论】:

setup/teardownbefore/after每个测试之后运行。我需要在 all 测试之前和之后运行一些东西。 Try this Nickolay -- after_tests() 但是对于 before_tests 没有任何作用,该死。我不敢相信这些年来这在 rspec 之外仍然不存在。 Github issue for a before(all) method to run once per TestCase: github.com/seattlerb/minitest/issues/61 and article related to this topic: chriskottom.com/blog/2014/10/… 使用 Minitest > 5.0 完成整个套件后运行代码请参见 this answer【参考方案2】:

如 Caley 的回答和 cmets 中所述,MiniTest::Unit 包含函数 after_tests。没有before_tests 或等效项,但您的minitest_helper.rb 文件中的任何代码都应在测试套件之前运行,这样才能执行此类功能。

警告:在 Ruby 中还是比较新的,在 Minitest 中非常新,所以如果我错了,纠正我! :-)

【讨论】:

我相信这是假设你 load 你的 test_helper/mintest_helper。如果你使用require,那么它只会加载一次,因此只会运行一次 嗯...是的。确切地。它会在测试开始之前运行一次。【参考方案3】:

要使其与当前版本的 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

【讨论】:

【参考方案4】:

要在每个测试之前运行代码,请使用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 放入数据库的任何内容都将被夹具设置擦除。因为变量本身仍然存在,所以会出现奇怪的情况。 (当然,无论如何,真的应该使用固定装置,我很顽皮)。【参考方案5】:

一种简单的方法是编写一个受保护的类方法,然后在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

【讨论】:

不错的方法。好奇:为什么不直接挂钩 Ruby 的初始化方法呢?【参考方案6】:

您可以将代码放在类之外。

这就是我做横幅的原因。

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

【讨论】:

我对这个答案投了赞成票,但请注意,将代码放在类之外仅适用于不影响数据库的代码。类外的所有代码都在事务外执行,如果有任何 activerecord 操作,会使测试数据库变得混乱。【参考方案7】:

minitest 的好处在于它的灵活性。我一直在使用带有 +before_suite+ 回调的自定义 MiniTest Runner。这个例子中的东西 - Ruby Minitest: Suite- or Class- level setup?

然后告诉 minitest 使用自定义 runner

MiniTest::Unit.runner = MiniTestSuite::Unit.new

【讨论】:

【参考方案8】:

您还可以通过像这样更新您的 test_helper.rb(或 spec_helper.rb)来添加测试后回调

# test_helper.rb

class MyTest < Minitest::Unit
  after_tests do
    # ... after test code
  end
end

【讨论】:

以上是关于使用 Ruby MiniTest 之前/之后的套件的主要内容,如果未能解决你的问题,请参考以下文章

ruby 来自https://mattbrictson.com/minitest-and-rails

Ruby 初学者需要语法

为啥我的 Minitest 测试没有并行运行?

使用 CircleCI 和 Minitest 进行前端测试:测试等待页面加载的时间不够长

如何在 testRigor 的一个测试中使用测试套件之前和测试套件之后?

在最新的VScode中运行Minitest - 显示Ansi颜色代码