I just started learning Ruby last week, so please bear with me on this.
I'm using Ruby 1.9.3. I have problem trying to get my unit test to run, and I've been trying for the past 2 days, but I haven't been able to successfully run my unit test.
Here's the code for my simple calculator class:
class Calc
def initialize
end
def Add(leftOp, rightOp)
return (leftOp + rightOp)
end
def Sub(leftOp, rightOp)
return (leftOp - rightOp)
end
def Div(leftOp, rightOp)
if(rightOp == 0)
raise ArgumentError.new("Divided by 0")
else
return (leftOp / rightOp)
end
def Mult(leftOp, rightOp)
return (leftOp * rightOp)
end
end
myCalc = Calc.new
puts "2 + 3 = " + myCalc.Add(2, 3).to_s
puts "2 - 3 = " + myCalc.Sub(2, 3).to_s
puts "2 * 3 = " + myCalc.Mult(2, 3).to_s
puts "6 / 3 = " + myCalc.Div(6, 3).to_s
puts "10 / 0 = " + myCalc.Div(10, 0).to_s
This works fine. All the outputs are printed out as expected. Now, I want to write a unit test for this class. Below is the code for the unit test:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
require 'Calc'
class Test_Calc < Test::Unit::TestCase
def setup
myCalc = Calc.new
#result_1 = myCalc.Add(5, 8)
#result_2 = myCalc.Sub(9, 15)
#result_3 = myCalc.Mult(8, 6)
#result_4 = myCalc.Div(18, 3)
#result_5 = myCalc.Div(2, 0)
end
def test_Add
assert_equal(#result_1, 13)
end
def test_Sub
assert_equal(#result_2, -6)
end
def test_Mult
assert_equal(#result_3, 48)
end
def test_Div
assert_equal(#result_4, 6)
end
def test_Div_Zero
assert_match("\Divided by 0\", e.message)
end
end
Test::Unit::UI::Console::TestRunner.run(Test_Calc)
When I ran this unit test, it spit out this error
The Calc.rb file is in the very same directory of the test_Calc.rb file. Why doesn't it see it? I even tried to copy the Calc.rb file to the same directory of the "custom_require.rb" file ("lib/ruby/site_ruby/1.9.1/rubygems"), but that didn't help.
After searching all over the web, I learned that Test::Unit has been removed and replaced by MiniTest (!). So, I tried the MiniTest thing as followed:
require 'minitest/unit'
require 'Calc'
class Test_Calc < MiniTest::Unit::TestCase
#Test_Calc definition
end
MiniTest::Unit.autorun
I still got back the exact same error as before, so maybe I was doing something wrong with the MiniTest thing.
I even followed the example from the following site, but it didn't seem to work in my case. Even if I have a fully defined class (Calc.rb), I still got the "Calc - (LoadError)".
http://www.ibm.com/developerworks/opensource/tutorials/os-ruby1/section3.html
After searching all over the web again, I learned that test::unit was available as a gem for backward compatibility, and so I downloaded and install test-unit-2.5.4.gem from the link below:
http://rubygems.org/gems/test-unit
Even after installing the gem, it still didn't work (I checked to ensure that the gem was installed in "Ruby193\lib\ruby\gem\1.9.1\gems"). Ruby still complained that it "cannot load such file -- Calc (LoadError)"
So, how do I run the test unit? What am I missing?
Thank you in advance for your help.
Updated:
After including ".\Calc" as Blaine suggested, I got the following new error message:
Well, at least, it recognizes the Calc class this time, and it started loading the test suite.
First, if the program says it can't find the file, make your require look like this: require './Calc'
Second, make sure you are using the latest version of the minitest gem. You can check this by doing:
gem list
The version will be on the right of the list. As of today the current version is 4.6.1. If your version is not correct, update it by doing:
gem install --version '4.6.1' (or whatever the version is)
Related
Ruby OOP beginner here. Trying to build a simple Vending machine code.
class VendingMachine
# TODO: add relevant getter/setter to this class to make the scenarios work properly.
attr_reader :snack_price_cents, :user_balance_cents
attr_accessor :snack_count
def initialize(snack_price_cents, snack_count)
#user_balance_cents = 0
#snack_count = snack_count
#snack_price_cents = snack_price_cents
end
def insert_coin(input_cents)
#user_balance_cents = user_balance_cents + input_cents if input_cents
end
def buy_snack
if snack_count.zero? || user_balance_cents.zero?
#snack_count = snack_count
else
#snack_count = snack_count - 1
#user_balance_cents = user_balance_cents - snack_price_cents
end
end
end
I am trying to understand what happens to snack_count, user_balance_cents and snack_price_cents when the user pushes a button to buy a snack?
It seems like all is working okay except for the user_balance_cents but I am getting:
should not let you buy a snack if you didn't insert enough money (error path) (FAILED - 1)"
error. Any help?
I would guess that your error here is that you are checking that user_balance_cents is not zero, but you are not checking that it as least snack_price_cents.
i.e. if I put 10c in and try to buy a 50c snack, it will give me it.
This question already has answers here:
What will give me something like ruby readline with a default value?
(6 answers)
Closed 6 years ago.
Let's say I have the following code in Ruby:
print("Enter a filename:")
editableprint("untitled.txt")
filename = gets.chomp!
What would be the function "editableprint" so that "untitled.txt" is part of the input of the user for the gets function? (thus the user can edit the "untitled.txt" string or simply leave it as is")
There are similar questions here and here
However, the solutions there don't seem to work as expected, so it looks this is ruby version or platform dependent?
For example, this does not work for me, but also does not throw an error.
require "readline"
filename = Readline.insert_text("untitled.txt").readline("Enter a filename:")
print filename
But since it looks much better, and should work according to the documentation for ruby >= 2, I am leaving it there for now.
The following works on my system (ruby 2.3.1, OS X)
require "readline"
require 'rb-readline'
module RbReadline
def self.prefill_prompt(str)
#rl_prefill = str
#rl_startup_hook = :rl_prefill_hook
end
def self.rl_prefill_hook
rl_insert_text #rl_prefill if #rl_prefill
#rl_startup_hook = nil
end
end
RbReadline.prefill_prompt("untitled.txt")
str = Readline.readline("Enter a filename:", true)
puts "You entered: #{str}"
I would use vim to edit the file. Vim will save edited files in ~/.viminfo. The last edited file is marked with '0. The pattern of a file entry is 'N N N filename where N stands for a integer.
def editableprint(filename)
system "vi #{filename}"
regex = /(?<='0\s{2}\d\s{2}\d\s{2}).*/
viminfo = File.expand_path("~/.viminfo")
File.read(viminfo).scan(regex).first
end
In order to make this to work you would have to change your code
print("Enter a filename:")
filename = gets.chomp!
filename = "untitled.txt" if filename.emtpy?
edited_filename = editableprint("untitled.txt")
This question sounds stupid, but I never found an answer online to do this.
Assume you have a test suite like this page:
http://en.wikibooks.org/wiki/Ruby_Programming/Unit_testing
or code:
require "simpleNumber"
require "test/unit"
class TestSimpleNumber < Test::Unit::TestCase
def test_simple
assert_equal(4, SimpleNumber.new(2).add(2) )
assert_equal(4, SimpleNumber.new(2).multiply(2) )
end
def test_typecheck
assert_raise( RuntimeError ) { SimpleNumber.new('a') }
end
def test_failure
assert_equal(3, SimpleNumber.new(2).add(2), "Adding doesn't work" )
end
end
Running the code:
>> ruby tc_simpleNumber2.rb
Loaded suite tc_simpleNumber2
Started
F..
Finished in 0.038617 seconds.
1) Failure:
test_failure(TestSimpleNumber) [tc_simpleNumber2.rb:16]:
Adding doesn't work.
<3> expected but was
<4>.
3 tests, 4 assertions, 1 failures, 0 errors
Now, how to use a variable (what kind?) to save the testing results?
e.g., an array like this:
[{:name => 'test_simple', :status => :pass},
{:name => 'test_typecheck', :status => :pass},
{:name => 'test_failure', :status => :fail},]
I am new to testing, but desperate to know the answer...
you need to execute your test script file, that's it, the result will display pass or fails.
Suppose you save file test_unit_to_rspec.rb, after that execute below command
ruby test_unit_to_rspec.rb
Solved the problem with setting a high verbose level, in a test runner call.
http://ruby-doc.org/stdlib-1.8.7/libdoc/test/unit/rdoc/Test/Unit/UI/Console/TestRunner.html
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class MySuperSuite < Test::Unit::TestSuite
def self.suite
suites = self.new("My Super Test Suite")
suites << TestSimpleNumber1
suites << TestSimpleNumber2
return suites
end
end
#run the suite
# Pass an io object
#new(suite, output_level=NORMAL, io=STDOUT)
runner = Test::Unit::UI::Console::TestRunner.new(MySuperSuite, 3, io)
results will be saved in the io stream in a nice format fo each test case.
What about using '-v' (verbose):
ruby test_unit_to_rspec.rb -v
This should show you a lot more information
You can check out another of Nat's posts for a way to capture the results. The short answer to your question is that there is no variable for capturing the results. All you get is:
Loaded suite My Special Tests
Started
..
Finished in 1.000935 seconds.
2 tests, 2 assertions, 0 failures, 0 errors
Which is not very helpful if you want to report to someone else what happened. Nat's other post shows how to wrap the Test::Unit in rspec to get a better result and more flexibility.
class Test::Unit::TestCase
def setup
#id = self.class.to_s()
end
def teardown
#test_result = "pass"
if(#_result.failure_count > 0 || #_result.error_count > 0)
#test_result = "fail"
# making sure no errors/failures exist before the next test case runs.
i = 0
while(i < #_result.failures.length) do
#_result.failures.delete_at(i)
i = i + 1
end
while(i < #_result.errors.length) do
#_result.errors.delete_at(i)
i = i + 1
end
#test_result = "fail"
end # if block ended
puts"#{#id}: #{#test_result}"
end # teardown definition ended
end # class Test::Unit::TestCase ended
Example Output :
test1: Pass
test2: fail
so on....
I'm building a rake task that pulls down a repo, runs some specs and builds a gem if they all pass.
The gemspec file comes with the original checkout of the repo, and I'd like to bump the version whenever the gem is built (i.e. when the task is run). Gem::Specification.load doesn't let me manipulate the attributes of the gemspec since it just returns nil. The only way I've figured out to do this so far is to create a temp gemspec, replace the version line with what I want and mv it over the current gemspec.
However, the file is not updated until (I think) the process exits. The path and file are nominally there, but there is no content in the file itself, it's just blank. When testing in irb, the gemspec's content appears after exiting the session.
Here's the rake task for gem building:
desc "Build new vulnerability tests gem"
task :build_gem do
Process.fork { update_gemspec_version 'foo.gemspec' }
gemspec = Gem::Specification.load('foo.gemspec')
builder = Gem::Builder.new(gemspec)
puts "Building gem from #{gemspec.file_name}"
builder.build
end
(You can see I thought forking the process to run the method would fix the problem, but it just used the original gemspec to build the gem and didn't update anything until the rake task completed.)
And the update_gemspec_version helper method:
def update_gemspec_version(gemspec)
temp_file = Tempfile.new "#{gemspec}"
time = Time.now
minor_rev = 0
base = time.year.to_s + '.' + time.month.to_s + '.' + time.day.to_s
File.open("#{gemspec}", 'r') do |file|
file.each do |line|
if line =~ /^\s*s\.version\s=\s'(\d+\.\d+\.\d+\.(\d+))'$/
if $1 >= base + '.' + minor_rev.to_s
while minor_rev <= $2.to_i
minor_rev += 1
end
replacement = line.gsub($1, base + '.' + minor_rev.to_s)
puts replacement
temp_file.puts replacement
else
replacement = line.gsub($1, base + '.' + minor_rev.to_s)
puts replacement
temp_file.puts replacement
end
else
temp_file.puts line
end
end
end
FileUtils.mv(temp_file.path, File.expand_path("#{gemspec}"))
nil
end
Am I going about this all wrong?
Gem::Specification.load doesn't let me manipulate the attributes of
the gemspec since it just returns nil.
Are you using the latest RubyGems? Gem::Specification.load returns an instance of Gem::Specification if it evaluates the gem spec file successfully... maybe a typo? See https://github.com/rubygems/rubygems/blob/master/lib/rubygems/specification.rb
I am working on a feature for an application that has to run on JRuby. Out of habit I develop on 'Native' Ruby. When I try to run any methods from this class in JRuby I get error messages like:
MissingSourceFile: no such file to load -- serialport
I think the problem lies in in the require 'serialport.so'. Is there a way to make this work in JRuby? Is there another way to require a .so file? Or a gem that can work with JRuby to provide the SerialPort class? I tried installing the ruby-serialport gem but that doesn't seem to install properly (Windows nmake issues).
Here is what my class file looks like:
require 'serialport.so'
class AlphaDisplay
#STATES
SOLID = "b"
ROTATE = "a"
BLINK = "c"
#COLORS
RED = "1"
GREEN = "2"
YELLOW = "3"
ORANGE = "7"
def self.message(address = 00, text = "ICS", color = AlphaDisplay::GREEN, state = AlphaDisplay::SOLID)
address = address.to_s
if address.length == 1
address = "0#{address}"
end
string = 1.chr + 90.chr + address + 2.chr + 65.chr + 65.chr + 27.chr + 26.chr + state + 28.chr + color + text + 4.chr
return string
end
def self.test(address = 00, text = "ICS", color = AlphaDisplay::GREEN, state = AlphaDisplay::SOLID)
sp = SerialPort.new(0, 9600, 8, 1, SerialPort::NONE)
sp.write(message(address,text,color,state))
sp.close
end
end
def SerialPort::new(port, *params)
sp = create(port)
begin
sp.set_modem_params(*params)
rescue
sp.close
raise
end
return sp
end
def SerialPort::open(port, *params)
sp = create(port)
begin
sp.set_modem_params(*params)
if (block_given?)
yield sp
sp.close
return nil
end
rescue
sp.close
raise
end
return sp
end
As far as I know, JRuby doesn't provide any native emulation layer, just the Ruby interpreter in Java. The problem is that ".so" files are UNIX specific and cannot run on Windows without some sort of emulation/translation.
You're better off avoiding Ruby libraries which require native extensions if you're going to use JRuby.