Ruby Minitest: Suite- or Class- level setup?
Using the built-in Ruby Minitest framework, is there a way to run some code once before the entire suite runs, or even once before an entire TestClass runs? I see in the answer to this question that Test::Unit::after_tests can b开发者_开发技巧e used to run code after all tests have been run; is there a similar method to run code before all tests have run?
I would like to use this functionality to initialize a test database before the tests run and tear it down after they have all run.
Thanks!
This is modified from the MiniTest docs (under Customizable Test Runner Types).
class Burger
  def initialize
    puts "YOU CREATED A BURGER"
  end
  def has_cheese?
    true
  end
  def has_pickle?
    false
  end
end
gem 'minitest'
require 'minitest/unit'
MiniTest::Unit.autorun
class MyMiniTest
  class Unit < MiniTest::Unit
    def before_suites
      # code to run before the first test
      p "Before everything"
    end
    def after_suites
      # code to run after the last test
      p "After everything"
    end
    def _run_suites(suites, type)
      begin
        before_suites
        super(suites, type)
      ensure
        after_suites
      end
    end
    def _run_suite(suite, type)
      begin
        suite.before_suite if suite.respond_to?(:before_suite)
        super(suite, type)
      ensure
        suite.after_suite if suite.respond_to?(:after_suite)
      end
    end
  end
end
MiniTest::Unit.runner = MyMiniTest::Unit.new
class BurgerTest < MiniTest::Unit::TestCase
  def self.before_suite
    p "hi"
  end
  def self.after_suite
    p "bye"
  end
  def setup
    @burger = Burger.new
  end
  def test_has_cheese
    assert_equal true, @burger.has_cheese?
  end
  def test_has_pickle
    assert_equal false, @burger.has_pickle?
  end
end
Note that you I included gem 'minitest' to use the gem instead of the bundled version which didn't have the MiniTest::Unit.runner method. Here's the output.
Run options: --seed 49053
# Running tests:
"Before everything"
"hi"
YOU CREATED A BURGER
.YOU CREATED A BURGER
."bye"
"After everything"
Finished tests in 0.000662s, 3021.1480 tests/s, 3021.1480 assertions/s.
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
So it calls #setup twice, but .before_suite and .after_suite only once, which is what you are looking for I think.
An alternative way to get a handle on the time before and after all the tests in a MiniTest suite have run is to put if blocks in the setup & teardown methods to control that these blocks only get called once.
In this way, you can load a browser and other dependencies such as page objects just once at the beginning of your test suite and then close the browser at the end when all tests have completed.
Here's an example of this using MiniTest 5.5.1 and Watir:
class CoolTests < Minitest::Test
  @@setupComplete  = false  # tracks whether 1-time setup has completed, so we only instantiate a browser and dependent pages/modules one time per suite run
  @@testsRun       = 0      # tracks how many tests have run so we can close the browser when all tests complete
  def setup                                                    # Minitest#setup runs before every #test method
    @@testsRun+=1                                              # increment tetsRun indicating that a test has run
    if (!@@setupComplete)                                      # we load the browser and necessary page objects here one-time if we haven't already
        @@driver = Watir::Browser.new :chrome                  # instantiate new chrome browser
        @@driver.window.maximize                               # maximize the browser window so we expect to test against Desktop UI/UX rather than Mobile UI/UX
        @@setupComplete = true                                 # setupComplete is now true as we've loaded up everything we need for our tests
    end
  end
  def teardown                                                 # Minitest#teardown runs after every #test method
    if (@@testsRun == CoolTests.runnable_methods.length)   # if we've run all the tests in the suite we are finished and can then close the browser
        @@driver.quit
    end
  end
  #Tests
  def test_one
    p __method__
    @@driver.goto('www.google.com')
    assert_equal 'Google', @@driver.title, 'browser should be at google.com'
  end
  def test_two
    p __method__
    @@driver.goto('www.bing.com')
    assert_equal 'Bing', @@driver.title, 'browser should be at bing.com'
  end
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论