ruby unit testing at_start not found - ruby

I am using test-unit-2.5.5 with ruby 1.9.3. In http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html#at_start-class_method there is a method called at_start as part of the ruby test::unit module from version 2.5.2. I tried to use it from the examples on the page like so:
class TestAOS < Test::Unit::TestCase
Test::Unit.at_start do
puts "start"
end
Test::Unit.at_exit do
puts "Exit!"
end
But when I run my test I get the following:
NoMethodError: undefined method `at_start' for Test::Unit:Module
TestAOS at unit/TestAOS.rb:8
(root) at unit/TestAOS.rb:7
Do I need to do anything first before this method can be used? I'm new to ruby
When I comment out the at_start bloack and run the test I get a different error for at_exit:
NoMethodError: private method `at_exit' called for Test::Unit:Module
TestAOS at unit/TestAOS.rb:12
(root) at unit/TestAOS.rb:7
A

In the example provided by your link the
Test::Unit.at_start do
puts "start"
end
is called outside of test class. You are calling it from inside of your test class. Just move it outside of your TestAOS

Related

Not able to call method in a gem

This might be an easy question but I was unfortunately not able to find the answer on Google.
Context:
I am working on a project of my own, and I am externalizing some code in a gem (FrenchTaxSystem). It is the first I create a gem and I have difficulties using it properly.
Problem:
When calling a method (like testit) defined in the main file (french_tax_system.rb) of my gem I get a "NoMethodError: undefined method `testit' for FrenchTaxSystem:Module", though I can call constants from this same file (like FISCAL_NB_PARTS_FOR_MARRIED_COUPLE) and it puzzles me.
E.g in IRB I get that when calling a method:
[
And it is the same in my Rspecs tests inside my gem
However when calling a constant I have no error:
Main file in my gem:
french_tax_system.rb
module FrenchTaxSystem
class Error < StandardError; end
# Constants
...
FISCAL_NB_PARTS_FOR_MARRIED_COUPLE = 2
...
# Methods
## Main method
def testit
"test me"
end
end
Gem file structure:
Thank you in advance for your help,
Mth0158
This should work:
module FrenchTaxSystem
def self.testit
"test me"
end
end

Unable to call Ruby mixin instance method from RSpec

Objective:
I want to run a basic RSpec unit test on an instance method of a mixin (module) named Debug. Below are the file contents of the Debug mixin:
Mixin File: ./mixins/debug.rb
module Debug
public
def class_info?
"#{self.class.name}"
end
end
Validate Debug mixin instance methods accessible from RSpec:
When I run irb and include the Debug mixin with commands require_relative './mixins/debug.rb' and include Debug, and then call Debug.class_info? it successfully returns "Module"
Then if I run rspec with the following RSpec unit test to confirm that the RSpec context can access the instance methods of the mixin, the test successfully passes:
RSpec Unit Test Setup #1: ./spec/mixins/debug_spec.rb
require_relative '../../mixins/debug.rb'
RSpec.describe Debug, "#class_info?" do
include Debug
before(:each) do
#class_info_instance_method = Debug.instance_methods[0].to_s
end
context "with mixins" do
it "has class info instance method" do
expect(#class_info_instance_method).to eq "class_info?"
end
end
end
Problem when calling Debug mixin instance method from RSpec:
Lastly, I change the RSpec unit test to be as follows, so instead it actually calls the class_info? instance method of the Debug mixin:
RSpec Unit Test Setup #2: ./spec/mixins/debug_spec.rb
require_relative '../../mixins/debug.rb'
RSpec.describe Debug, "#class_info?" do
include Debug
before(:each) do
#class_info = Debug.class_info?
end
context "with mixins" do
it "shows class info" do
expect(#class_info).to eq "Module"
end
end
end
But now when I run rspec from the command line, why does it return the following error? (Note: even though in the previous RSpec Unit Test Setup #1 that was entirely similar I checked I could successfully access this Debug mixin instance method)
1) Debug#class_info? with mixins shows class info
Failure/Error: #class_info = Debug.class_info?
NoMethodError:
undefined method `class_info?' for Debug:Module
Note: I have shared the above code in my RubyTest GitHub repo.
Setup and References:
My System:
Ruby: ruby 2.3.0p0 (ruby -v)
RSpec: 3.5.4 (rspec -v)
References:
Applying example from Mixins chapter of Programming Ruby book
When you include a module, the methods become instance methods in the included class. Debug.class_info? doesn't work because there is no class method class_info?. I'm also not sure that the way you've included the module in your test is the best way to do it. Would something like this work?
require_relative '../../mixins/debug.rb'
class TestClass
include Debug
end
RSpec.describe Debug, "#class_info?" do
let(:test_instance) { TestClass.new }
context "with mixins" do
it "shows class info" do
expect(test_instance.class_info?).to eq "TestClass"
end
end
end

Upgraded to minitest 5.4.0. Now must* and won't* doesn't work within Minitest::Test subclass, but assert* still works

I have been using the MiniTest that comes with Ruby 2.1 without a problem. I would subclass MiniTest::Unit:TestCase create a couple methods like 'test_simple', and everything just worked. I would use Expectations and Asserts without a problem.
I have upgraded Minitest to 5.4.0 using a gem. Everywhere I use Expectations (musts and wonts) I get a strangle error. Example of the test class.
gem 'minitest'
require "minitest/autorun"
require "rest-client"
require "json"
require "pp"
# require './testcase_addins'
class TestUserKey < Minitest::Test
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
When I run this, the assert line passes without a problem, but must_be line throws this error:
1) Error:
TestUserKey#test_simple:
NoMethodError: undefined method `assert_operator' for nil:NilClass
(eval):4:in `must_be'
user_key_testcase.rb:14:in `test_simple'
The strange part is what is the nil:NilClass in the error can't be nil; it's 0. Even I change the Fixnum to a String, I still get the same error.
If I change the test to a spec test, everything works again. So I can't use Expectations with in Unit Tests? IF that is the case, could someone explain why?
The short answer is that with 5.4.0 your test class must inherit from MiniTest::Spec in order to use expectations.
I tested this on a new ubuntu machine with ruby 2.1.2 installed via RVM:
rvm install ruby-2.1.2
This code works with the stock ruby 2.1.2 (no 5.4.0 minitest gem installed, slightly cleaned up from your example code above):
#!/usr/bin/env ruby
require 'minitest/unit'
require "minitest/autorun"
class TestUserKey < MiniTest::Unit::TestCase
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Running this code works fine. To reproduce the error listed above, install minitest 5.4.0:
gem install minitest -v 5.4.0
Now the code fails with "NoMethodError: undefined method `assert_operator' for nil:NilClass". You now have both versions of minitest installed:
~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/ # stock ruby version of minitest
~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/ # minitest v5.4.0 installed via rubygems
Now that everything is set up, we can dig into what exactly is happening. The expectations are defined with a call to infect_an_assertion, like this:
infect_an_assertion :assert_operator, :must_be, :reverse
For 5.4.0 that call happens in ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/expectations.rb. It's roughly the same in both versions, it just happens in a different place.
infect_an_assertion is also roughly the same for both versions. For :must_be it winds up making this call, which is identical between the two versions of minitest:
MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1])
They're doing some metaprogramming here, the call at runtime will look more like this since meth is set to assert_operator:
MiniTest::Spec.current.assert_operator(...)
The important part is MiniTest::Spec.current. In 5.4.0 this method returns nil, which results in a NoMethodError exception when it tries to call assert_operator on nil.
In the stock minitest from ruby 2.1.2:
Here MiniTest::Spec inherits from MiniTest::Unit::TestCase. TestCase defines the method current and returns a value that was set in the initialize method. You can see this all happening around line 1303 of ~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/unit.rb:
def initialize name # :nodoc:
#__name__ = name
#__io__ = nil
#passed = nil
##current = self # FIX: make thread local
end
def self.current # :nodoc:
##current # FIX: make thread local
end
Therefore, when you inherit from MiniTest::Unit::TestCase in your test class with the stock minitest, current is defined as a method and is guaranteed to return a value when the above call to MiniTest::Spec.current is made. This is why it works in the stock ruby 2.1.2 minitest.
In minitest 5.4.0
In 5.4.0, Minitest::Spec inherits from Minitest::Test, which does not define current (nor do any of its parents). The current method is defined directly on Minitest::Spec. It simply returns Thread.current[:current_spec]:
# line 83 of ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/spec.rb
def self.current # :nodoc:
Thread.current[:current_spec]
end
The value of Thread.current[:current_spec] is set in the Minitest::Spec constructor on line 87 of the same file:
def initialize name # :nodoc:
super
Thread.current[:current_spec] = self
end
The problem is that when your test class inherits from Minitest::Test, the Minitest::Spec constructor never gets called and Thread.current[:current_spec] is never initialized. That means the call in infect_an_assertion to Minitest::Spec.current returns nil, which results in the NoMethodError you're seeing when it tries to call assert_operator on nil. The solution is to make your test class inherit from Minitest::Spec so that the constructor is called and Thread.current[:current_spec] gets a value.
Here is a slightly modified version of the original code that works with minitest 5.4.0:
#!/usr/bin/env ruby
gem 'minitest'
require "minitest/autorun"
class TestUserKey < Minitest::Spec
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Hope this helps!
From the minitest readme, it seems like the must style syntax is a part of the spec syntax, which would require you to use methods like describe and it instead of defining your own unit test methods.

How to run code before each test case in all tests in MiniTest?

I need to run code before each test in all my tests in MiniTest.
Before I did:
MiniTest::Unit::TestCase.add_setup_hook do
...code to run before each test
end
After I upgraded MiniTest to version 4.7.2 it shows the following error:
undefined method `add_setup_hook' for MiniTest::Unit::TestCase:Class (NoMethodError)
I am using Ruby MRI 2.0.0p0.
SOLUTION
module MyMinitestPlugin
def before_setup
super
# ...code to run before all test cases
end
def after_teardown
# ... code to run after all test cases
super
end
end
class MiniTest::Unit::TestCase
include MyMinitestPlugin
end
add_setup_hook was removed in 4.6.0.
https://github.com/seattlerb/minitest/commit/792a480ebeb32983b9150adae575b7c396e2ae63
Use before_setup instead.
I think that you're looking for the setup() method.
If using MiniTest, you can set that in test/test_helper.rb:
class ActiveSupport::TestCase
...
setup do
...code to run before each test
end
end
Update 2019
Don't write a plugin for this, plugins are intended for gems which extend Minitest functionality, not for test authors.
If you write Minitest Specs, you can do the following instead:
class Minitest::Spec
before :each do
[do stuff]
end
end

Ruby undefined method for 'assert' for :class

I'm trying to use the Test::Unit::TestCase API in ruby to do some unit tests but have run into an issue with using assert. I am only trying to call specific methods within a class that uses the Test::Unit::TestCase class but it keeps failing on assert. In my rake file I have:
require 'test_file'
task :manage do
my_app = Test::Unit::TestCase::Unit_Test
my_app.test1
end
And in my test_file.rb I have:
require 'rubygems'
require 'test/unit'
require 'rack/test'
class Unit_Test < Test::Unit::TestCase
include Rack::Test::Methods
# manage tests
def self.test1
browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application))
browser.get '/homepage'
assert browser.last_response.ok?
end
end
Everything works up until I get to the 'assert' statement which says: Undefined method assert for Unit_Test:Class. If I do not make the method a static method than it will run ALL of the methods within the Unit_Test class. I only want to run specific unit tests from my rake file.
What am I missing?
I can't think of a nice way to use assert from a class method because assert is an instance method.
If you want to run just a specific test method you might be better off making the test an instance method and using the name parameter, e.g.:
ruby test_file.rb --name test1
You should be able to invoke that from your rake task.

Resources