Creating a Test Suite Using Ruby Minitest

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



Leave a reply



Submit