I have written some code that makes use of Ruby's defined? keyword.
I would like to test this using RSpec but I cannot think of a way to make the method return something thats undefined for testing purposes.
Here is my test -
my_service = class_double('MyService').as_stubbed_const(transfer_nested_constants: true)
allow(my_service).to receive(:something).and_return(UNDEFINED_HERE)
expect(something_else).to receive(:fail!)
Here is my code -
has_result = false
attempts = 0
until has_result do
result = MyService.something(object)
if defined? result
has_result = true
else
attempts += 1
end
end
Thanks in advance!!
Related
While writing a unit test for following:
def foo()
popen_response = ""
IO.popen(#packaging_cmd, :err=>[:child, :out]) {|io| popen_response = io.read }
rc = $?
#log.debug{"Response from IO.popen() : #{popen_response}. rc: '#{rc}'"}
if rc.exitstatus != 0
#log.error{"Packaging failed. rc: '#{rc}'"}
raise PackagingError.new("Packaging failed. rc: '#{rc}'")
end
end
I'm stuck because I don't know how to mock/stub what $? evaluates to. I can hack around by creating a function that returns $? and mock that function or tinker with teh command passed to IO.popen(), but I wonder if there is any official way in RR that I can use.
I'm using rr with stock Test::Unit::TestCase
require 'test/unit'
require 'rr'
I'm not sure which mocking framework you are using, but in RSpec:
allow_any_instance_of(Process::Status).to receive(:exitstatus).and_return(0)
Here is my code I'm trying to run the method but it keeps on kicking out a NoMethodError: undefined method 'template' for main:Object
Can someone please help?
module Template
attr_accessor :source_template, :req_id
def initialize (source_template, req_id)
#source_template = source_template
#req_id = req_id
end
def self.template(source_template, req_id)
template = String.new(#source_template)
template_split_begin = template.index("e")
template_split_end = template_split_begin + 6
template_part_one =
String.new(self.template[0..(template_split_begin-1)])
template_part_two =
String.new(self.template[template.length..template_split_end])
code = String.new(#req_id)
final_template =
String.new(template_part_one + code + template_part_two)
template_split_begin_alt = template.index("a")
template_split_end_alt = template_split_begin_alt + 9
template_alt =
String.new(self.template[0..(template_split_begin_alt-1)])
template_part_two =
String.new(self.template[template.length..template_split_begin_alt])
altcode = code[5..7] - code[0..4]
final_alt_template =
String.new(template_part_one_alt + altcode + template_part_two_alt)
end
end
sample = "Green", 8
template("Blue", 6)
Ok, I think I need deeper explanation.
You can't get the module instance, thus your initialize method is meaningless. You should use it only with classes.
attr_accessor :source_template, :req_id makes no sense in your code
sample = "Green", 8 is unused variable
You call template("Blue", 6) on an object, not on your module, where it's defined, that's why I said you should use Template.template("Blue", 6)
If you had changed it, you would haven't got this error anymore. But from your code seems like you are missing basic knowledge of the language, so I would recommend you to read some book about Ruby, before diving into coding.
I'm trying to write a custom parser for my cucumber results. In doing so, I want to write rspec tests around it. What I currently have is as follows:
describe 'determine_test_results' do
it 'returns a scenario name as the key of the scenario results, with the scenario_line attached' do
pcr = ParseCucumberJsonReport.new
expected_results = {"I can login successfully"=>{"status"=>"passed", "scenario_line"=>4}}
cucumber_results = JSON.parse(IO.read('example_json_reports/json_passing.json'))
pcr.determine_test_results(cucumber_results[0]).should == expected_results
end
end
The problem is, determine_test_results has a sub method called determine_step_results, which means this is really an integration test between the 2 methods and not a unit test for determine_test_results.
How would I mock out the "response" from determine_step_results?
Assume determine_step_results returns {"status"=>"passed", "scenario_line"=>4}
what I have tried:
pcr.stub(:determine_step_results).and_return({"status"=>"passed", "scenario_line"=>6})
and
allow(pcr).to receive(:determine_step_results).and_return({"status"=>"passed", "scenario_line"=>6})
You could utilize stubs for what you're trying to accomplish. Project: RSpec Mocks 2.3 would be good reading regarding this particular case. I have added some code below as a suggestion.
describe 'determine_test_results' do
it 'returns a scenario name as the key of the scenario results, with the scenario_line attached' do
pcr = ParseCucumberJsonReport.new
expected_results = {"I can login successfully"=>{"status"=>"passed", "scenario_line"=>4}}
# calls on pcr will return expected results every time determine_step_results is called in any method on your pcr object.
pcr.stub!(:determine_step_results).and_return(expected_results)
cucumber_results = JSON.parse(IO.read('example_json_reports/json_passing.json'))
pcr.determine_test_results(cucumber_results[0]).should == expected_results
end
end
If all what determine_test_results does is call determine_step_results, you should not really test it, since it is trivial...
If you do decide to test it, all you need to test is that it calls the delegate function, and returns whatever is passed to it:
describe ParseCucumberJsonReport do
describe '#determine_test_results' do
it 'calls determine_step_results' do
result = double(:result)
input = double(:input)
expect(subject).to receive(:determine_step_results).with(input).and_return(result)
subject.determine_test_results(input).should == result
end
end
end
If it is doing anything more (like adding the result to a larger hash) you can describe it too:
describe ParseCucumberJsonReport do
describe '#determine_test_results' do
it 'calls determine_step_results' do
result = double(:result)
input = double(:input)
expect(subject).to receive(:determine_step_results).with(input).and_return(result)
expect(subject.larger_hash).to receive(:merge).with(result)
subject.determine_test_results(input).should == result
end
end
end
I implemeting async thread manager and I want to pass reference to thread, where it should save the results of his work. And then when all thread finished i will handle all results.
What I need is to know how to work with 'references'.
lets assume I have variable result (or hash[:result1]), I want to pass it to the thread like
def test_func
return 777;
end
def thread_start(result)
Thread.new do
result = test_func;
end
end
and I want is to get following result
result = 555
thread_start(result);
#thread_wait_logic_there
result == 777; #=> true
hash = {:res1 => 555};
thread_start(hash[:res1])
#thread_wait_logic_there
hash[:res1]==777 #=> true
what should I chnage in my code to make it work?
Ruby version is 1.9.3
You can pass entrire hash to function:
def test_func
return 777;
end
def thread_start(hash, key)
Thread.new do
hash[key] = test_func;
end
end
Then this will work:
hash = {:res1 => 555};
thread_start(hash, :res1)
hash[:res1]==777 #=> true
Also if you want to be sure that you getting result after computations finished you must wait for thread, like this:
hash = {:res1 => 555};
thread_start(hash, :res1).join
hash[:res1]==777 #=> true
Edit: Added key,join
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....