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

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

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

【问题讨论】:

    标签: ruby test-suite minitest


    【解决方案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
        

        【讨论】:

          猜你喜欢
          • 2013-11-18
          • 1970-01-01
          • 1970-01-01
          • 2014-08-30
          • 1970-01-01
          • 2017-09-02
          • 2022-01-24
          • 1970-01-01
          • 2013-09-17
          相关资源
          最近更新 更多