Creating a test suite using Ruby minitest
There is no Test::Unit::TestSuite
in minitest. You have several options, assuming your tests look something like this:
require 'minitest/unit'
require 'minitest/autorun'
class FSSessionTest < MiniTest::Unit::TestCase
def test_the_truth
assert true
end
end
The vital part here is require 'minitest/autorun'
which uses at_exit
to run all tests it can find, just before the enclosing script exits. I find this to be the easiest way for running my test suites.
Run tests with Rake
For example, you can create a Rakefile
using Rake::TestTask
which runs all the tests in your test/
directory:
require 'rake'
require 'rake/testtask'
Rake::TestTask.new do |t|
t.pattern = 'tests/**/*_test.rb'
end
Run the tests with
$ rake test
Require tests in a Ruby file
If you frequently only need certain tests, you can also write a test script, something like
require './tests/fs_session_test'
require './tests/resource_test'
require './tests/rest_session_test'
require './tests/server_test'
You could also include require 'minitest/autorun'
at the top of this file to ensure, the tests are run, but i do this at the top of every test file, anyway. Run the suite with
$ ruby test.rb
Result
Both methods give you the same output, for example something like
Run options: --seed 5559
# Running tests:
....
Finished tests in 0.001909s, 2095.3379 tests/s, 2095.3379 assertions/s.
4 tests, 4 assertions, 0 failures, 0 errors, 0 skips
Because mintiest makes use of at_exit
, there is really no need to group the tests before you run them. You never get the output of only one test. Unless, of course you run a test on its own, for example with
$ ruby tests/fs_session_test.rb
Run options: --seed 43007
# Running tests:
.
Finished tests in 0.000672s, 1488.0952 tests/s, 1488.0952 assertions/s.
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
Ruby Minitest: Suite- or Class- level setup?
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.
How to run MiniTest::Unit tests in ordered sequence?
You can use i_suck_and_my_tests_are_order_dependent!()
class method.
class MyTest < MiniTest::Unit::TestCase
i_suck_and_my_tests_are_order_dependent! # <----
def test_1
p 1
end
def test_2
p 2
end
end
But as the name suggest, it's not a good idea to make the tests to be dependant on orders.
Before/After Suite when using Ruby MiniTest
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?
Ruby test suite creation
You need to prefix your test methods with the string test_
. For example:
class TC_HelloWorld < Test::Unit::TestCase
def test_hello # method name updated here
puts "Hello world!"
end
end
This is reflected in the documentation: "Add a method that begins with “test” to your class.".
Using Ruby and Minitest, how do I run the same testcase with different data, controlled only by a list
You could dynamically define the methods.
In the following example, 6 tests are dynamically created (2 tests for each of the 3 values being tested). This means that if anything fails, the other tests still run.
require "minitest/autorun"
class MyTests < MiniTest::Unit::TestCase
['0', '1111111', '2222222'].each do |phone_number|
define_method("test_#{phone_number}_has_7_characters") do
assert_equal(7, phone_number.length)
end
define_method("test_#{phone_number}_starts_with_1") do
assert_equal('1', phone_number[0])
end
end
end
The apply test case gives the following results:
# Running tests:
F..F.F
Finished tests in 0.044004s, 136.3512 tests/s, 136.3512 assertions/s.
1) Failure:
test_0_starts_with_1(MyTests) [stuff.rb:13]:
Expected: "1"
Actual: "0"
2) Failure:
test_0_has_7_characters(MyTests) [stuff.rb:9]:
Expected: 7
Actual: 1
3) Failure:
test_2222222_starts_with_1(MyTests) [stuff.rb:13]:
Expected: "1"
Actual: "2"
6 tests, 6 assertions, 3 failures, 0 errors, 0 skips
Applying the same concept to your tests, I think you want:
class MyTests < MiniTest::Unit::TestCase
listOfPhoneNumbersForTesting.each do |phone|
define_method("test_#{phone}") do
TestPhone.new phone
end
end
end
A similar approach can be taken when using the spec-style tests:
require 'minitest/spec'
require 'minitest/autorun'
describe "my tests" do
['0', '1111111', '2222222'].each do |phone_number|
it "#{phone_number} has 7 characters" do
assert_equal(7, phone_number.length)
end
it "#{phone_number} starts with 1" do
assert_equal('1', phone_number[0])
end
end
end
IMPORTANT: One thing to note is that you need to make sure that the name of the test methods created are unique for each test case.
For example, if you do not put the phone number in the method name, you end up overwriting your previously defined methods. Ultimately this means that only the last phone number gets tested.
This is because MiniTest generates the test methods on the fly and will overwrite already generated test methods, ultimately only using the last .each variable.
Minitest and Test::Unit
Basically, Test::Unit got replaced by MiniTest (which ships with Ruby now). MiniTest tests can be written in the Test::Unit syntax or in the MiniTest::Spec syntax. Mini::Test, as a standalone, doesn't have a future... but MiniTest is faster, smaller, included by default, and has a great future and, IMHO, you should definitely make the switch! Although it is definitely lacking in documentation, as you have found. For the most part, you can just use Test::Unit documentation for help with using MiniTest.
Related Topics
Uninitialized Constant > Actioncable::Server::Configuration::Applicationcable
How to Use the Fetch Method for Nested Hash
How to Get the Destination Url of a Shortened Url Using Ruby
Find Case-Insensitive Word Matches in a Line
Find Where Associated Records Exist
Ruby: What Is the Order of Keys/Values Returned by Hash.Keys and Hash.Values Methods
How to Add a Single Backslash Character to a String in Ruby
How to Dynamically Define a Method as Private
How to Perform Vector Addition in Ruby
Disable Rdoc and Ri Generation by Default for Rubygems 1.8.X
How to Add a Custom Log Level to Logger in Ruby
Ruby 1.9 Doesn't Support Unicode Normalization Yet
How to Add Syntax Highlighting to Sublime Text 2
Man in the Middle (Mitm) Proxy with Https Support
Rake Aborted! Stack Level Too Deep