Reputation: 809
Given the following code:
require 'minitest/autorun'
require '<some other stuff>
class test < MiniTest::Unit::TestCase
def setup
<setup some stuff>
end
def teardown
<teardown some stuff>
end
def test1
<test1 code>
end
def test2
<test2 code>
end
end
How can I make it so that minitest runs both test1 and test2 using the initial setup? The reason I am asking, is because setup instantiates a Selenium Webdriver instance and does some time consuming login/setup, and I'd like to use the same instance(instead of instantiating a new instance every time) to shorten the time it takes to test the feature.
Upvotes: 0
Views: 2075
Reputation: 8984
There are a lot of assumptions being made in this question that I will try to address. First, Minitest doesn't run the tests in parallel. By default Minitest runs tests in random order. You can change the order the tests are run by overriding the test_order
method on the test class.
class MyTest < MiniTest::Unit::TestCase
def self.test_order
:sorted # Or :alpha, they both behave the same
end
end
But, that won't get you to what I think you are asking. This will only make it so that test1
is always run before test2
. This is only useful if you have written your tests such they need to run in order. (Alphabetical order, not necessarily the order they are defined in the class.)
Instance variables within a test class are not shared between tests. Meaning, test1
is run on a different instance of MyTest
than test2
is run on. In order to share objects between tests you need to set them in global or class variables.
class MyTest < MiniTest::Unit::TestCase
def setup
@@this_thing ||= begin
# Really expensive operation here
end
end
end
Hope this helps.
Upvotes: 3
Reputation: 27885
Do you need Minitest, or can you change to test-unit?
With test-unit you may use 'Test::Unit::TestCase.startupand
Test::Unit::TestCase.shutdown':
gem 'test-unit'#, '>= 2.1.1' #startup
require 'test/unit'
#~ require '<some other stuff>
class MyTest < Test::Unit::TestCase
def self.startup
puts '<setup some stuff>'
end
def self.shutdown
puts '<teardown some stuff>'
end
def test1
puts '<test1 code>'
end
def test2
puts '<test2 code>'
end
end
See also can't get test unit startup to work in ruby 1.9.2
Upvotes: 0
Reputation: 46846
You can do what you want by creating a custom test runner type that has a before and after all tests method. You could then create a selenium-webdriver instance before all tests and close it after all tests.
Here is an example of starting a browser and going to Google before all tests. Each test then re-uses the same browser.
require 'minitest/autorun'
require 'selenium-webdriver'
#Add before and after suite hooks using a custom runner
class MyMiniTest
class Unit < MiniTest::Unit
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 GoogleTest < MiniTest::Unit::TestCase
def self.before_suite
p "before all tests"
@@driver = Selenium::WebDriver.for :firefox
@@driver.navigate.to 'http://www.google.com'
end
def self.after_suite
p "after all tests"
@@driver.quit
end
def setup
p 'setup before each test'
end
def teardown
p 'teardown after each test'
end
def test1
p 'test1'
assert_equal(0, @@driver.find_elements(:xpath, '//div').length)
end
def test2
p 'test2'
assert_equal(0, @@driver.find_elements(:xpath, '//a').length)
end
end
You can see the order that things are run by the output:
"before all tests"
"setup before each test"
"test1"
"teardown after each test"
"setup before each test"
"test2"
"teardown after each test"
"after all tests"
Note that variables you want to share across tests will need to be class variables (ie prefixed with @@).
Upvotes: 0
Reputation: 20330
It's bad idea from a testing point of view, but
You could do both tests in one test and reuse the setup
Or take it out of setup and teardown and add a helper method to set it up if it isn't already and call that from the test. First test that runs takes the hit, other's just reuse it.
What you should be doing however is a mock or stub in the unit test, and leaving the real deal to an integration test.
Upvotes: 0