Before/After Suite when using Ruby MiniTest

前端 未结 8 1043
时光说笑
时光说笑 2020-12-09 07:30

Is there an alternative to RSpec\'s before(:suite) and after(:suite) in MiniTest?

I suspect that a custom test runner is in order, however

相关标签:
8条回答
  • 2020-12-09 07:58

    You can just place the code outside of the class.

    This is what I do to have a banner.

    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
    
    0 讨论(0)
  • 2020-12-09 07:59

    Nice thing about minitest is its flexibility. I've been using a custom MiniTest Runner with a +before_suite+ callback. Something like in this example - Ruby Minitest: Suite- or Class- level setup?

    And then tell minitest to use the custom runner

    MiniTest::Unit.runner = MiniTestSuite::Unit.new
    
    0 讨论(0)
  • 2020-12-09 08:01

    To run code before each test, use before. You're operating here in the context of an instance, possibly of a class generated implicitly by describe, so instance variables set in before are accessible in each test (e.g. inside an it block).

    To run code before all tests, simply wrap the tests in a class, a subclass of MiniTest::Spec or whatever; now, before the tests themselves, you can create a class or module, set class variables, call a class method, etc., and all of that will be available in all tests.

    Example:

    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
    

    Here's the output, along with my comments in braces explaining what each line of the output proves:

    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]
    

    (Note that I do not mean this output to imply any guarantee about the order in which tests will run.)

    Another approach is to use the existing before but wrap code to run only once in a class variable flag. Example:

    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
    
    0 讨论(0)
  • 2020-12-09 08:02

    One simple way to do this is to write a guarded class method, and then call that in a begin.

    A Minitest::Spec example:

    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
    

    ...to get

    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
    
    0 讨论(0)
  • 2020-12-09 08:04

    There are setup() and teardown() methods available. The documentation also lists before() and after() as being available.

    Edit: Are you looking to run something before each test or before or after the whole suite is finished?

    0 讨论(0)
  • 2020-12-09 08:07

    To get this to work with the current version of Minitest (5.0.6) you need to require 'minitest' and use 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

    0 讨论(0)
提交回复
热议问题