Question

I'm trying to write a custom tool that runs ruby unit tests with my customizations.

What I need it to do is to load a certain TestCase from given file(through require or whatever), and then run it after doing some calculations and initializations.

Problem is, the moment I require "test/unit" and a test case, it runs immediately.

What can I do with this?

Thanks.

Was it helpful?

Solution

Since you're running 1.9 and test/unit in 1.9 is merely a wrapper for MiniTest, the following approach should work:

  • implement your own custom Runner
  • set MiniTest's runner to your custom runner

Something like (shameless plug from EndOfLine Custom Test Runner, adjusted to Ruby 1.9):

fastfailrunner.rb:

require 'test/unit'

class FastFailRunner19 < MiniTest::Unit
  def _run args = []
    puts "fast fail runner" 
  end
end

~

example_test.rb:

require 'test/unit'

class ExampleTest < Test::Unit::TestCase
  def test_assert_equal
    assert_equal 1, 1
  end

  def test_lies
    assert false
  end

  def test_exceptions
    raise Exception, 'Beware the Jubjub bird, and shun the frumious Bandersnatch!'
  end

  def test_truth
    assert true
  end
end

run.rb:

require_relative 'fast_fail_runner'
require_relative 'example_test'

MiniTest::Unit.runner= FastFailRunner19.new

If you run this with

  ruby run.rb

the custom FastFailRunner19 will be used, which does nothing.

OTHER TIPS

What about reading file content as a regular text file and doing eval on its content after you initialize/calculate things you say? It may not be sufficient for your needs and may require manual setup and execution of testing framework.

Like that (I put heredoc instead of reading file). Basically content is just a string containing your test case code.

content = <<TEST_CASE
  class YourTestCase

    def hello
      puts 'Hello from eval'
    end

  end
  YourTestCase.new.hello
TEST_CASE

eval content 

Note: Altough I'd rather not use eval if there is another way. One should be extra careful when evaling code from string manually in any language.

You could collect the test cases you want to deferred its executions and store them in an array. Afterwards you would create a block execution code. For instance:

test_files = ['test/unit/first_test.rb'] #=> Testcases you want to run

test_block = Proc.new {spec_files.each {|f|load f} }  #=> block storing the actual execution of those tests.

Once you're ready to call those testcases you just do test_block.call.

To generalize a bit, when thinking about deferring or delaying code executions, closures are a very elegant and flexible alternative.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top